Allow nested unknown @ rules
This commit is contained in:
parent
a6cc86e4db
commit
a3b260c0bd
@ -37,6 +37,7 @@ impl AtRule {
|
||||
pos: Pos,
|
||||
toks: &mut Peekable<I>,
|
||||
scope: &Scope,
|
||||
super_selector: &Selector,
|
||||
) -> SassResult<AtRule> {
|
||||
devour_whitespace(toks);
|
||||
Ok(match rule {
|
||||
@ -116,7 +117,22 @@ impl AtRule {
|
||||
params.push_str(&tok.kind.to_string());
|
||||
}
|
||||
|
||||
let body = eat_unknown_atrule_body(toks, scope, &Selector::new())?;
|
||||
let raw_body = eat_unknown_atrule_body(toks, scope, super_selector)?;
|
||||
let mut body = Vec::with_capacity(raw_body.len());
|
||||
body.push(Stmt::RuleSet(RuleSet::new()));
|
||||
let mut rules = Vec::new();
|
||||
for stmt in raw_body {
|
||||
match stmt {
|
||||
s @ Stmt::Style(..) => rules.push(s),
|
||||
s => body.push(s),
|
||||
}
|
||||
}
|
||||
|
||||
body[0] = Stmt::RuleSet(RuleSet {
|
||||
selector: super_selector.clone(),
|
||||
rules,
|
||||
super_selector: Selector::new(),
|
||||
});
|
||||
|
||||
let u = UnknownAtRule {
|
||||
name: name.clone(),
|
||||
@ -140,6 +156,7 @@ fn eat_unknown_atrule_body<I: Iterator<Item = Token>>(
|
||||
let mut stmts = Vec::new();
|
||||
while let Some(expr) = eat_expr(toks, scope, super_selector)? {
|
||||
match expr {
|
||||
Expr::AtRule(a) => stmts.push(Stmt::AtRule(a)),
|
||||
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
||||
Expr::Styles(s) => stmts.extend(s.into_iter().map(Stmt::Style)),
|
||||
Expr::Include(s) => stmts.extend(s),
|
||||
|
@ -82,7 +82,7 @@ impl Css {
|
||||
.get_mut(0)
|
||||
.expect("expected block to exist")
|
||||
.push_comment(s),
|
||||
Stmt::AtRule(_) => todo!("at rule inside css block"),
|
||||
Stmt::AtRule(r) => vals.push(Toplevel::AtRule(r)),
|
||||
};
|
||||
}
|
||||
vals
|
||||
|
@ -4,6 +4,7 @@ use crate::args::{eat_func_args, CallArgs, FuncArgs};
|
||||
use crate::atrule::AtRule;
|
||||
use crate::common::{Scope, Symbol};
|
||||
use crate::error::SassResult;
|
||||
use crate::selector::Selector;
|
||||
use crate::utils::devour_whitespace;
|
||||
use crate::value::Value;
|
||||
use crate::{Token, TokenKind};
|
||||
@ -47,9 +48,13 @@ impl Function {
|
||||
while nesting > 0 {
|
||||
if let Some(tok) = toks.next() {
|
||||
match &tok.kind {
|
||||
TokenKind::AtRule(rule) => {
|
||||
body.push(AtRule::from_tokens(rule, tok.pos, toks, scope)?)
|
||||
}
|
||||
TokenKind::AtRule(rule) => body.push(AtRule::from_tokens(
|
||||
rule,
|
||||
tok.pos,
|
||||
toks,
|
||||
scope,
|
||||
&Selector::new(),
|
||||
)?),
|
||||
TokenKind::Symbol(Symbol::CloseCurlyBrace) => nesting -= 1,
|
||||
_ => {}
|
||||
}
|
||||
|
19
src/lib.rs
19
src/lib.rs
@ -213,6 +213,16 @@ pub(crate) struct RuleSet {
|
||||
super_selector: Selector,
|
||||
}
|
||||
|
||||
impl RuleSet {
|
||||
pub(crate) fn new() -> RuleSet {
|
||||
RuleSet {
|
||||
selector: Selector::new(),
|
||||
rules: Vec::new(),
|
||||
super_selector: Selector::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An intermediate representation of what are essentially single lines
|
||||
/// todo! rename this
|
||||
#[derive(Clone, Debug)]
|
||||
@ -236,6 +246,7 @@ enum Expr {
|
||||
MultilineComment(String),
|
||||
Debug(Pos, String),
|
||||
Warn(Pos, String),
|
||||
AtRule(AtRule),
|
||||
// /// Function call: `calc(10vw - 1px)`
|
||||
// FuncCall(String, Vec<Token>),
|
||||
}
|
||||
@ -437,7 +448,7 @@ impl<'a> StyleSheetParser<'a> {
|
||||
pos,
|
||||
}) = self.lexer.next()
|
||||
{
|
||||
match AtRule::from_tokens(rule, pos, &mut self.lexer, &self.global_scope)? {
|
||||
match AtRule::from_tokens(rule, pos, &mut self.lexer, &self.global_scope, &Selector::new())? {
|
||||
AtRule::Mixin(name, mixin) => {
|
||||
self.global_scope.insert_mixin(&name, *mixin);
|
||||
}
|
||||
@ -476,7 +487,7 @@ impl<'a> StyleSheetParser<'a> {
|
||||
while let Some(expr) = eat_expr(&mut self.lexer, scope, super_selector)? {
|
||||
match expr {
|
||||
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
||||
#[allow(clippy::redundant_closure)]
|
||||
Expr::AtRule(s) => stmts.push(Stmt::AtRule(s)),
|
||||
Expr::Styles(s) => stmts.extend(s.into_iter().map(Stmt::Style)),
|
||||
Expr::MixinDecl(name, mixin) => {
|
||||
scope.insert_mixin(&name, *mixin);
|
||||
@ -623,7 +634,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
pos,
|
||||
}) = toks.next()
|
||||
{
|
||||
return match AtRule::from_tokens(rule, pos, toks, scope)? {
|
||||
return match AtRule::from_tokens(rule, pos, toks, scope, &super_selector)? {
|
||||
AtRule::Mixin(name, mixin) => Ok(Some(Expr::MixinDecl(name, mixin))),
|
||||
AtRule::Function(name, func) => Ok(Some(Expr::FunctionDecl(name, func))),
|
||||
AtRule::Charset(_) => todo!("@charset as expr"),
|
||||
@ -631,7 +642,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
||||
AtRule::Warn(a, b) => Ok(Some(Expr::Warn(a, b))),
|
||||
AtRule::Error(pos, err) => Err(SassError::new(err, pos)),
|
||||
AtRule::Return(_) => todo!("@return in unexpected location!"),
|
||||
AtRule::Unknown(..) => todo!("nested media queries not yet implemented"),
|
||||
u @ AtRule::Unknown(..) => Ok(Some(Expr::AtRule(u))),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +94,7 @@ impl Mixin {
|
||||
let mut stmts = Vec::new();
|
||||
while let Some(expr) = eat_expr(&mut self.body, &self.scope, super_selector)? {
|
||||
match expr {
|
||||
Expr::AtRule(a) => stmts.push(Stmt::AtRule(a)),
|
||||
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
||||
Expr::Styles(s) => stmts.extend(s.into_iter().map(Stmt::Style)),
|
||||
Expr::Include(s) => stmts.extend(s),
|
||||
|
@ -335,6 +335,8 @@ impl Selector {
|
||||
pub fn zip(&self, other: &Selector) -> Selector {
|
||||
if self.0.is_empty() {
|
||||
return Selector(other.0.clone());
|
||||
} else if other.0.is_empty() {
|
||||
return self.clone();
|
||||
}
|
||||
let mut rules: Vec<SelectorKind> = Vec::with_capacity(self.0.len() + other.0.len());
|
||||
let sel1_split: Vec<&[SelectorKind]> =
|
||||
|
@ -7,3 +7,8 @@ test!(
|
||||
basic_toplevel,
|
||||
"@media foo {\n a {\n color: red;\n }\n}\n"
|
||||
);
|
||||
test!(
|
||||
basic_nested,
|
||||
"a {\n @media foo {\n color: red;\n }\n}\n",
|
||||
"@media foo {\n a {\n color: red;\n }\n}\n"
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user