implement \@while

This commit is contained in:
ConnorSkees 2020-04-02 00:14:11 -04:00
parent b71b11dccb
commit e836ecb8ce
3 changed files with 55 additions and 3 deletions

View File

@ -40,6 +40,7 @@ pub(crate) enum AtRule {
Unknown(UnknownAtRule),
For(Vec<Stmt>),
Each(Vec<Stmt>),
While(Vec<Stmt>),
If(If),
}
@ -312,7 +313,32 @@ impl AtRule {
AtRule::For(stmts)
}
AtRuleKind::While => todo!("@while not yet implemented"),
AtRuleKind::While => {
let mut stmts = Vec::new();
devour_whitespace(toks);
let cond = read_until_open_curly_brace(toks);
toks.next();
let scope = &mut scope.clone();
let body = read_until_closing_curly_brace(toks);
toks.next();
devour_whitespace(toks);
while Value::from_tokens(
&mut cond.clone().into_iter().peekable(),
scope,
super_selector,
)?
.is_true()?
{
stmts.extend(eat_stmts(
&mut body.clone().into_iter().peekable(),
scope,
super_selector,
)?);
}
AtRule::While(stmts)
}
AtRuleKind::Keyframes => todo!("@keyframes not yet implemented"),
AtRuleKind::Unknown(name) => AtRule::Unknown(UnknownAtRule::from_tokens(
toks,

View File

@ -382,7 +382,7 @@ impl<'a> StyleSheetParser<'a> {
AtRule::Return(_) => {
return Err("This at-rule is not allowed here.".into())
}
AtRule::Each(s) | AtRule::For(s) => rules.extend(s),
AtRule::While(s) | AtRule::Each(s) | AtRule::For(s) => rules.extend(s),
AtRule::Content => return Err("@content is only allowed within mixin declarations.".into()),
AtRule::If(i) => {
rules.extend(i.eval(&mut Scope::new(), &Selector::new())?);
@ -412,7 +412,7 @@ impl<'a> StyleSheetParser<'a> {
match expr {
Expr::Style(s) => stmts.push(Stmt::Style(s)),
Expr::AtRule(a) => match a {
AtRule::Each(s) | AtRule::For(s) => stmts.extend(s),
AtRule::While(s) | AtRule::Each(s) | AtRule::For(s) => stmts.extend(s),
AtRule::If(i) => stmts.extend(i.eval(scope, super_selector)?),
AtRule::Content => {
return Err("@content is only allowed within mixin declarations.".into())
@ -595,6 +595,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
c @ AtRule::Content => Ok(Some(Expr::AtRule(c))),
f @ AtRule::If(..) => Ok(Some(Expr::AtRule(f))),
f @ AtRule::For(..) => Ok(Some(Expr::AtRule(f))),
f @ AtRule::While(..) => Ok(Some(Expr::AtRule(f))),
f @ AtRule::Each(..) => Ok(Some(Expr::AtRule(f))),
u @ AtRule::Unknown(..) => Ok(Some(Expr::AtRule(u))),
};

25
tests/while.rs Normal file
View File

@ -0,0 +1,25 @@
#![cfg(test)]
#[macro_use]
mod macros;
test!(
inner_increment_var,
"$a: 4;\n$b: 1;\na {\n @while $a > $b {\n color: $b;\n $b: $b + 1;\n }\n}",
"a {\n color: 1;\n color: 2;\n color: 3;\n}\n"
);
test!(
outer_increment_var,
"$a: 4;\n$b: 1;\n@while $a > $b {\na {\n color: $b;\n }\n $b: $b + 1;\n}",
"a {\n color: 1;\n}\n\na {\n color: 2;\n}\n\na {\n color: 3;\n}\n"
);
test!(
inner_while_false,
"a {\n @while false {\n color: foo;\n }\n}",
""
);
test!(
outer_while_false,
"@while false {\na {\n color: $b;\n }\n $b: $b + 1;\n}",
""
);