Handle pseudo elements like ::before
This commit is contained in:
parent
89060a0e83
commit
ee44982198
@ -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,32 +217,40 @@ 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 {
|
||||||
{
|
kind: TokenKind::Symbol(Symbol::OpenParen),
|
||||||
if let Some(Token {
|
..
|
||||||
kind: TokenKind::Symbol(Symbol::OpenParen),
|
}) = tokens.peek()
|
||||||
..
|
{
|
||||||
}) = tokens.peek()
|
tokens.next();
|
||||||
{
|
let mut toks = Vec::new();
|
||||||
tokens.next();
|
while let Some(Token { kind, .. }) = tokens.peek() {
|
||||||
let mut toks = Vec::new();
|
if kind == &TokenKind::Symbol(Symbol::CloseParen) {
|
||||||
while let Some(Token { kind, .. }) = tokens.peek() {
|
break;
|
||||||
if kind == &TokenKind::Symbol(Symbol::CloseParen) {
|
}
|
||||||
break;
|
let tok = tokens.next().unwrap();
|
||||||
|
toks.push(tok.kind);
|
||||||
|
}
|
||||||
|
tokens.next();
|
||||||
|
self.selectors.push(SelectorKind::PseudoParen(s, toks))
|
||||||
|
} else {
|
||||||
|
self.selectors.push(SelectorKind::Pseudo(s))
|
||||||
}
|
}
|
||||||
let tok = tokens.next().unwrap();
|
|
||||||
toks.push(tok.kind);
|
|
||||||
}
|
}
|
||||||
tokens.next();
|
TokenKind::Symbol(Symbol::Colon) => {
|
||||||
self.selectors.push(SelectorKind::PseudoParen(s, toks))
|
if let Some(Token {
|
||||||
} else {
|
kind: TokenKind::Ident(s),
|
||||||
self.selectors.push(SelectorKind::Pseudo(s))
|
..
|
||||||
|
}) = tokens.next()
|
||||||
|
{
|
||||||
|
self.selectors.push(SelectorKind::PseudoElement(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => todo!("expected ident or `:` after `:` in selector"),
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
todo!("expected ident after `:` in selector")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user