/rust/registry/src/index.crates.io-1949cf8c6b5b557f/lightningcss-1.0.0-alpha.72/src/values/ident.rs
Line | Count | Source |
1 | | //! CSS identifiers. |
2 | | |
3 | | use crate::error::{ParserError, PrinterError}; |
4 | | use crate::printer::Printer; |
5 | | use crate::properties::css_modules::Specifier; |
6 | | use crate::traits::{Parse, ParseWithOptions, ToCss}; |
7 | | use crate::values::string::CowArcStr; |
8 | | #[cfg(feature = "visitor")] |
9 | | use crate::visitor::Visit; |
10 | | use cssparser::*; |
11 | | use smallvec::SmallVec; |
12 | | use std::borrow::Borrow; |
13 | | use std::ops::Deref; |
14 | | |
15 | | use super::string::impl_string_type; |
16 | | |
17 | | /// A CSS [`<custom-ident>`](https://www.w3.org/TR/css-values-4/#custom-idents). |
18 | | /// |
19 | | /// Custom idents are author defined, and allow any valid identifier except the |
20 | | /// [CSS-wide keywords](https://www.w3.org/TR/css-values-4/#css-wide-keywords). |
21 | | /// They may be renamed to include a hash when compiled as part of a CSS module. |
22 | | #[derive(Debug, Clone, Eq, Hash)] |
23 | 0 | #[cfg_attr(feature = "visitor", derive(Visit))] Unexecuted instantiation: <lightningcss::values::ident::CustomIdent as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::ValueCollector>>::visit_children Unexecuted instantiation: <lightningcss::values::ident::CustomIdent as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::FirstRgbColorCollector>>::visit_children Unexecuted instantiation: <lightningcss::values::ident::CustomIdent as lightningcss::visitor::Visit<_, _>>::visit_children |
24 | | #[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))] |
25 | | #[cfg_attr(feature = "visitor", visit(visit_custom_ident, CUSTOM_IDENTS))] |
26 | | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent))] |
27 | | #[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))] |
28 | | pub struct CustomIdent<'i>(#[cfg_attr(feature = "serde", serde(borrow))] pub CowArcStr<'i>); |
29 | | |
30 | | impl<'i> Parse<'i> for CustomIdent<'i> { |
31 | 138k | fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> { |
32 | 138k | let location = input.current_source_location(); |
33 | 138k | let ident = input.expect_ident()?; |
34 | 97.9k | let valid = match_ignore_ascii_case! { &ident, |
35 | 97.9k | "initial" | "inherit" | "unset" | "default" | "revert" | "revert-layer" => false, |
36 | 97.9k | _ => true |
37 | | }; |
38 | | |
39 | 97.9k | if !valid { |
40 | 18 | return Err(location.new_unexpected_token_error(Token::Ident(ident.clone()))); |
41 | 97.9k | } |
42 | | |
43 | 97.9k | Ok(CustomIdent(ident.into())) |
44 | 138k | } |
45 | | } |
46 | | |
47 | | impl<'i> ToCss for CustomIdent<'i> { |
48 | 0 | fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> |
49 | 0 | where |
50 | 0 | W: std::fmt::Write, |
51 | | { |
52 | 0 | self.to_css_with_options(dest, true) |
53 | 0 | } |
54 | | } |
55 | | |
56 | | impl<'i> CustomIdent<'i> { |
57 | | /// Write the custom ident to CSS. |
58 | 0 | pub(crate) fn to_css_with_options<W>( |
59 | 0 | &self, |
60 | 0 | dest: &mut Printer<W>, |
61 | 0 | enabled_css_modules: bool, |
62 | 0 | ) -> Result<(), PrinterError> |
63 | 0 | where |
64 | 0 | W: std::fmt::Write, |
65 | | { |
66 | 0 | let css_module_custom_idents_enabled = enabled_css_modules |
67 | 0 | && dest |
68 | 0 | .css_module |
69 | 0 | .as_mut() |
70 | 0 | .map_or(false, |css_module| css_module.config.custom_idents); |
71 | 0 | dest.write_ident(&self.0, css_module_custom_idents_enabled) |
72 | 0 | } |
73 | | } |
74 | | |
75 | | /// A list of CSS [`<custom-ident>`](https://www.w3.org/TR/css-values-4/#custom-idents) values. |
76 | | pub type CustomIdentList<'i> = SmallVec<[CustomIdent<'i>; 1]>; |
77 | | |
78 | | /// The `none` keyword, or a space-separated list of custom idents. |
79 | | #[derive(Debug, Clone, PartialEq, Default)] |
80 | 0 | #[cfg_attr(feature = "visitor", derive(Visit))] Unexecuted instantiation: <lightningcss::values::ident::NoneOrCustomIdentList as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::ValueCollector>>::visit_children Unexecuted instantiation: <lightningcss::values::ident::NoneOrCustomIdentList as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::FirstRgbColorCollector>>::visit_children Unexecuted instantiation: <lightningcss::values::ident::NoneOrCustomIdentList as lightningcss::visitor::Visit<_, _>>::visit_children |
81 | | #[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))] |
82 | | #[cfg_attr( |
83 | | feature = "serde", |
84 | | derive(serde::Serialize, serde::Deserialize), |
85 | | serde(rename_all = "kebab-case") |
86 | | )] |
87 | | #[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))] |
88 | | pub enum NoneOrCustomIdentList<'i> { |
89 | | /// None. |
90 | | #[default] |
91 | | None, |
92 | | /// A list of idents. |
93 | | #[cfg_attr(feature = "serde", serde(borrow, untagged))] |
94 | | Idents(SmallVec<[CustomIdent<'i>; 1]>), |
95 | | } |
96 | | |
97 | | impl<'i> Parse<'i> for NoneOrCustomIdentList<'i> { |
98 | 14 | fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> { |
99 | 14 | let mut types = SmallVec::new(); |
100 | | loop { |
101 | 29 | if let Ok(ident) = input.try_parse(CustomIdent::parse) { |
102 | 15 | if ident == "none" { |
103 | 0 | if types.is_empty() { |
104 | 0 | return Ok(NoneOrCustomIdentList::None); |
105 | | } else { |
106 | 0 | return Err(input.new_custom_error(ParserError::InvalidValue)); |
107 | | } |
108 | 15 | } |
109 | | |
110 | 15 | types.push(ident); |
111 | | } else { |
112 | 14 | return Ok(NoneOrCustomIdentList::Idents(types)); |
113 | | } |
114 | | } |
115 | 14 | } |
116 | | } |
117 | | |
118 | | impl<'i> ToCss for NoneOrCustomIdentList<'i> { |
119 | 0 | fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> |
120 | 0 | where |
121 | 0 | W: std::fmt::Write, |
122 | | { |
123 | 0 | match self { |
124 | 0 | NoneOrCustomIdentList::None => dest.write_str("none"), |
125 | 0 | NoneOrCustomIdentList::Idents(types) => { |
126 | 0 | let mut first = true; |
127 | 0 | for ident in types { |
128 | 0 | if !first { |
129 | 0 | dest.write_char(' ')?; |
130 | 0 | } else { |
131 | 0 | first = false; |
132 | 0 | } |
133 | 0 | ident.to_css(dest)?; |
134 | | } |
135 | 0 | Ok(()) |
136 | | } |
137 | | } |
138 | 0 | } |
139 | | } |
140 | | |
141 | | /// A CSS [`<dashed-ident>`](https://www.w3.org/TR/css-values-4/#dashed-idents) declaration. |
142 | | /// |
143 | | /// Dashed idents are used in cases where an identifier can be either author defined _or_ CSS-defined. |
144 | | /// Author defined idents must start with two dash characters ("--") or parsing will fail. |
145 | | #[derive(Debug, Clone, Eq, Hash)] |
146 | 0 | #[cfg_attr(feature = "visitor", derive(Visit))] Unexecuted instantiation: <lightningcss::values::ident::DashedIdent as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::ValueCollector>>::visit_children Unexecuted instantiation: <lightningcss::values::ident::DashedIdent as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::FirstRgbColorCollector>>::visit_children Unexecuted instantiation: <lightningcss::values::ident::DashedIdent as lightningcss::visitor::Visit<_, _>>::visit_children |
147 | | #[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))] |
148 | | #[cfg_attr(feature = "visitor", visit(visit_dashed_ident, DASHED_IDENTS))] |
149 | | #[cfg_attr(feature = "serde", derive(serde::Serialize), serde(transparent))] |
150 | | #[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))] |
151 | | pub struct DashedIdent<'i>(#[cfg_attr(feature = "serde", serde(borrow))] pub CowArcStr<'i>); |
152 | | |
153 | | impl<'i> Parse<'i> for DashedIdent<'i> { |
154 | 82.8k | fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> { |
155 | 82.8k | let location = input.current_source_location(); |
156 | 82.8k | let ident = input.expect_ident()?; |
157 | 27.6k | if !ident.starts_with("--") { |
158 | 18.5k | return Err(location.new_unexpected_token_error(Token::Ident(ident.clone()))); |
159 | 9.06k | } |
160 | | |
161 | 9.06k | Ok(DashedIdent(ident.into())) |
162 | 82.8k | } |
163 | | } |
164 | | |
165 | | impl<'i> ToCss for DashedIdent<'i> { |
166 | 0 | fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> |
167 | 0 | where |
168 | 0 | W: std::fmt::Write, |
169 | | { |
170 | 0 | dest.write_dashed_ident(&self.0, true) |
171 | 0 | } |
172 | | } |
173 | | |
174 | | #[cfg(feature = "serde")] |
175 | | impl<'i, 'de: 'i> serde::Deserialize<'de> for DashedIdent<'i> { |
176 | | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
177 | | where |
178 | | D: serde::Deserializer<'de>, |
179 | | { |
180 | | let ident = CowArcStr::deserialize(deserializer)?; |
181 | | if !ident.starts_with("--") { |
182 | | return Err(serde::de::Error::custom("Dashed idents must start with --")); |
183 | | } |
184 | | |
185 | | Ok(DashedIdent(ident)) |
186 | | } |
187 | | } |
188 | | |
189 | | /// A CSS [`<dashed-ident>`](https://www.w3.org/TR/css-values-4/#dashed-idents) reference. |
190 | | /// |
191 | | /// Dashed idents are used in cases where an identifier can be either author defined _or_ CSS-defined. |
192 | | /// Author defined idents must start with two dash characters ("--") or parsing will fail. |
193 | | /// |
194 | | /// In CSS modules, when the `dashed_idents` option is enabled, the identifier may be followed by the |
195 | | /// `from` keyword and an argument indicating where the referenced identifier is declared (e.g. a filename). |
196 | | #[derive(Debug, Clone, PartialEq)] |
197 | 0 | #[cfg_attr(feature = "visitor", derive(Visit))] Unexecuted instantiation: <lightningcss::values::ident::DashedIdentReference as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::ValueCollector>>::visit_children Unexecuted instantiation: <lightningcss::values::ident::DashedIdentReference as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::FirstRgbColorCollector>>::visit_children Unexecuted instantiation: <lightningcss::values::ident::DashedIdentReference as lightningcss::visitor::Visit<_, _>>::visit_children |
198 | | #[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))] |
199 | | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] |
200 | | #[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))] |
201 | | pub struct DashedIdentReference<'i> { |
202 | | /// The referenced identifier. |
203 | | #[cfg_attr(feature = "serde", serde(borrow))] |
204 | | pub ident: DashedIdent<'i>, |
205 | | /// CSS modules extension: the filename where the variable is defined. |
206 | | /// Only enabled when the CSS modules `dashed_idents` option is turned on. |
207 | | pub from: Option<Specifier<'i>>, |
208 | | } |
209 | | |
210 | | impl<'i> ParseWithOptions<'i> for DashedIdentReference<'i> { |
211 | 29.4k | fn parse_with_options<'t>( |
212 | 29.4k | input: &mut Parser<'i, 't>, |
213 | 29.4k | options: &crate::stylesheet::ParserOptions, |
214 | 29.4k | ) -> Result<Self, ParseError<'i, ParserError<'i>>> { |
215 | 29.4k | let ident = DashedIdent::parse(input)?; |
216 | | |
217 | 9.06k | let from = match &options.css_modules { |
218 | 8.61k | Some(config) if config.dashed_idents => { |
219 | 0 | if input.try_parse(|input| input.expect_ident_matching("from")).is_ok() { |
220 | 0 | Some(Specifier::parse(input)?) |
221 | | } else { |
222 | 0 | None |
223 | | } |
224 | | } |
225 | 9.06k | _ => None, |
226 | | }; |
227 | | |
228 | 9.06k | Ok(DashedIdentReference { ident, from }) |
229 | 29.4k | } |
230 | | } |
231 | | |
232 | | impl<'i> ToCss for DashedIdentReference<'i> { |
233 | 0 | fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> |
234 | 0 | where |
235 | 0 | W: std::fmt::Write, |
236 | | { |
237 | 0 | match &mut dest.css_module { |
238 | 0 | Some(css_module) if css_module.config.dashed_idents => { |
239 | 0 | if let Some(name) = css_module.reference_dashed(&self.ident.0, &self.from, dest.loc.source_index) { |
240 | 0 | dest.write_str("--")?; |
241 | 0 | serialize_name(&name, dest)?; |
242 | 0 | return Ok(()); |
243 | 0 | } |
244 | | } |
245 | 0 | _ => {} |
246 | | } |
247 | | |
248 | 0 | dest.write_dashed_ident(&self.ident.0, false) |
249 | 0 | } |
250 | | } |
251 | | |
252 | | /// A CSS [`<ident>`](https://www.w3.org/TR/css-values-4/#css-css-identifier). |
253 | | #[derive(Debug, Clone, Eq, Hash, Default)] |
254 | 0 | #[cfg_attr(feature = "visitor", derive(Visit))] Unexecuted instantiation: <lightningcss::values::ident::Ident as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::ValueCollector>>::visit_children Unexecuted instantiation: <lightningcss::values::ident::Ident as lightningcss::visitor::Visit<lightningcss::parser::DefaultAtRule, fallow_extract::css_metrics::FirstRgbColorCollector>>::visit_children Unexecuted instantiation: <lightningcss::values::ident::Ident as lightningcss::visitor::Visit<_, _>>::visit_children |
255 | | #[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))] |
256 | | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent))] |
257 | | #[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))] |
258 | | pub struct Ident<'i>(#[cfg_attr(feature = "serde", serde(borrow))] pub CowArcStr<'i>); |
259 | | |
260 | | impl<'i> Parse<'i> for Ident<'i> { |
261 | 15.1k | fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> { |
262 | 15.1k | let ident = input.expect_ident()?; |
263 | 7.87k | Ok(Ident(ident.into())) |
264 | 15.1k | } |
265 | | } |
266 | | |
267 | | impl<'i> ToCss for Ident<'i> { |
268 | 0 | fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> |
269 | 0 | where |
270 | 0 | W: std::fmt::Write, |
271 | | { |
272 | 0 | serialize_identifier(&self.0, dest)?; |
273 | 0 | Ok(()) |
274 | 0 | } |
275 | | } |
276 | | |
277 | | impl<'i> cssparser::ToCss for Ident<'i> { |
278 | 0 | fn to_css<W>(&self, dest: &mut W) -> std::fmt::Result |
279 | 0 | where |
280 | 0 | W: std::fmt::Write, |
281 | | { |
282 | 0 | serialize_identifier(&self.0, dest) |
283 | 0 | } |
284 | | } |
285 | | |
286 | | impl_string_type!(Ident); |
287 | | impl_string_type!(CustomIdent); |
288 | | impl_string_type!(DashedIdent); |