Handle pseudo elements like ::before

This commit is contained in:
ConnorSkees 2020-02-02 15:06:46 -05:00
parent 89060a0e83
commit ee44982198
2 changed files with 49 additions and 23 deletions

View File

@ -20,6 +20,7 @@ impl Display for Selector {
SelectorKind::Whitespace => continue, SelectorKind::Whitespace => continue,
SelectorKind::Attribute(_) SelectorKind::Attribute(_)
| SelectorKind::Pseudo(_) | SelectorKind::Pseudo(_)
| SelectorKind::PseudoElement(_)
| SelectorKind::PseudoParen(..) | SelectorKind::PseudoParen(..)
| SelectorKind::Class | SelectorKind::Class
| SelectorKind::Id | SelectorKind::Id
@ -31,6 +32,7 @@ impl Display for Selector {
match iter.peek() { match iter.peek() {
Some(SelectorKind::Attribute(_)) Some(SelectorKind::Attribute(_))
| Some(SelectorKind::Pseudo(_)) | Some(SelectorKind::Pseudo(_))
| Some(SelectorKind::PseudoElement(_))
| Some(SelectorKind::PseudoParen(..)) | Some(SelectorKind::PseudoParen(..))
| Some(SelectorKind::Class) | Some(SelectorKind::Class)
| Some(SelectorKind::Id) | Some(SelectorKind::Id)
@ -83,6 +85,8 @@ pub(crate) enum SelectorKind {
Attribute(Attribute), Attribute(Attribute),
/// Pseudo selector: `:hover` /// Pseudo selector: `:hover`
Pseudo(String), Pseudo(String),
/// Pseudo element selector: `::before`
PseudoElement(String),
/// Pseudo selector with additional parens: `:any(h1, h2, h3, h4, h5, h6)` /// Pseudo selector with additional parens: `:any(h1, h2, h3, h4, h5, h6)`
PseudoParen(String, Vec<TokenKind>), PseudoParen(String, Vec<TokenKind>),
/// Use the super selector: `&.red` /// Use the super selector: `&.red`
@ -122,6 +126,7 @@ impl Display for SelectorKind {
SelectorKind::Preceding => write!(f, " ~ "), SelectorKind::Preceding => write!(f, " ~ "),
SelectorKind::Attribute(attr) => write!(f, "{}", attr), SelectorKind::Attribute(attr) => write!(f, "{}", attr),
SelectorKind::Pseudo(s) => write!(f, ":{}", s), SelectorKind::Pseudo(s) => write!(f, ":{}", s),
SelectorKind::PseudoElement(s) => write!(f, "::{}", s),
SelectorKind::PseudoParen(s, toks) => write!( SelectorKind::PseudoParen(s, toks) => write!(
f, f,
":{}({})", ":{}({})",
@ -212,11 +217,9 @@ impl<'a> SelectorParser<'a> {
} }
fn consume_pseudo_selector(&mut self, tokens: &'_ mut Peekable<IntoIter<Token>>) { fn consume_pseudo_selector(&mut self, tokens: &'_ mut Peekable<IntoIter<Token>>) {
if let Some(Token { if let Some(tok) = tokens.next() {
kind: TokenKind::Ident(s), match tok.kind {
.. TokenKind::Ident(s) => {
}) = tokens.next()
{
if let Some(Token { if let Some(Token {
kind: TokenKind::Symbol(Symbol::OpenParen), kind: TokenKind::Symbol(Symbol::OpenParen),
.. ..
@ -236,8 +239,18 @@ impl<'a> SelectorParser<'a> {
} else { } else {
self.selectors.push(SelectorKind::Pseudo(s)) self.selectors.push(SelectorKind::Pseudo(s))
} }
} else { }
todo!("expected ident after `:` in selector") TokenKind::Symbol(Symbol::Colon) => {
if let Some(Token {
kind: TokenKind::Ident(s),
..
}) = tokens.next()
{
self.selectors.push(SelectorKind::PseudoElement(s))
}
}
_ => todo!("expected ident or `:` after `:` in selector"),
}
} }
} }

View File

@ -106,6 +106,19 @@ test!(
selector_pseudo_el_descendant, selector_pseudo_el_descendant,
":pseudo a {\n color: red;\n}\n" ":pseudo a {\n color: red;\n}\n"
); );
test!(selector_pseudoelement, "::before {\n color: red;\n}\n");
test!(
selector_el_and_pseudoelement,
"a::before {\n color: red;\n}\n"
);
test!(
selector_el_pseudoelement_descendant,
"a ::before {\n color: red;\n}\n"
);
test!(
selector_pseudoelement_el_descendant,
"::before a {\n color: red;\n}\n"
);
test!( test!(
selector_pseudo_paren_comma, selector_pseudo_paren_comma,
":pseudo(a, b, c) {\n color: red;\n}\n" ":pseudo(a, b, c) {\n color: red;\n}\n"