/rust/registry/src/index.crates.io-1949cf8c6b5b557f/lightningcss-1.0.0-alpha.72/src/rules/property.rs
Line | Count | Source |
1 | | //! The `@property` rule. |
2 | | |
3 | | use super::Location; |
4 | | #[cfg(feature = "visitor")] |
5 | | use crate::visitor::Visit; |
6 | | use crate::{ |
7 | | error::{ParserError, PrinterError}, |
8 | | printer::Printer, |
9 | | properties::custom::TokenList, |
10 | | traits::{Parse, ToCss}, |
11 | | values::{ |
12 | | ident::DashedIdent, |
13 | | syntax::{ParsedComponent, SyntaxString}, |
14 | | }, |
15 | | }; |
16 | | use cssparser::*; |
17 | | |
18 | | /// A [@property](https://drafts.css-houdini.org/css-properties-values-api/#at-property-rule) rule. |
19 | | #[derive(Debug, PartialEq, Clone)] |
20 | 0 | #[cfg_attr(feature = "visitor", derive(Visit))] Unexecuted instantiation: <lightningcss::rules::property::PropertyRule as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::ValueCollector>>::visit_children Unexecuted instantiation: <lightningcss::rules::property::PropertyRule as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::FirstRgbColorCollector>>::visit_children Unexecuted instantiation: <lightningcss::rules::property::PropertyRule as lightningcss::visitor::Visit<_, _>>::visit_children |
21 | | #[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))] |
22 | | #[cfg_attr( |
23 | | feature = "serde", |
24 | | derive(serde::Serialize, serde::Deserialize), |
25 | | serde(rename_all = "camelCase") |
26 | | )] |
27 | | #[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))] |
28 | | pub struct PropertyRule<'i> { |
29 | | /// The name of the custom property to declare. |
30 | | #[cfg_attr(feature = "serde", serde(borrow))] |
31 | | pub name: DashedIdent<'i>, |
32 | | /// A syntax string to specify the grammar for the custom property. |
33 | | #[cfg_attr(feature = "visitor", skip_visit)] |
34 | | pub syntax: SyntaxString, |
35 | | /// Whether the custom property is inherited. |
36 | | #[cfg_attr(feature = "visitor", skip_visit)] |
37 | | pub inherits: bool, |
38 | | /// An optional initial value for the custom property. |
39 | | #[cfg_attr(feature = "visitor", skip_visit)] |
40 | | pub initial_value: Option<ParsedComponent<'i>>, |
41 | | /// The location of the rule in the source file. |
42 | | #[cfg_attr(feature = "visitor", skip_visit)] |
43 | | pub loc: Location, |
44 | | } |
45 | | |
46 | | impl<'i> PropertyRule<'i> { |
47 | 0 | pub(crate) fn parse<'t>( |
48 | 0 | name: DashedIdent<'i>, |
49 | 0 | input: &mut Parser<'i, 't>, |
50 | 0 | loc: Location, |
51 | 0 | ) -> Result<Self, ParseError<'i, ParserError<'i>>> { |
52 | 0 | let mut parser = PropertyRuleDeclarationParser { |
53 | 0 | syntax: None, |
54 | 0 | inherits: None, |
55 | 0 | initial_value: None, |
56 | 0 | }; |
57 | | |
58 | 0 | let mut decl_parser = RuleBodyParser::new(input, &mut parser); |
59 | 0 | while let Some(decl) = decl_parser.next() { |
60 | 0 | match decl { |
61 | 0 | Ok(()) => {} |
62 | 0 | Err((e, _)) => return Err(e), |
63 | | } |
64 | | } |
65 | | |
66 | | // `syntax` and `inherits` are always required. |
67 | 0 | let parser = decl_parser.parser; |
68 | 0 | let syntax = parser |
69 | 0 | .syntax |
70 | 0 | .clone() |
71 | 0 | .ok_or(decl_parser.input.new_custom_error(ParserError::AtRuleBodyInvalid))?; |
72 | 0 | let inherits = parser |
73 | 0 | .inherits |
74 | 0 | .clone() |
75 | 0 | .ok_or(decl_parser.input.new_custom_error(ParserError::AtRuleBodyInvalid))?; |
76 | | |
77 | | // `initial-value` is required unless the syntax is a universal definition. |
78 | 0 | let initial_value = match syntax { |
79 | 0 | SyntaxString::Universal => match parser.initial_value { |
80 | 0 | None => None, |
81 | 0 | Some(val) => { |
82 | 0 | let mut input = ParserInput::new(val); |
83 | 0 | let mut parser = Parser::new(&mut input); |
84 | | |
85 | 0 | if parser.is_exhausted() { |
86 | 0 | Some(ParsedComponent::TokenList(TokenList(vec![]))) |
87 | | } else { |
88 | 0 | Some(syntax.parse_value(&mut parser)?) |
89 | | } |
90 | | } |
91 | | }, |
92 | | _ => { |
93 | 0 | let val = parser |
94 | 0 | .initial_value |
95 | 0 | .ok_or(input.new_custom_error(ParserError::AtRuleBodyInvalid))?; |
96 | 0 | let mut input = ParserInput::new(val); |
97 | 0 | let mut parser = Parser::new(&mut input); |
98 | 0 | Some(syntax.parse_value(&mut parser)?) |
99 | | } |
100 | | }; |
101 | | |
102 | 0 | return Ok(PropertyRule { |
103 | 0 | name, |
104 | 0 | syntax, |
105 | 0 | inherits, |
106 | 0 | initial_value, |
107 | 0 | loc, |
108 | 0 | }); |
109 | 0 | } |
110 | | } |
111 | | |
112 | | impl<'i> ToCss for PropertyRule<'i> { |
113 | 0 | fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> |
114 | 0 | where |
115 | 0 | W: std::fmt::Write, |
116 | | { |
117 | | #[cfg(feature = "sourcemap")] |
118 | | dest.add_mapping(self.loc); |
119 | 0 | dest.write_str("@property ")?; |
120 | 0 | self.name.to_css(dest)?; |
121 | 0 | dest.whitespace()?; |
122 | 0 | dest.write_char('{')?; |
123 | 0 | dest.indent(); |
124 | 0 | dest.newline()?; |
125 | | |
126 | 0 | dest.write_str("syntax:")?; |
127 | 0 | dest.whitespace()?; |
128 | 0 | self.syntax.to_css(dest)?; |
129 | 0 | dest.write_char(';')?; |
130 | 0 | dest.newline()?; |
131 | | |
132 | 0 | dest.write_str("inherits:")?; |
133 | 0 | dest.whitespace()?; |
134 | 0 | match self.inherits { |
135 | 0 | true => dest.write_str("true")?, |
136 | 0 | false => dest.write_str("false")?, |
137 | | } |
138 | | |
139 | 0 | if let Some(initial_value) = &self.initial_value { |
140 | 0 | dest.write_char(';')?; |
141 | 0 | dest.newline()?; |
142 | | |
143 | 0 | dest.write_str("initial-value:")?; |
144 | 0 | dest.whitespace()?; |
145 | 0 | initial_value.to_css(dest)?; |
146 | | |
147 | 0 | if !dest.minify { |
148 | 0 | dest.write_char(';')?; |
149 | 0 | } |
150 | 0 | } |
151 | | |
152 | 0 | dest.dedent(); |
153 | 0 | dest.newline()?; |
154 | 0 | dest.write_char('}') |
155 | 0 | } |
156 | | } |
157 | | |
158 | | pub(crate) struct PropertyRuleDeclarationParser<'i> { |
159 | | syntax: Option<SyntaxString>, |
160 | | inherits: Option<bool>, |
161 | | initial_value: Option<&'i str>, |
162 | | } |
163 | | |
164 | | impl<'i> cssparser::DeclarationParser<'i> for PropertyRuleDeclarationParser<'i> { |
165 | | type Declaration = (); |
166 | | type Error = ParserError<'i>; |
167 | | |
168 | 0 | fn parse_value<'t>( |
169 | 0 | &mut self, |
170 | 0 | name: CowRcStr<'i>, |
171 | 0 | input: &mut cssparser::Parser<'i, 't>, |
172 | 0 | _declaration_start: &ParserState, |
173 | 0 | ) -> Result<Self::Declaration, cssparser::ParseError<'i, Self::Error>> { |
174 | 0 | match_ignore_ascii_case! { &name, |
175 | 0 | "syntax" => { |
176 | 0 | let syntax = SyntaxString::parse(input)?; |
177 | 0 | self.syntax = Some(syntax); |
178 | | }, |
179 | 0 | "inherits" => { |
180 | 0 | let location = input.current_source_location(); |
181 | 0 | let ident = input.expect_ident()?; |
182 | 0 | let inherits = match_ignore_ascii_case! {&*ident, |
183 | 0 | "true" => true, |
184 | 0 | "false" => false, |
185 | 0 | _ => return Err(location.new_unexpected_token_error( |
186 | 0 | cssparser::Token::Ident(ident.clone()) |
187 | 0 | )) |
188 | | }; |
189 | 0 | self.inherits = Some(inherits); |
190 | | }, |
191 | 0 | "initial-value" => { |
192 | | // Buffer the value into a string. We will parse it later. |
193 | 0 | let start = input.position(); |
194 | 0 | while input.next().is_ok() {} |
195 | 0 | let initial_value = input.slice_from(start); |
196 | 0 | self.initial_value = Some(initial_value); |
197 | | }, |
198 | 0 | _ => return Err(input.new_custom_error(ParserError::InvalidDeclaration)) |
199 | | } |
200 | | |
201 | 0 | return Ok(()); |
202 | 0 | } |
203 | | } |
204 | | |
205 | | /// Default methods reject all at rules. |
206 | | impl<'i> AtRuleParser<'i> for PropertyRuleDeclarationParser<'i> { |
207 | | type Prelude = (); |
208 | | type AtRule = (); |
209 | | type Error = ParserError<'i>; |
210 | | } |
211 | | |
212 | | impl<'i> QualifiedRuleParser<'i> for PropertyRuleDeclarationParser<'i> { |
213 | | type Prelude = (); |
214 | | type QualifiedRule = (); |
215 | | type Error = ParserError<'i>; |
216 | | } |
217 | | |
218 | | impl<'i> RuleBodyItemParser<'i, (), ParserError<'i>> for PropertyRuleDeclarationParser<'i> { |
219 | 0 | fn parse_qualified(&self) -> bool { |
220 | 0 | false |
221 | 0 | } |
222 | | |
223 | 0 | fn parse_declarations(&self) -> bool { |
224 | 0 | true |
225 | 0 | } |
226 | | } |