mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +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 {
|
||||
compound_selectors: CompoundSelector,
|
||||
pseudo_element: Option<PseudoElement>,
|
||||
// specificity: u32,
|
||||
specificity: u32,
|
||||
}
|
||||
|
||||
pub static STYLE_ATTRIBUTE_SPECIFICITY: u32 = 1 << 31;
|
||||
|
||||
|
||||
pub enum PseudoElement {
|
||||
Before,
|
||||
After,
|
||||
|
@ -127,6 +130,7 @@ fn parse_selector(iter: &mut Iter, namespaces: &NamespaceMap)
|
|||
}
|
||||
}
|
||||
let selector = Selector{
|
||||
specificity: compute_specificity(&compound, &pseudo_element),
|
||||
compound_selectors: compound,
|
||||
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
|
||||
fn parse_simple_selectors(iter: &mut Iter, namespaces: &NamespaceMap)
|
||||
-> Option<(~[SimpleSelector], Option<PseudoElement>)> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue