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,
|
read_until_semicolon_or_closing_curly_brace,
|
||||||
};
|
};
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::{Stmt, Token};
|
use crate::{RuleSet, Stmt, Token};
|
||||||
|
|
||||||
pub(crate) use function::Function;
|
pub(crate) use function::Function;
|
||||||
pub(crate) use if_rule::If;
|
pub(crate) use if_rule::If;
|
||||||
@ -40,6 +40,7 @@ pub(crate) enum AtRule {
|
|||||||
Each(Vec<Stmt>),
|
Each(Vec<Stmt>),
|
||||||
While(Vec<Stmt>),
|
While(Vec<Stmt>),
|
||||||
If(If),
|
If(If),
|
||||||
|
AtRoot(Vec<Stmt>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AtRule {
|
impl AtRule {
|
||||||
@ -103,7 +104,39 @@ impl AtRule {
|
|||||||
}
|
}
|
||||||
AtRuleKind::Use => todo!("@use not yet implemented"),
|
AtRuleKind::Use => todo!("@use not yet implemented"),
|
||||||
AtRuleKind::Annotation => todo!("@annotation 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 => {
|
AtRuleKind::Charset => {
|
||||||
read_until_semicolon_or_closing_curly_brace(toks);
|
read_until_semicolon_or_closing_curly_brace(toks);
|
||||||
if toks.peek().unwrap().kind == ';' {
|
if toks.peek().unwrap().kind == ';' {
|
||||||
|
@ -382,6 +382,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
AtRule::If(i) => {
|
AtRule::If(i) => {
|
||||||
rules.extend(i.eval(&mut Scope::new(), &Selector::new())?);
|
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)),
|
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())
|
return Err("@content is only allowed within mixin declarations.".into())
|
||||||
}
|
}
|
||||||
AtRule::Return(..) => return Err("This at-rule is not allowed here.".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)),
|
r => stmts.push(Stmt::AtRule(r)),
|
||||||
},
|
},
|
||||||
Expr::Styles(s) => stmts.extend(s.into_iter().map(Box::new).map(Stmt::Style)),
|
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>> {
|
) -> SassResult<Option<Expr>> {
|
||||||
let mut values = Vec::with_capacity(5);
|
let mut values = Vec::with_capacity(5);
|
||||||
while let Some(tok) = toks.peek() {
|
while let Some(tok) = toks.peek() {
|
||||||
match &tok.kind {
|
match tok.kind {
|
||||||
':' => {
|
':' => {
|
||||||
let tok = toks.next();
|
let tok = toks.next();
|
||||||
if devour_whitespace(toks) {
|
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::While(..) => Ok(Some(Expr::AtRule(f))),
|
||||||
f @ AtRule::Each(..) => Ok(Some(Expr::AtRule(f))),
|
f @ AtRule::Each(..) => Ok(Some(Expr::AtRule(f))),
|
||||||
u @ AtRule::Unknown(..) => Ok(Some(Expr::AtRule(u))),
|
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)
|
.get_mut(0)
|
||||||
.expect("expected block to exist")
|
.expect("expected block to exist")
|
||||||
.push_comment(s),
|
.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)),
|
Stmt::AtRule(r) => vals.push(Toplevel::AtRule(r)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -384,13 +384,10 @@ impl Selector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace(super_selector: Selector, this: Selector) -> Selector {
|
pub fn replace(super_selector: Selector, this: Selector) -> Selector {
|
||||||
if super_selector.0.is_empty() {
|
if super_selector.0.is_empty() || this.0.is_empty() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
if this.0.is_empty() {
|
|
||||||
return super_selector;
|
|
||||||
}
|
|
||||||
let mut parts = Vec::with_capacity(super_selector.0.len());
|
let mut parts = Vec::with_capacity(super_selector.0.len());
|
||||||
for (idx, part) in super_selector.clone().0.into_iter().enumerate() {
|
for (idx, part) in super_selector.clone().0.into_iter().enumerate() {
|
||||||
let mut found_inner = false;
|
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 {\n @at-root & {\n .bar {\n @at-root & {\n a: b;\n }\n }\n }\n}\n",
|
||||||
".foo .bar {\n a: b;\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