mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Add selector specificity.
This commit is contained in:
parent
af2f90fe74
commit
cc302053ed
1 changed files with 55 additions and 1 deletions
56
selectors.rs
56
selectors.rs
|
@ -7,9 +7,12 @@ use stylesheets::NamespaceMap;
|
||||||
pub struct Selector {
|
pub struct Selector {
|
||||||
compound_selectors: CompoundSelector,
|
compound_selectors: CompoundSelector,
|
||||||
pseudo_element: Option<PseudoElement>,
|
pseudo_element: Option<PseudoElement>,
|
||||||
// specificity: u32,
|
specificity: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub static STYLE_ATTRIBUTE_SPECIFICITY: u32 = 1 << 31;
|
||||||
|
|
||||||
|
|
||||||
pub enum PseudoElement {
|
pub enum PseudoElement {
|
||||||
Before,
|
Before,
|
||||||
After,
|
After,
|
||||||
|
@ -127,6 +130,7 @@ fn parse_selector(iter: &mut Iter, namespaces: &NamespaceMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let selector = Selector{
|
let selector = Selector{
|
||||||
|
specificity: compute_specificity(&compound, &pseudo_element),
|
||||||
compound_selectors: compound,
|
compound_selectors: compound,
|
||||||
pseudo_element: pseudo_element,
|
pseudo_element: pseudo_element,
|
||||||
};
|
};
|
||||||
|
@ -134,6 +138,56 @@ fn parse_selector(iter: &mut Iter, namespaces: &NamespaceMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn compute_specificity(mut selector: &CompoundSelector,
|
||||||
|
pseudo_element: &Option<PseudoElement>) -> u32 {
|
||||||
|
struct Specificity {
|
||||||
|
id_selectors: u32,
|
||||||
|
class_like_selectors: u32,
|
||||||
|
element_selectors: u32,
|
||||||
|
}
|
||||||
|
let mut specificity = Specificity {
|
||||||
|
id_selectors: 0,
|
||||||
|
class_like_selectors: 0,
|
||||||
|
element_selectors: 0,
|
||||||
|
};
|
||||||
|
if pseudo_element.is_some() { specificity.element_selectors += 1 }
|
||||||
|
|
||||||
|
simple_selectors_specificity(selector.simple_selectors, &mut specificity);
|
||||||
|
loop {
|
||||||
|
match selector.next {
|
||||||
|
None => break,
|
||||||
|
Some((ref next_selector, _)) => {
|
||||||
|
selector = &**next_selector;
|
||||||
|
simple_selectors_specificity(selector.simple_selectors, &mut specificity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simple_selectors_specificity(simple_selectors: &[SimpleSelector],
|
||||||
|
specificity: &mut Specificity) {
|
||||||
|
for simple_selector in simple_selectors.iter() {
|
||||||
|
match simple_selector {
|
||||||
|
&LocalNameSelector{_} => specificity.element_selectors += 1,
|
||||||
|
&IDSelector(_) => specificity.id_selectors += 1,
|
||||||
|
&ClassSelector(_)
|
||||||
|
| &AttrExists(_) | &AttrEqual(_, _) | &AttrIncludes(_, _) | &AttrDashMatch(_, _)
|
||||||
|
| &AttrPrefixMatch(_, _) | &AttrSubstringMatch(_, _) | &AttrSuffixMatch(_, _)
|
||||||
|
| &Empty | &Root | &Lang(_)
|
||||||
|
=> specificity.class_like_selectors += 1,
|
||||||
|
&NamespaceSelector(_) => (),
|
||||||
|
&Negation(ref negated)
|
||||||
|
=> simple_selectors_specificity(negated.as_slice(), specificity),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MAX_10BIT: u32 = (1u32 << 10) - 1;
|
||||||
|
specificity.id_selectors.min(&MAX_10BIT) << 20
|
||||||
|
| specificity.class_like_selectors.min(&MAX_10BIT) << 10
|
||||||
|
| specificity.id_selectors.min(&MAX_10BIT)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// None means invalid selector
|
// None means invalid selector
|
||||||
fn parse_simple_selectors(iter: &mut Iter, namespaces: &NamespaceMap)
|
fn parse_simple_selectors(iter: &mut Iter, namespaces: &NamespaceMap)
|
||||||
-> Option<(~[SimpleSelector], Option<PseudoElement>)> {
|
-> Option<(~[SimpleSelector], Option<PseudoElement>)> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue