initial implementation of @ at-root
This commit is contained in:
parent
526ed4fde0
commit
648dc04c33
@ -9,7 +9,7 @@ use crate::utils::{
|
||||
read_until_semicolon_or_closing_curly_brace,
|
||||
};
|
||||
use crate::value::Value;
|
||||
use crate::{Stmt, Token};
|
||||
use crate::{RuleSet, Stmt, Token};
|
||||
|
||||
pub(crate) use function::Function;
|
||||
pub(crate) use if_rule::If;
|
||||
@ -40,6 +40,7 @@ pub(crate) enum AtRule {
|
||||
Each(Vec<Stmt>),
|
||||
While(Vec<Stmt>),
|
||||
If(If),
|
||||
AtRoot(Vec<Stmt>),
|
||||
}
|
||||
|
||||
impl AtRule {
|
||||
@ -103,7 +104,39 @@ impl AtRule {
|
||||
}
|
||||
AtRuleKind::Use => todo!("@use not yet implemented"),
|
||||
AtRuleKind::Annotation => todo!("@annotation not yet implemented"),
|
||||
AtRuleKind::AtRoot => todo!("@at-root not yet implemented"),
|
||||
AtRuleKind::AtRoot => {
|
||||
let selector = &Selector::replace(
|
||||
super_selector.clone(),
|
||||
Selector::from_tokens(
|
||||
&mut read_until_open_curly_brace(toks).into_iter().peekable(),
|
||||
scope,
|
||||
super_selector,
|
||||
)?,
|
||||
);
|
||||
toks.next();
|
||||
devour_whitespace(toks);
|
||||
let mut body = read_until_closing_curly_brace(toks);
|
||||
body.push(toks.next().unwrap());
|
||||
devour_whitespace(toks);
|
||||
let mut styles = Vec::new();
|
||||
let raw_stmts = eat_stmts(&mut body.into_iter().peekable(), scope, &selector)?
|
||||
.into_iter()
|
||||
.filter_map(|s| match s {
|
||||
Stmt::Style(..) => {
|
||||
styles.push(s);
|
||||
None
|
||||
}
|
||||
_ => Some(s),
|
||||
})
|
||||
.collect::<Vec<Stmt>>();
|
||||
let mut stmts = vec![Stmt::RuleSet(RuleSet {
|
||||
selector: selector.clone(),
|
||||
rules: styles,
|
||||
super_selector: Selector::new(),
|
||||
})];
|
||||
stmts.extend(raw_stmts);
|
||||
AtRule::AtRoot(stmts)
|
||||
}
|
||||
AtRuleKind::Charset => {
|
||||
read_until_semicolon_or_closing_curly_brace(toks);
|
||||
if toks.peek().unwrap().kind == ';' {
|
||||
|
@ -382,6 +382,7 @@ impl<'a> StyleSheetParser<'a> {
|
||||
AtRule::If(i) => {
|
||||
rules.extend(i.eval(&mut Scope::new(), &Selector::new())?);
|
||||
}
|
||||
AtRule::AtRoot(root_rules) => rules.extend(root_rules),
|
||||
u @ AtRule::Unknown(..) => rules.push(Stmt::AtRule(u)),
|
||||
}
|
||||
}
|
||||
@ -416,6 +417,7 @@ impl<'a> StyleSheetParser<'a> {
|
||||
return Err("@content is only allowed within mixin declarations.".into())
|
||||
}
|
||||
AtRule::Return(..) => return Err("This at-rule is not allowed here.".into()),
|
||||
AtRule::AtRoot(root_stmts) => stmts.extend(root_stmts),
|
||||
r => stmts.push(Stmt::AtRule(r)),
|
||||
},
|
||||
Expr::Styles(s) => stmts.extend(s.into_iter().map(Box::new).map(Stmt::Style)),
|
||||
@ -463,7 +465,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
) -> SassResult<Option<Expr>> {
|
||||
let mut values = Vec::with_capacity(5);
|
||||
while let Some(tok) = toks.peek() {
|
||||
match &tok.kind {
|
||||
match tok.kind {
|
||||
':' => {
|
||||
let tok = toks.next();
|
||||
if devour_whitespace(toks) {
|
||||
@ -600,6 +602,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
f @ AtRule::While(..) => Ok(Some(Expr::AtRule(f))),
|
||||
f @ AtRule::Each(..) => Ok(Some(Expr::AtRule(f))),
|
||||
u @ AtRule::Unknown(..) => Ok(Some(Expr::AtRule(u))),
|
||||
u @ AtRule::AtRoot(..) => Ok(Some(Expr::AtRule(u))),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -89,6 +89,10 @@ impl Css {
|
||||
.get_mut(0)
|
||||
.expect("expected block to exist")
|
||||
.push_comment(s),
|
||||
Stmt::AtRule(AtRule::AtRoot(stmts)) => stmts
|
||||
.into_iter()
|
||||
.map(|r| Ok(vals.extend(self.parse_stmt(r)?)))
|
||||
.collect::<SassResult<()>>()?,
|
||||
Stmt::AtRule(r) => vals.push(Toplevel::AtRule(r)),
|
||||
};
|
||||
}
|
||||
|
@ -384,13 +384,10 @@ impl Selector {
|
||||
}
|
||||
}
|
||||
|
||||
fn replace(super_selector: Selector, this: Selector) -> Selector {
|
||||
if super_selector.0.is_empty() {
|
||||
pub fn replace(super_selector: Selector, this: Selector) -> Selector {
|
||||
if super_selector.0.is_empty() || this.0.is_empty() {
|
||||
return this;
|
||||
}
|
||||
if this.0.is_empty() {
|
||||
return super_selector;
|
||||
}
|
||||
let mut parts = Vec::with_capacity(super_selector.0.len());
|
||||
for (idx, part) in super_selector.clone().0.into_iter().enumerate() {
|
||||
let mut found_inner = false;
|
||||
|
@ -28,3 +28,8 @@ test!(
|
||||
".foo {\n @at-root & {\n .bar {\n @at-root & {\n a: b;\n }\n }\n }\n}\n",
|
||||
".foo .bar {\n a: b;\n}\n"
|
||||
);
|
||||
test!(
|
||||
deeply_nested_with_rulesets_and_styles,
|
||||
".foo {\n @at-root .bar {\n a: b;\n c {\n d: e;\n foo {\n bar: baz;\n }\n h: j;\n }\n f: g;\n }\n}\n",
|
||||
".bar {\n a: b;\n f: g;\n}\n.bar c {\n d: e;\n h: j;\n}\n.bar c foo {\n bar: baz;\n}\n"
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user