Implement & only inside selectors
This commit is contained in:
parent
ebfeb35341
commit
97958b01a7
24
src/main.rs
24
src/main.rs
@ -22,7 +22,8 @@
|
|||||||
clippy::too_many_lines,
|
clippy::too_many_lines,
|
||||||
clippy::integer_arithmetic,
|
clippy::integer_arithmetic,
|
||||||
clippy::missing_errors_doc,
|
clippy::missing_errors_doc,
|
||||||
clippy::let_underscore_must_use
|
clippy::let_underscore_must_use,
|
||||||
|
clippy::module_name_repetitions
|
||||||
)]
|
)]
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
@ -593,4 +594,25 @@ mod test_css {
|
|||||||
"// a { color: red }\na {\n height: 1 1px;\n}\n",
|
"// a { color: red }\na {\n height: 1 1px;\n}\n",
|
||||||
"a {\n height: 1 1px;\n}\n"
|
"a {\n height: 1 1px;\n}\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test!(
|
||||||
|
outer_ampersand,
|
||||||
|
"a, b {\n& c {\n color: red;\n}\n}\n",
|
||||||
|
"a c, b c {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
inner_ampersand,
|
||||||
|
"a, b {\na & c {\n color: red;\n}\n}\n",
|
||||||
|
"a a c, a b c {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
ampersand_multiple_whitespace,
|
||||||
|
" a , b {\n&c {\n color: red;\n}\n}\n",
|
||||||
|
"ac, bc {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
ampersand_alone,
|
||||||
|
"a, b {\n& {\n color: red;\n}\n}\n",
|
||||||
|
"a, b {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ impl Display for Selector {
|
|||||||
| Some(SelectorKind::Id)
|
| Some(SelectorKind::Id)
|
||||||
| Some(SelectorKind::Universal)
|
| Some(SelectorKind::Universal)
|
||||||
| Some(SelectorKind::Element(_)) => {
|
| Some(SelectorKind::Element(_)) => {
|
||||||
write!(f, " {}", iter.next().expect("already peeked here"))?;
|
write!(f, " ")?;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ pub enum SelectorKind {
|
|||||||
/// Pseudo selector: `:hover`
|
/// Pseudo selector: `:hover`
|
||||||
Pseudo(String),
|
Pseudo(String),
|
||||||
/// 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)
|
||||||
None,
|
None,
|
||||||
Whitespace,
|
Whitespace,
|
||||||
@ -94,8 +94,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::Super => write!(f, "{}"),
|
SelectorKind::Super | SelectorKind::None => write!(f, ""),
|
||||||
SelectorKind::None => write!(f, ""),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,6 +134,17 @@ mod test_selector_display {
|
|||||||
)),
|
)),
|
||||||
"a c"
|
"a c"
|
||||||
);
|
);
|
||||||
|
test_selector_display!(
|
||||||
|
keeps_one_whitespace_with_three_els,
|
||||||
|
Selector((
|
||||||
|
Element("a".to_string()),
|
||||||
|
Whitespace,
|
||||||
|
Element("a".to_string()),
|
||||||
|
Whitespace,
|
||||||
|
Element("c".to_string()),
|
||||||
|
)),
|
||||||
|
"a a c"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SelectorParser<'a> {
|
struct SelectorParser<'a> {
|
||||||
@ -154,15 +164,29 @@ impl<'a> SelectorParser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn all_selectors(&mut self) -> Selector {
|
fn all_selectors(&mut self) -> Selector {
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::with_capacity(self.tokens.len());
|
||||||
while let Some(s) = self.consume_selector() {
|
while let Some(s) = self.consume_selector() {
|
||||||
v.push(s);
|
v.push(s);
|
||||||
}
|
}
|
||||||
|
while let Some(x) = v.pop() {
|
||||||
|
if x != SelectorKind::Whitespace {
|
||||||
|
v.push(x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
Selector(v)
|
Selector(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
kind: TokenKind::Symbol(Symbol::Comma),
|
||||||
|
..
|
||||||
|
}) = self.tokens.peek()
|
||||||
|
{
|
||||||
|
self.tokens.next();
|
||||||
|
return Some(SelectorKind::Multiple);
|
||||||
|
}
|
||||||
return Some(SelectorKind::Whitespace);
|
return Some(SelectorKind::Whitespace);
|
||||||
}
|
}
|
||||||
if let Some(Token { kind, .. }) = self.tokens.next() {
|
if let Some(Token { kind, .. }) = self.tokens.next() {
|
||||||
@ -186,7 +210,7 @@ impl<'a> SelectorParser<'a> {
|
|||||||
TokenKind::Symbol(Symbol::Plus) => SelectorKind::Following,
|
TokenKind::Symbol(Symbol::Plus) => SelectorKind::Following,
|
||||||
TokenKind::Symbol(Symbol::Tilde) => SelectorKind::Preceding,
|
TokenKind::Symbol(Symbol::Tilde) => SelectorKind::Preceding,
|
||||||
TokenKind::Symbol(Symbol::Mul) => SelectorKind::Universal,
|
TokenKind::Symbol(Symbol::Mul) => SelectorKind::Universal,
|
||||||
// TokenKind::Symbol(Symbol::BitAnd) => SelectorKind::Super,
|
TokenKind::Symbol(Symbol::BitAnd) => SelectorKind::Super,
|
||||||
TokenKind::Attribute(attr) => SelectorKind::Attribute(attr.clone()),
|
TokenKind::Attribute(attr) => SelectorKind::Attribute(attr.clone()),
|
||||||
_ => todo!("unimplemented selector"),
|
_ => todo!("unimplemented selector"),
|
||||||
});
|
});
|
||||||
@ -221,7 +245,7 @@ impl Selector {
|
|||||||
if self.0.is_empty() {
|
if self.0.is_empty() {
|
||||||
return Selector(other.0);
|
return Selector(other.0);
|
||||||
}
|
}
|
||||||
let mut rules: Vec<SelectorKind> = Vec::with_capacity(self.0.len());
|
let mut rules: Vec<SelectorKind> = Vec::with_capacity(self.0.len() + other.0.len());
|
||||||
let sel1_split: Vec<Vec<SelectorKind>> = self
|
let sel1_split: Vec<Vec<SelectorKind>> = self
|
||||||
.0
|
.0
|
||||||
.split(|sel| sel == &SelectorKind::Multiple)
|
.split(|sel| sel == &SelectorKind::Multiple)
|
||||||
@ -234,9 +258,24 @@ impl Selector {
|
|||||||
.collect();
|
.collect();
|
||||||
for (idx, sel1) in sel1_split.iter().enumerate() {
|
for (idx, sel1) in sel1_split.iter().enumerate() {
|
||||||
for (idx2, sel2) in sel2_split.iter().enumerate() {
|
for (idx2, sel2) in sel2_split.iter().enumerate() {
|
||||||
rules.extend(sel1.iter().cloned());
|
let mut this_selector = Vec::with_capacity(other.0.len());
|
||||||
rules.push(SelectorKind::Whitespace);
|
let mut found_super = false;
|
||||||
rules.extend(sel2.iter().cloned());
|
|
||||||
|
for sel in sel2 {
|
||||||
|
if sel == &SelectorKind::Super {
|
||||||
|
this_selector.extend(sel1.iter().cloned());
|
||||||
|
found_super = true;
|
||||||
|
} else {
|
||||||
|
this_selector.push(sel.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found_super {
|
||||||
|
rules.extend(sel1.iter().cloned());
|
||||||
|
rules.push(SelectorKind::Whitespace);
|
||||||
|
}
|
||||||
|
rules.extend(this_selector);
|
||||||
|
|
||||||
if !(idx + 1 == sel1_split.len() && idx2 + 1 == sel2_split.len()) {
|
if !(idx + 1 == sel1_split.len() && idx2 + 1 == sel2_split.len()) {
|
||||||
rules.push(SelectorKind::Multiple);
|
rules.push(SelectorKind::Multiple);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user