implement @if/@else
This commit is contained in:
parent
1127897bd8
commit
f1238c4d3a
@ -32,6 +32,7 @@ pub(crate) enum AtRule {
|
||||
Content,
|
||||
Unknown(UnknownAtRule),
|
||||
For(Vec<Stmt>),
|
||||
If(Vec<Token>, Vec<Stmt>, Vec<Stmt>),
|
||||
}
|
||||
|
||||
impl AtRule {
|
||||
@ -104,7 +105,46 @@ impl AtRule {
|
||||
}
|
||||
AtRuleKind::Each => todo!("@each not yet implemented"),
|
||||
AtRuleKind::Extend => todo!("@extend not yet implemented"),
|
||||
AtRuleKind::If => todo!("@if not yet implemented"),
|
||||
AtRuleKind::If => {
|
||||
let mut cond = Vec::new();
|
||||
let mut n = 0;
|
||||
while let Some(tok) = toks.peek() {
|
||||
match tok.kind {
|
||||
TokenKind::Symbol(Symbol::OpenCurlyBrace) => n += 1,
|
||||
TokenKind::Symbol(Symbol::CloseCurlyBrace) => n -= 1,
|
||||
TokenKind::Interpolation => n += 1,
|
||||
_ => {}
|
||||
}
|
||||
if n == 1 {
|
||||
break;
|
||||
}
|
||||
cond.push(toks.next().unwrap());
|
||||
}
|
||||
toks.next();
|
||||
devour_whitespace_or_comment(toks);
|
||||
let mut yes = Vec::new();
|
||||
yes.extend(eat_stmts(toks, scope, super_selector)?);
|
||||
|
||||
devour_whitespace_or_comment(toks);
|
||||
|
||||
let mut no = Vec::new();
|
||||
if let Some(tok) = toks.peek() {
|
||||
if tok.kind == TokenKind::AtRule(AtRuleKind::Else) {
|
||||
toks.next();
|
||||
devour_whitespace_or_comment(toks);
|
||||
if let Some(tok) = toks.next() {
|
||||
if !tok.is_symbol(Symbol::OpenCurlyBrace) {
|
||||
return Err("expected \"{\".".into());
|
||||
}
|
||||
}
|
||||
devour_whitespace_or_comment(toks);
|
||||
no.extend(eat_stmts(toks, scope, super_selector)?);
|
||||
}
|
||||
}
|
||||
devour_whitespace_or_comment(toks);
|
||||
|
||||
AtRule::If(cond, yes, no)
|
||||
}
|
||||
AtRuleKind::Else => todo!("@else not yet implemented"),
|
||||
AtRuleKind::For => {
|
||||
let mut stmts = Vec::new();
|
||||
|
@ -153,7 +153,7 @@ impl Css {
|
||||
.pretty_print(buf, nesting + 1)?;
|
||||
writeln!(buf, "{}}}", padding)?;
|
||||
}
|
||||
_ => todo!(),
|
||||
_ => todo!("at-rule other than unknown at toplevel"),
|
||||
},
|
||||
Toplevel::Newline => {
|
||||
if has_written {
|
||||
|
25
src/lib.rs
25
src/lib.rs
@ -417,6 +417,17 @@ impl<'a> StyleSheetParser<'a> {
|
||||
}
|
||||
AtRule::For(s) => rules.extend(s),
|
||||
AtRule::Content => return Err("@content is only allowed within mixin declarations.".into()),
|
||||
AtRule::If(cond, yes, no) => {
|
||||
if Value::from_tokens(
|
||||
&mut cond.into_iter().peekable(),
|
||||
&mut GLOBAL_SCOPE.with(|s| s.borrow().clone()),
|
||||
&Selector::new(),
|
||||
)?.is_true()? {
|
||||
rules.extend(yes);
|
||||
} else {
|
||||
rules.extend(no);
|
||||
}
|
||||
}
|
||||
u @ AtRule::Unknown(..) => rules.push(Stmt::AtRule(u)),
|
||||
}
|
||||
}
|
||||
@ -443,6 +454,19 @@ impl<'a> StyleSheetParser<'a> {
|
||||
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
||||
Expr::AtRule(a) => match a {
|
||||
AtRule::For(s) => stmts.extend(s),
|
||||
AtRule::If(cond, yes, no) => {
|
||||
if Value::from_tokens(
|
||||
&mut cond.into_iter().peekable(),
|
||||
&mut GLOBAL_SCOPE.with(|s| s.borrow().clone()),
|
||||
&Selector::new(),
|
||||
)?
|
||||
.is_true()?
|
||||
{
|
||||
stmts.extend(yes);
|
||||
} else {
|
||||
stmts.extend(no);
|
||||
}
|
||||
}
|
||||
AtRule::Content => {
|
||||
return Err("@content is only allowed within mixin declarations.".into())
|
||||
}
|
||||
@ -620,6 +644,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
AtRule::Content => {
|
||||
return Err("@content is only allowed within mixin declarations.".into())
|
||||
}
|
||||
f @ AtRule::If(..) => Ok(Some(Expr::AtRule(f))),
|
||||
f @ AtRule::For(..) => Ok(Some(Expr::AtRule(f))),
|
||||
u @ AtRule::Unknown(..) => Ok(Some(Expr::AtRule(u))),
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user