mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Fix selector parsing.
This commit is contained in:
parent
de06249408
commit
b9d964bcf1
1 changed files with 76 additions and 8 deletions
|
@ -8,7 +8,7 @@ use cssparser::*;
|
||||||
use namespaces::NamespaceMap;
|
use namespaces::NamespaceMap;
|
||||||
|
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Eq, Clone)]
|
||||||
pub struct Selector {
|
pub struct Selector {
|
||||||
compound_selectors: CompoundSelector,
|
compound_selectors: CompoundSelector,
|
||||||
pseudo_element: Option<PseudoElement>,
|
pseudo_element: Option<PseudoElement>,
|
||||||
|
@ -27,7 +27,7 @@ pub enum PseudoElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Eq, Clone)]
|
||||||
pub struct CompoundSelector {
|
pub struct CompoundSelector {
|
||||||
simple_selectors: ~[SimpleSelector],
|
simple_selectors: ~[SimpleSelector],
|
||||||
next: Option<(~CompoundSelector, Combinator)>, // c.next is left of c
|
next: Option<(~CompoundSelector, Combinator)>, // c.next is left of c
|
||||||
|
@ -41,7 +41,7 @@ pub enum Combinator {
|
||||||
LaterSibling, // ~
|
LaterSibling, // ~
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Eq, Clone)]
|
||||||
pub enum SimpleSelector {
|
pub enum SimpleSelector {
|
||||||
IDSelector(~str),
|
IDSelector(~str),
|
||||||
ClassSelector(~str),
|
ClassSelector(~str),
|
||||||
|
@ -66,7 +66,7 @@ pub enum SimpleSelector {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Eq, Clone)]
|
||||||
pub struct AttrSelector {
|
pub struct AttrSelector {
|
||||||
name: ~str,
|
name: ~str,
|
||||||
namespace: Option<~str>,
|
namespace: Option<~str>,
|
||||||
|
@ -192,7 +192,7 @@ fn compute_specificity(mut selector: &CompoundSelector,
|
||||||
static MAX_10BIT: u32 = (1u32 << 10) - 1;
|
static MAX_10BIT: u32 = (1u32 << 10) - 1;
|
||||||
specificity.id_selectors.min(&MAX_10BIT) << 20
|
specificity.id_selectors.min(&MAX_10BIT) << 20
|
||||||
| specificity.class_like_selectors.min(&MAX_10BIT) << 10
|
| specificity.class_like_selectors.min(&MAX_10BIT) << 10
|
||||||
| specificity.id_selectors.min(&MAX_10BIT)
|
| specificity.element_selectors.min(&MAX_10BIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ fn parse_simple_selectors(iter: &mut Iter, namespaces: &NamespaceMap)
|
||||||
match parse_one_simple_selector(iter, namespaces, /* inside_negation = */ false) {
|
match parse_one_simple_selector(iter, namespaces, /* inside_negation = */ false) {
|
||||||
None => return None, // invalid selector
|
None => return None, // invalid selector
|
||||||
Some(None) => break,
|
Some(None) => break,
|
||||||
Some(Some(Left(s))) => simple_selectors.push(s),
|
Some(Some(Left(s))) => { simple_selectors.push(s); empty = false },
|
||||||
Some(Some(Right(p))) => { pseudo_element = Some(p); break },
|
Some(Some(Right(p))) => { pseudo_element = Some(p); break },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -359,8 +359,7 @@ fn parse_qualified_name(iter: &mut Iter, allow_universal: bool, namespaces: &Nam
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(&Delim('|')) => explicit_namespace(iter, allow_universal, Some(~"")),
|
Some(&Delim('|')) => explicit_namespace(iter, allow_universal, Some(~"")),
|
||||||
Some(&IDHash(*)) => default_namespace(namespaces, None),
|
_ => Some(None),
|
||||||
_ => return None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,3 +491,72 @@ fn skip_whitespace(iter: &mut Iter) -> bool {
|
||||||
iter.next();
|
iter.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use cssparser;
|
||||||
|
use namespaces::NamespaceMap;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn parse(input: &str) -> Option<~[Selector]> {
|
||||||
|
parse_selector_list(
|
||||||
|
cssparser::tokenize(input).map(|(v, _)| v).to_owned_vec(),
|
||||||
|
&NamespaceMap::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn specificity(a: u32, b: u32, c: u32) -> u32 {
|
||||||
|
a << 20 | b << 10 | c
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parsing() {
|
||||||
|
assert_eq!(parse(""), None)
|
||||||
|
assert_eq!(parse("e"), Some(~[Selector{
|
||||||
|
compound_selectors: CompoundSelector {
|
||||||
|
simple_selectors: ~[LocalNameSelector(~"e")],
|
||||||
|
next: None,
|
||||||
|
},
|
||||||
|
pseudo_element: None,
|
||||||
|
specificity: specificity(0, 0, 1),
|
||||||
|
}]))
|
||||||
|
assert_eq!(parse(".foo"), Some(~[Selector{
|
||||||
|
compound_selectors: CompoundSelector {
|
||||||
|
simple_selectors: ~[ClassSelector(~"foo")],
|
||||||
|
next: None,
|
||||||
|
},
|
||||||
|
pseudo_element: None,
|
||||||
|
specificity: specificity(0, 1, 0),
|
||||||
|
}]))
|
||||||
|
assert_eq!(parse("#bar"), Some(~[Selector{
|
||||||
|
compound_selectors: CompoundSelector {
|
||||||
|
simple_selectors: ~[IDSelector(~"bar")],
|
||||||
|
next: None,
|
||||||
|
},
|
||||||
|
pseudo_element: None,
|
||||||
|
specificity: specificity(1, 0, 0),
|
||||||
|
}]))
|
||||||
|
assert_eq!(parse("e.foo#bar"), Some(~[Selector{
|
||||||
|
compound_selectors: CompoundSelector {
|
||||||
|
simple_selectors: ~[LocalNameSelector(~"e"),
|
||||||
|
ClassSelector(~"foo"),
|
||||||
|
IDSelector(~"bar")],
|
||||||
|
next: None,
|
||||||
|
},
|
||||||
|
pseudo_element: None,
|
||||||
|
specificity: specificity(1, 1, 1),
|
||||||
|
}]))
|
||||||
|
assert_eq!(parse("e.foo #bar"), Some(~[Selector{
|
||||||
|
compound_selectors: CompoundSelector {
|
||||||
|
simple_selectors: ~[IDSelector(~"bar")],
|
||||||
|
next: Some((~CompoundSelector {
|
||||||
|
simple_selectors: ~[LocalNameSelector(~"e"),
|
||||||
|
ClassSelector(~"foo")],
|
||||||
|
next: None,
|
||||||
|
}, Descendant)),
|
||||||
|
},
|
||||||
|
pseudo_element: None,
|
||||||
|
specificity: specificity(1, 1, 1),
|
||||||
|
}]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue