swc_css_ast/
selector.rs

1use is_macro::Is;
2use string_enum::StringEnum;
3use swc_atoms::Atom;
4use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span};
5
6use crate::{Delimiter, Ident, ListOfComponentValues, Str, TokenAndSpan};
7
8#[ast_node("SelectorList")]
9#[derive(Eq, Hash, EqIgnoreSpan)]
10pub struct SelectorList {
11    pub span: Span,
12    pub children: Vec<ComplexSelector>,
13}
14
15impl Take for SelectorList {
16    fn dummy() -> Self {
17        Self {
18            span: Take::dummy(),
19            children: Take::dummy(),
20        }
21    }
22}
23
24#[ast_node("SelectorList")]
25#[derive(Eq, Hash, EqIgnoreSpan)]
26pub struct ForgivingSelectorList {
27    pub span: Span,
28    pub children: Vec<ForgivingComplexSelector>,
29}
30
31#[ast_node]
32#[derive(Eq, Hash, Is, EqIgnoreSpan)]
33pub enum ForgivingComplexSelector {
34    #[tag("ComplexSelector")]
35    ComplexSelector(ComplexSelector),
36    #[tag("ListOfComponentValues")]
37    ListOfComponentValues(ListOfComponentValues),
38}
39
40#[ast_node("CompoundSelectorList")]
41#[derive(Eq, Hash, EqIgnoreSpan)]
42pub struct CompoundSelectorList {
43    pub span: Span,
44    pub children: Vec<CompoundSelector>,
45}
46
47#[ast_node("RelativeSelectorList")]
48#[derive(Eq, Hash, EqIgnoreSpan)]
49pub struct RelativeSelectorList {
50    pub span: Span,
51    pub children: Vec<RelativeSelector>,
52}
53
54#[ast_node("ForgivingRelativeSelectorList")]
55#[derive(Eq, Hash, EqIgnoreSpan)]
56pub struct ForgivingRelativeSelectorList {
57    pub span: Span,
58    pub children: Vec<ForgivingRelativeSelector>,
59}
60
61#[ast_node]
62#[derive(Eq, Hash, Is, EqIgnoreSpan)]
63pub enum ForgivingRelativeSelector {
64    #[tag("RelativeSelector")]
65    RelativeSelector(RelativeSelector),
66    #[tag("ListOfComponentValues")]
67    ListOfComponentValues(ListOfComponentValues),
68}
69
70#[ast_node("ComplexSelector")]
71#[derive(Eq, Hash, EqIgnoreSpan)]
72pub struct ComplexSelector {
73    pub span: Span,
74    pub children: Vec<ComplexSelectorChildren>,
75}
76
77impl Take for ComplexSelector {
78    fn dummy() -> Self {
79        Self {
80            span: Take::dummy(),
81            children: Take::dummy(),
82        }
83    }
84}
85
86#[ast_node]
87#[derive(Eq, Hash, Is, EqIgnoreSpan)]
88pub enum ComplexSelectorChildren {
89    #[tag("CompoundSelector")]
90    CompoundSelector(CompoundSelector),
91    #[tag("Combinator")]
92    Combinator(Combinator),
93}
94
95#[ast_node("RelativeSelector")]
96#[derive(Eq, Hash, EqIgnoreSpan)]
97pub struct RelativeSelector {
98    pub span: Span,
99    pub combinator: Option<Combinator>,
100    pub selector: ComplexSelector,
101}
102
103/// e.g. `foo.c1.c2`
104#[ast_node("CompoundSelector")]
105#[derive(Eq, Hash, EqIgnoreSpan)]
106pub struct CompoundSelector {
107    pub span: Span,
108    /// "&"
109    pub nesting_selector: Option<NestingSelector>,
110    pub type_selector: Option<Box<TypeSelector>>,
111    pub subclass_selectors: Vec<SubclassSelector>,
112}
113
114#[ast_node("Combinator")]
115#[derive(Eq, Hash, EqIgnoreSpan)]
116pub struct Combinator {
117    pub span: Span,
118    pub value: CombinatorValue,
119}
120
121#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)]
122#[cfg_attr(
123    feature = "rkyv",
124    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
125)]
126#[cfg_attr(
127    feature = "rkyv",
128    rkyv(serialize_bounds(__S: rkyv::ser::Writer + rkyv::ser::Allocator,
129        __S::Error: rkyv::rancor::Source))
130)]
131#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))]
132#[cfg_attr(feature = "rkyv", repr(u32))]
133pub enum CombinatorValue {
134    /// ` `
135    Descendant,
136
137    /// `+`
138    NextSibling,
139
140    /// `>`
141    Child,
142
143    /// `~`
144    LaterSibling,
145
146    /// `||`
147    Column,
148}
149
150#[ast_node("NestingSelector")]
151#[derive(Eq, Hash, EqIgnoreSpan)]
152pub struct NestingSelector {
153    pub span: Span,
154}
155
156#[ast_node]
157#[derive(Eq, Hash, Is, EqIgnoreSpan)]
158pub enum TypeSelector {
159    #[tag("TagNameSelector")]
160    TagName(TagNameSelector),
161    #[tag("UniversalSelector")]
162    Universal(UniversalSelector),
163}
164
165#[ast_node("TagNameSelector")]
166#[derive(Eq, Hash, EqIgnoreSpan)]
167pub struct TagNameSelector {
168    pub span: Span,
169    pub name: WqName,
170}
171
172#[ast_node("UniversalSelector")]
173#[derive(Eq, Hash, EqIgnoreSpan)]
174pub struct UniversalSelector {
175    pub span: Span,
176    pub prefix: Option<NamespacePrefix>,
177}
178
179#[ast_node("NamespacePrefix")]
180#[derive(Eq, Hash, EqIgnoreSpan)]
181pub struct NamespacePrefix {
182    pub span: Span,
183    pub namespace: Option<Namespace>,
184}
185
186#[ast_node]
187#[derive(Eq, Hash, Is, EqIgnoreSpan)]
188pub enum Namespace {
189    #[tag("NamedNamespace")]
190    Named(NamedNamespace),
191    #[tag("AnyNamespace")]
192    Any(AnyNamespace),
193}
194
195#[ast_node("NamedNamespace")]
196#[derive(Eq, Hash, EqIgnoreSpan)]
197pub struct NamedNamespace {
198    pub span: Span,
199    pub name: Ident,
200}
201
202#[ast_node("AnyNamespace")]
203#[derive(Eq, Hash, EqIgnoreSpan)]
204pub struct AnyNamespace {
205    pub span: Span,
206}
207
208#[ast_node("WqName")]
209#[derive(Eq, Hash, EqIgnoreSpan)]
210pub struct WqName {
211    pub span: Span,
212    pub prefix: Option<NamespacePrefix>,
213    pub value: Ident,
214}
215
216#[ast_node]
217#[derive(Eq, Hash, Is, EqIgnoreSpan)]
218pub enum SubclassSelector {
219    #[tag("IdSelector")]
220    Id(IdSelector),
221
222    #[tag("ClassSelector")]
223    Class(ClassSelector),
224
225    #[tag("AttributeSelector")]
226    Attribute(Box<AttributeSelector>),
227
228    #[tag("PseudoClassSelector")]
229    PseudoClass(PseudoClassSelector),
230
231    #[tag("PseudoElementSelector")]
232    PseudoElement(PseudoElementSelector),
233}
234
235#[ast_node("IdSelector")]
236#[derive(Eq, Hash, EqIgnoreSpan)]
237pub struct IdSelector {
238    pub span: Span,
239    /// Does not include `#`
240    pub text: Ident,
241}
242
243#[ast_node("ClassSelector")]
244#[derive(Eq, Hash, EqIgnoreSpan)]
245pub struct ClassSelector {
246    pub span: Span,
247    /// Does not include `.`
248    pub text: Ident,
249}
250
251#[ast_node("AttributeSelector")]
252#[derive(Eq, Hash, EqIgnoreSpan)]
253pub struct AttributeSelector {
254    pub span: Span,
255    pub name: WqName,
256    pub matcher: Option<AttributeSelectorMatcher>,
257    pub value: Option<AttributeSelectorValue>,
258    pub modifier: Option<AttributeSelectorModifier>,
259}
260
261#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Is, EqIgnoreSpan)]
262#[cfg_attr(
263    feature = "rkyv",
264    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
265)]
266#[cfg_attr(feature = "rkyv", derive(bytecheck::CheckBytes))]
267#[cfg_attr(feature = "rkyv", repr(u32))]
268//#[cfg_attr(
269//    feature = "rkyv",
270//    archive(bound(serialize = "__S: rkyv::ser::ScratchSpace +
271// rkyv::ser::Serializer"))
272//)]
273pub enum AttributeSelectorMatcherValue {
274    /// `=`
275    Equals,
276
277    /// `~=`
278    Tilde,
279
280    /// `|=`
281    Bar,
282
283    /// `^=`
284    Caret,
285
286    /// `$=`
287    Dollar,
288
289    /// `*=`
290    Asterisk,
291}
292
293#[ast_node("AttributeSelectorMatcher")]
294#[derive(Eq, Hash, EqIgnoreSpan)]
295pub struct AttributeSelectorMatcher {
296    pub span: Span,
297    pub value: AttributeSelectorMatcherValue,
298}
299
300#[ast_node]
301#[derive(Eq, Hash, Is, EqIgnoreSpan)]
302pub enum AttributeSelectorValue {
303    #[tag("String")]
304    Str(Str),
305
306    #[tag("Ident")]
307    Ident(Ident),
308}
309
310#[ast_node("AttributeSelectorModifier")]
311#[derive(Eq, Hash, EqIgnoreSpan)]
312pub struct AttributeSelectorModifier {
313    pub span: Span,
314    pub value: Ident,
315}
316
317#[ast_node("PseudoClassSelector")]
318#[derive(Eq, Hash, EqIgnoreSpan)]
319pub struct PseudoClassSelector {
320    pub span: Span,
321    pub name: Ident,
322    pub children: Option<Vec<PseudoClassSelectorChildren>>,
323}
324
325#[ast_node]
326#[derive(Eq, Hash, Is, EqIgnoreSpan)]
327pub enum PseudoClassSelectorChildren {
328    #[tag("TokenAndSpan")]
329    PreservedToken(TokenAndSpan),
330
331    #[tag("AnPlusB")]
332    AnPlusB(AnPlusB),
333
334    #[tag("Ident")]
335    Ident(Ident),
336
337    #[tag("Str")]
338    Str(Str),
339
340    #[tag("Delimiter")]
341    Delimiter(Delimiter),
342
343    #[tag("ComplexSelector")]
344    ComplexSelector(ComplexSelector),
345
346    #[tag("SelectorList")]
347    SelectorList(SelectorList),
348
349    #[tag("ForgivingSelectorList")]
350    ForgivingSelectorList(ForgivingSelectorList),
351
352    #[tag("CompoundSelectorList")]
353    CompoundSelectorList(CompoundSelectorList),
354
355    #[tag("RelativeSelectorList")]
356    RelativeSelectorList(RelativeSelectorList),
357
358    #[tag("ForgivingRelativeSelectorList")]
359    ForgivingRelativeSelectorList(ForgivingRelativeSelectorList),
360
361    #[tag("CompoundSelector")]
362    CompoundSelector(CompoundSelector),
363}
364
365#[ast_node]
366#[derive(Eq, Hash, Is, EqIgnoreSpan)]
367pub enum AnPlusB {
368    #[tag("Ident")]
369    Ident(Ident),
370    #[tag("AnPlusBNotation")]
371    AnPlusBNotation(AnPlusBNotation),
372}
373
374#[ast_node("AnPlusBNotation")]
375#[derive(Eq, Hash, EqIgnoreSpan)]
376pub struct AnPlusBNotation {
377    pub span: Span,
378    pub a: Option<i32>,
379    pub a_raw: Option<Atom>,
380    pub b: Option<i32>,
381    pub b_raw: Option<Atom>,
382}
383
384#[ast_node("PseudoElementSelector")]
385#[derive(Eq, Hash, EqIgnoreSpan)]
386pub struct PseudoElementSelector {
387    pub span: Span,
388    pub name: Ident,
389    pub children: Option<Vec<PseudoElementSelectorChildren>>,
390}
391
392#[ast_node]
393#[derive(Eq, Hash, Is, EqIgnoreSpan)]
394pub enum PseudoElementSelectorChildren {
395    #[tag("TokenAndSpan")]
396    PreservedToken(TokenAndSpan),
397    #[tag("Ident")]
398    Ident(Ident),
399    #[tag("CompoundSelector")]
400    CompoundSelector(CompoundSelector),
401    #[tag("CustomHighlightName")]
402    CustomHighlightName(CustomHighlightName),
403}
404
405#[ast_node("CustomHighlightName")]
406#[derive(Eq, Hash)]
407pub struct CustomHighlightName {
408    pub span: Span,
409
410    pub value: Atom,
411    pub raw: Option<Atom>,
412}
413
414impl EqIgnoreSpan for CustomHighlightName {
415    fn eq_ignore_span(&self, other: &Self) -> bool {
416        self.value == other.value
417    }
418}