Handle pseudo selectors with arguments
This commit is contained in:
parent
6746ac1619
commit
c73be13024
@ -75,7 +75,7 @@ impl Css {
|
|||||||
} else {
|
} else {
|
||||||
self.blocks[self.idx + self.inner_rulesets - 1].push_style(s)
|
self.blocks[self.idx + self.inner_rulesets - 1].push_style(s)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Stmt::MultilineComment(s) => {
|
Stmt::MultilineComment(s) => {
|
||||||
if self.idx == 0 {
|
if self.idx == 0 {
|
||||||
self.blocks.push(Toplevel::MultilineComment(s));
|
self.blocks.push(Toplevel::MultilineComment(s));
|
||||||
|
@ -3,11 +3,7 @@ use crate::StyleSheetParser;
|
|||||||
pub struct Importer {}
|
pub struct Importer {}
|
||||||
|
|
||||||
impl Importer {
|
impl Importer {
|
||||||
pub fn import(path: &str) {
|
pub fn import(path: &str) {}
|
||||||
|
|
||||||
}
|
fn find_files() {}
|
||||||
|
|
||||||
fn find_files() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -40,6 +40,8 @@ impl<'a> Iterator for Lexer<'a> {
|
|||||||
',' => symbol!(self, Comma),
|
',' => symbol!(self, Comma),
|
||||||
'.' => symbol!(self, Period),
|
'.' => symbol!(self, Period),
|
||||||
';' => symbol!(self, SemiColon),
|
';' => symbol!(self, SemiColon),
|
||||||
|
'(' => symbol!(self, OpenParen),
|
||||||
|
')' => symbol!(self, CloseParen),
|
||||||
'+' => symbol!(self, Plus),
|
'+' => symbol!(self, Plus),
|
||||||
'~' => symbol!(self, Tilde),
|
'~' => symbol!(self, Tilde),
|
||||||
'\'' => symbol!(self, SingleQuote),
|
'\'' => symbol!(self, SingleQuote),
|
||||||
|
25
src/main.rs
25
src/main.rs
@ -538,6 +538,31 @@ mod test_css {
|
|||||||
selector_pseudo_el_descendant,
|
selector_pseudo_el_descendant,
|
||||||
":pseudo a {\n color: red;\n}\n"
|
":pseudo a {\n color: red;\n}\n"
|
||||||
);
|
);
|
||||||
|
test!(
|
||||||
|
selector_pseudo_paren_comma,
|
||||||
|
":pseudo(a, b, c) {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
selector_pseudo_paren_space,
|
||||||
|
":pseudo(a b c) {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
selector_el_pseudo_paren_and,
|
||||||
|
"a:pseudo(a, b, c) {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
selector_el_pseudo_paren_descendant,
|
||||||
|
"a :pseudo(a, b, c) {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
selector_pseudo_paren_el_descendant,
|
||||||
|
":pseudo(a, b, c) a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
selector_pseudo_paren_el_nested,
|
||||||
|
"a {\n :pseudo(a, b, c) {\n color: red;\n }\n}\n",
|
||||||
|
"a :pseudo(a, b, c) {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
|
||||||
test!(basic_style, "a {\n color: red;\n}\n");
|
test!(basic_style, "a {\n color: red;\n}\n");
|
||||||
test!(two_styles, "a {\n color: red;\n color: blue;\n}\n");
|
test!(two_styles, "a {\n color: red;\n color: blue;\n}\n");
|
||||||
|
@ -3,6 +3,7 @@ use crate::{Token, TokenKind};
|
|||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::iter::Peekable;
|
use std::iter::Peekable;
|
||||||
use std::slice::Iter;
|
use std::slice::Iter;
|
||||||
|
use std::string::ToString;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Selector(pub Vec<SelectorKind>);
|
pub struct Selector(pub Vec<SelectorKind>);
|
||||||
@ -25,6 +26,7 @@ impl Display for Selector {
|
|||||||
SelectorKind::Whitespace => continue,
|
SelectorKind::Whitespace => continue,
|
||||||
SelectorKind::Attribute(_)
|
SelectorKind::Attribute(_)
|
||||||
| SelectorKind::Pseudo(_)
|
| SelectorKind::Pseudo(_)
|
||||||
|
| SelectorKind::PseudoParen(..)
|
||||||
| SelectorKind::Class
|
| SelectorKind::Class
|
||||||
| SelectorKind::Id
|
| SelectorKind::Id
|
||||||
| SelectorKind::Universal
|
| SelectorKind::Universal
|
||||||
@ -34,6 +36,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::PseudoParen(..))
|
||||||
| Some(SelectorKind::Class)
|
| Some(SelectorKind::Class)
|
||||||
| Some(SelectorKind::Id)
|
| Some(SelectorKind::Id)
|
||||||
| Some(SelectorKind::Universal)
|
| Some(SelectorKind::Universal)
|
||||||
@ -73,6 +76,8 @@ pub enum SelectorKind {
|
|||||||
Attribute(Attribute),
|
Attribute(Attribute),
|
||||||
/// Pseudo selector: `:hover`
|
/// Pseudo selector: `:hover`
|
||||||
Pseudo(String),
|
Pseudo(String),
|
||||||
|
/// Pseudo selector with additional parens: `:any(h1, h2, h3, h4, h5, h6)`
|
||||||
|
PseudoParen(String, Vec<TokenKind>),
|
||||||
/// Use the super selector: `&.red`
|
/// Use the super selector: `&.red`
|
||||||
Super,
|
Super,
|
||||||
/// Used to signify no selector (when there is no super_selector of a rule)
|
/// Used to signify no selector (when there is no super_selector of a rule)
|
||||||
@ -94,6 +99,12 @@ 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::PseudoParen(s, toks) => write!(
|
||||||
|
f,
|
||||||
|
":{}({})",
|
||||||
|
s,
|
||||||
|
toks.iter().map(ToString::to_string).collect::<String>()
|
||||||
|
),
|
||||||
SelectorKind::Super | SelectorKind::None => write!(f, ""),
|
SelectorKind::Super | SelectorKind::None => write!(f, ""),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,6 +188,36 @@ impl<'a> SelectorParser<'a> {
|
|||||||
Selector(v)
|
Selector(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn consume_pseudo_selector(&mut self) -> Option<SelectorKind> {
|
||||||
|
if let Some(Token {
|
||||||
|
kind: TokenKind::Ident(s),
|
||||||
|
..
|
||||||
|
}) = self.tokens.next()
|
||||||
|
{
|
||||||
|
if let Some(Token {
|
||||||
|
kind: TokenKind::Symbol(Symbol::OpenParen),
|
||||||
|
..
|
||||||
|
}) = self.tokens.peek()
|
||||||
|
{
|
||||||
|
self.tokens.next();
|
||||||
|
let mut toks = Vec::new();
|
||||||
|
while let Some(Token { kind, .. }) = self.tokens.peek() {
|
||||||
|
if kind == &TokenKind::Symbol(Symbol::CloseParen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let tok = self.tokens.next().unwrap();
|
||||||
|
toks.push(tok.kind.clone());
|
||||||
|
}
|
||||||
|
self.tokens.next();
|
||||||
|
Some(SelectorKind::PseudoParen(s.clone(), toks))
|
||||||
|
} else {
|
||||||
|
Some(SelectorKind::Pseudo(s.clone()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
todo!("expected ident after `:` in selector")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn consume_selector(&mut self) -> Option<SelectorKind> {
|
fn consume_selector(&mut self) -> Option<SelectorKind> {
|
||||||
if self.devour_whitespace() {
|
if self.devour_whitespace() {
|
||||||
if let Some(&&Token {
|
if let Some(&&Token {
|
||||||
@ -194,17 +235,7 @@ impl<'a> SelectorParser<'a> {
|
|||||||
TokenKind::Ident(tok) => SelectorKind::Element(tok.clone()),
|
TokenKind::Ident(tok) => SelectorKind::Element(tok.clone()),
|
||||||
TokenKind::Symbol(Symbol::Period) => SelectorKind::Class,
|
TokenKind::Symbol(Symbol::Period) => SelectorKind::Class,
|
||||||
TokenKind::Symbol(Symbol::Hash) => SelectorKind::Id,
|
TokenKind::Symbol(Symbol::Hash) => SelectorKind::Id,
|
||||||
TokenKind::Symbol(Symbol::Colon) => {
|
TokenKind::Symbol(Symbol::Colon) => return self.consume_pseudo_selector(),
|
||||||
if let Some(Token {
|
|
||||||
kind: TokenKind::Ident(s),
|
|
||||||
..
|
|
||||||
}) = self.tokens.next()
|
|
||||||
{
|
|
||||||
SelectorKind::Pseudo(s.clone())
|
|
||||||
} else {
|
|
||||||
todo!("expected ident after `:` in selector")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TokenKind::Symbol(Symbol::Comma) => SelectorKind::Multiple,
|
TokenKind::Symbol(Symbol::Comma) => SelectorKind::Multiple,
|
||||||
TokenKind::Symbol(Symbol::Gt) => SelectorKind::ImmediateChild,
|
TokenKind::Symbol(Symbol::Gt) => SelectorKind::ImmediateChild,
|
||||||
TokenKind::Symbol(Symbol::Plus) => SelectorKind::Following,
|
TokenKind::Symbol(Symbol::Plus) => SelectorKind::Following,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user