2020-03-01 08:02:59 -05:00
|
|
|
use std::iter::Peekable;
|
|
|
|
|
2020-04-12 19:37:12 -04:00
|
|
|
use codemap::{Span, Spanned};
|
|
|
|
|
2020-03-01 08:02:59 -05:00
|
|
|
use super::parse::eat_stmts;
|
|
|
|
use crate::error::SassResult;
|
2020-03-17 20:13:53 -04:00
|
|
|
use crate::scope::Scope;
|
2020-03-01 08:02:59 -05:00
|
|
|
use crate::selector::Selector;
|
|
|
|
use crate::utils::{devour_whitespace, parse_interpolation};
|
2020-03-29 13:28:17 -04:00
|
|
|
use crate::{RuleSet, Stmt, Token};
|
2020-03-01 08:02:59 -05:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub(crate) struct UnknownAtRule {
|
|
|
|
pub name: String,
|
|
|
|
pub super_selector: Selector,
|
|
|
|
pub params: String,
|
2020-04-12 19:37:12 -04:00
|
|
|
pub body: Vec<Spanned<Stmt>>,
|
2020-03-01 08:02:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UnknownAtRule {
|
|
|
|
pub fn from_tokens<I: Iterator<Item = Token>>(
|
|
|
|
toks: &mut Peekable<I>,
|
|
|
|
name: &str,
|
2020-03-01 08:20:59 -05:00
|
|
|
scope: &mut Scope,
|
2020-03-01 08:02:59 -05:00
|
|
|
super_selector: &Selector,
|
2020-04-12 19:37:12 -04:00
|
|
|
kind_span: Span,
|
2020-03-01 08:02:59 -05:00
|
|
|
) -> SassResult<UnknownAtRule> {
|
|
|
|
let mut params = String::new();
|
|
|
|
while let Some(tok) = toks.next() {
|
|
|
|
match tok.kind {
|
2020-03-29 13:28:17 -04:00
|
|
|
'{' => break,
|
|
|
|
'#' => {
|
|
|
|
if toks.peek().unwrap().kind == '{' {
|
|
|
|
toks.next();
|
2020-04-12 19:37:12 -04:00
|
|
|
let interpolation = parse_interpolation(toks, scope, super_selector)?;
|
|
|
|
params.push_str(&interpolation.node.to_css_string(interpolation.span)?);
|
2020-03-29 13:28:17 -04:00
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
params.push(tok.kind);
|
|
|
|
}
|
2020-03-01 08:02:59 -05:00
|
|
|
}
|
2020-03-29 13:28:17 -04:00
|
|
|
'\n' | ' ' | '\t' => {
|
2020-03-01 08:02:59 -05:00
|
|
|
devour_whitespace(toks);
|
|
|
|
params.push(' ');
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2020-03-29 13:28:17 -04:00
|
|
|
params.push(tok.kind);
|
2020-03-01 08:02:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
let raw_body = eat_stmts(toks, scope, super_selector)?;
|
2020-04-12 21:47:32 -04:00
|
|
|
let mut rules = Vec::with_capacity(raw_body.len());
|
|
|
|
let mut body = Vec::new();
|
|
|
|
|
2020-03-01 08:02:59 -05:00
|
|
|
for stmt in raw_body {
|
2020-04-12 19:37:12 -04:00
|
|
|
match stmt.node {
|
2020-04-12 21:47:32 -04:00
|
|
|
Stmt::Style(..) => body.push(stmt),
|
|
|
|
_ => rules.push(stmt),
|
2020-03-01 08:02:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-12 21:47:32 -04:00
|
|
|
if super_selector.is_empty() {
|
|
|
|
body.append(&mut rules);
|
|
|
|
} else {
|
|
|
|
body = vec![Spanned {
|
|
|
|
node: Stmt::RuleSet(RuleSet {
|
|
|
|
selector: super_selector.clone(),
|
|
|
|
rules: body,
|
|
|
|
super_selector: Selector::new(),
|
|
|
|
}),
|
|
|
|
span: kind_span,
|
|
|
|
}];
|
|
|
|
body.append(&mut rules);
|
|
|
|
}
|
2020-03-01 08:02:59 -05:00
|
|
|
|
|
|
|
Ok(UnknownAtRule {
|
|
|
|
name: name.to_owned(),
|
|
|
|
super_selector: Selector::new(),
|
|
|
|
params: params.trim().to_owned(),
|
|
|
|
body,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|