Skip to main content

hpx_browser/css_selectors/
ast.rs

1/// A comma-separated list of complex selectors.
2pub type SelectorList = Vec<Selector>;
3
4/// A complete selector. Components are stored right-to-left for efficient matching.
5#[derive(Debug, Clone, PartialEq)]
6pub struct Selector {
7    pub(crate) components: Vec<Component>,
8    pub(crate) specificity: Specificity,
9}
10
11impl Selector {
12    pub fn new(components: Vec<Component>, specificity: Specificity) -> Self {
13        Self {
14            components,
15            specificity,
16        }
17    }
18
19    pub fn components(&self) -> &[Component] {
20        &self.components
21    }
22
23    pub fn specificity(&self) -> Specificity {
24        self.specificity
25    }
26}
27
28/// A component of a selector.
29#[derive(Debug, Clone, PartialEq)]
30pub enum Component {
31    Combinator(Combinator),
32    Simple(SimpleSelector),
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum Combinator {
37    Descendant,
38    Child,
39    NextSibling,
40    SubsequentSibling,
41}
42
43#[derive(Debug, Clone, PartialEq)]
44pub enum SimpleSelector {
45    Type(String),
46    Universal,
47    Id(String),
48    Class(String),
49    Attribute {
50        name: String,
51        operator: Option<AttributeOperator>,
52        value: Option<String>,
53        case_sensitivity: CaseSensitivity,
54    },
55    PseudoClass(PseudoClass),
56    PseudoElement(PseudoElement),
57    Nesting,
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub enum AttributeOperator {
62    Exact,
63    Includes,
64    DashMatch,
65    Prefix,
66    Suffix,
67    Substring,
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum CaseSensitivity {
72    Default,
73    CaseInsensitive,
74    CaseSensitive,
75}
76
77#[derive(Debug, Clone, PartialEq)]
78pub enum PseudoClass {
79    AnyLink,
80    Link,
81    Visited,
82    Target,
83    Hover,
84    Active,
85    Focus,
86    FocusWithin,
87    FocusVisible,
88    Enabled,
89    Disabled,
90    ReadWrite,
91    ReadOnly,
92    Checked,
93    Default,
94    Indeterminate,
95    Required,
96    Optional,
97    Valid,
98    Invalid,
99    InRange,
100    OutOfRange,
101    PlaceholderShown,
102    Root,
103    Empty,
104    FirstChild,
105    LastChild,
106    OnlyChild,
107    FirstOfType,
108    LastOfType,
109    OnlyOfType,
110    NthChild(NthExpr, Option<SelectorList>),
111    NthLastChild(NthExpr, Option<SelectorList>),
112    NthOfType(NthExpr),
113    NthLastOfType(NthExpr),
114    Lang(Vec<String>),
115    Is(SelectorList),
116    Not(SelectorList),
117    Where(SelectorList),
118    Has(Vec<RelativeSelector>),
119}
120
121/// An+B expression for nth-child etc.
122#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123pub struct NthExpr {
124    pub a: i32,
125    pub b: i32,
126}
127
128impl NthExpr {
129    pub fn matches(&self, index: i32) -> bool {
130        if self.a == 0 {
131            return index == self.b;
132        }
133        let diff = index - self.b;
134        if self.a > 0 {
135            diff >= 0 && diff % self.a == 0
136        } else {
137            diff <= 0 && diff % self.a == 0
138        }
139    }
140}
141
142#[derive(Debug, Clone, PartialEq)]
143pub struct RelativeSelector {
144    pub combinator: Option<Combinator>,
145    pub selector: Selector,
146}
147
148#[derive(Debug, Clone, PartialEq)]
149pub enum PseudoElement {
150    Before,
151    After,
152    FirstLine,
153    FirstLetter,
154    Placeholder,
155    Selection,
156    Part(Vec<String>),
157    Slotted(Box<Selector>),
158    Custom(String),
159}
160
161/// Specificity as (a, b, c) per Selectors ยง17.
162#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
163pub struct Specificity {
164    pub a: u32,
165    pub b: u32,
166    pub c: u32,
167}
168
169impl Specificity {
170    pub fn new(a: u32, b: u32, c: u32) -> Self {
171        Self { a, b, c }
172    }
173
174    pub fn max(self, other: Self) -> Self {
175        if self >= other { self } else { other }
176    }
177}
178
179impl std::ops::Add for Specificity {
180    type Output = Self;
181    fn add(self, rhs: Self) -> Self {
182        Self {
183            a: self.a + rhs.a,
184            b: self.b + rhs.b,
185            c: self.c + rhs.c,
186        }
187    }
188}
189
190impl std::ops::AddAssign for Specificity {
191    fn add_assign(&mut self, rhs: Self) {
192        self.a += rhs.a;
193        self.b += rhs.b;
194        self.c += rhs.c;
195    }
196}