MVP implementation of @supports
This commit is contained in:
parent
c9a68c55b9
commit
207aa1bf38
@ -18,6 +18,10 @@ enum Toplevel {
|
|||||||
params: String,
|
params: String,
|
||||||
body: Vec<Stmt>,
|
body: Vec<Stmt>,
|
||||||
},
|
},
|
||||||
|
Supports {
|
||||||
|
params: String,
|
||||||
|
body: Vec<Stmt>,
|
||||||
|
},
|
||||||
Newline,
|
Newline,
|
||||||
Style(Box<Style>),
|
Style(Box<Style>),
|
||||||
}
|
}
|
||||||
@ -105,6 +109,9 @@ impl Css {
|
|||||||
Stmt::Media { params, body, .. } => {
|
Stmt::Media { params, body, .. } => {
|
||||||
vals.push(Toplevel::Media { params, body })
|
vals.push(Toplevel::Media { params, body })
|
||||||
}
|
}
|
||||||
|
Stmt::Supports { params, body, .. } => {
|
||||||
|
vals.push(Toplevel::Supports { params, body })
|
||||||
|
}
|
||||||
Stmt::UnknownAtRule {
|
Stmt::UnknownAtRule {
|
||||||
params, body, name, ..
|
params, body, name, ..
|
||||||
} => vals.push(Toplevel::UnknownAtRule { params, body, name }),
|
} => vals.push(Toplevel::UnknownAtRule { params, body, name }),
|
||||||
@ -120,6 +127,7 @@ impl Css {
|
|||||||
Stmt::Comment(s) => vec![Toplevel::MultilineComment(s)],
|
Stmt::Comment(s) => vec![Toplevel::MultilineComment(s)],
|
||||||
Stmt::Style(s) => vec![Toplevel::Style(s)],
|
Stmt::Style(s) => vec![Toplevel::Style(s)],
|
||||||
Stmt::Media { params, body, .. } => vec![Toplevel::Media { params, body }],
|
Stmt::Media { params, body, .. } => vec![Toplevel::Media { params, body }],
|
||||||
|
Stmt::Supports { params, body, .. } => vec![Toplevel::Supports { params, body }],
|
||||||
Stmt::UnknownAtRule {
|
Stmt::UnknownAtRule {
|
||||||
params, name, body, ..
|
params, name, body, ..
|
||||||
} => vec![Toplevel::UnknownAtRule { params, name, body }],
|
} => vec![Toplevel::UnknownAtRule { params, name, body }],
|
||||||
@ -216,6 +224,33 @@ impl Css {
|
|||||||
)?;
|
)?;
|
||||||
writeln!(buf, "{}}}", padding)?;
|
writeln!(buf, "{}}}", padding)?;
|
||||||
}
|
}
|
||||||
|
Toplevel::Supports { params, body } => {
|
||||||
|
if should_emit_newline {
|
||||||
|
should_emit_newline = false;
|
||||||
|
writeln!(buf)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.is_empty() {
|
||||||
|
write!(buf, "{}@supports", padding)?;
|
||||||
|
} else {
|
||||||
|
write!(buf, "{}@supports {}", padding, params)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if body.is_empty() {
|
||||||
|
writeln!(buf, ";")?;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
writeln!(buf, " {{")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Css::from_stmts(body, extender)?._inner_pretty_print(
|
||||||
|
buf,
|
||||||
|
map,
|
||||||
|
extender,
|
||||||
|
nesting + 1,
|
||||||
|
)?;
|
||||||
|
writeln!(buf, "{}}}", padding)?;
|
||||||
|
}
|
||||||
Toplevel::Media { params, body } => {
|
Toplevel::Media { params, body } => {
|
||||||
if body.is_empty() {
|
if body.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
|
111
src/parse/mod.rs
111
src/parse/mod.rs
@ -56,6 +56,10 @@ pub(crate) enum Stmt {
|
|||||||
params: String,
|
params: String,
|
||||||
body: Vec<Stmt>,
|
body: Vec<Stmt>,
|
||||||
},
|
},
|
||||||
|
Supports {
|
||||||
|
params: String,
|
||||||
|
body: Vec<Stmt>,
|
||||||
|
},
|
||||||
AtRoot {
|
AtRoot {
|
||||||
body: Vec<Stmt>,
|
body: Vec<Stmt>,
|
||||||
},
|
},
|
||||||
@ -1040,31 +1044,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_media(&mut self) -> SassResult<Stmt> {
|
fn parse_media(&mut self) -> SassResult<Stmt> {
|
||||||
let mut params = String::new();
|
let params = self.parse_media_args()?;
|
||||||
self.whitespace();
|
|
||||||
while let Some(tok) = self.toks.next() {
|
|
||||||
match tok.kind {
|
|
||||||
'{' => break,
|
|
||||||
'#' => {
|
|
||||||
if let Some(Token { kind: '{', pos }) = self.toks.peek().cloned() {
|
|
||||||
self.toks.next();
|
|
||||||
self.span_before = pos;
|
|
||||||
let interpolation = self.parse_interpolation()?;
|
|
||||||
params.push_str(&interpolation.node.to_css_string(interpolation.span)?);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
params.push(tok.kind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'\n' | ' ' | '\t' => {
|
|
||||||
self.whitespace();
|
|
||||||
params.push(' ');
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
params.push(tok.kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
if params.is_empty() {
|
if params.is_empty() {
|
||||||
return Err(("Expected identifier.", self.span_before).into());
|
return Err(("Expected identifier.", self.span_before).into());
|
||||||
@ -1179,7 +1159,6 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(stmts)
|
Ok(stmts)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unused_self)]
|
|
||||||
fn parse_extend(&mut self) -> SassResult<()> {
|
fn parse_extend(&mut self) -> SassResult<()> {
|
||||||
// todo: track when inside ruleset or `@content`
|
// todo: track when inside ruleset or `@content`
|
||||||
// if !self.in_style_rule && !self.in_mixin && !self.in_content_block {
|
// if !self.in_style_rule && !self.in_mixin && !self.in_content_block {
|
||||||
@ -1256,15 +1235,91 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unused_self)]
|
|
||||||
fn parse_supports(&mut self) -> SassResult<Stmt> {
|
fn parse_supports(&mut self) -> SassResult<Stmt> {
|
||||||
todo!("@supports not yet implemented")
|
let params = self.parse_media_args()?;
|
||||||
|
|
||||||
|
if params.is_empty() {
|
||||||
|
return Err(("Expected \"not\".", self.span_before).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let raw_body = Parser {
|
||||||
|
toks: self.toks,
|
||||||
|
map: self.map,
|
||||||
|
path: self.path,
|
||||||
|
scopes: self.scopes,
|
||||||
|
global_scope: self.global_scope,
|
||||||
|
super_selectors: self.super_selectors,
|
||||||
|
span_before: self.span_before,
|
||||||
|
content: self.content.clone(),
|
||||||
|
in_mixin: self.in_mixin,
|
||||||
|
in_function: self.in_function,
|
||||||
|
in_control_flow: self.in_control_flow,
|
||||||
|
at_root: false,
|
||||||
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
|
extender: self.extender,
|
||||||
|
}
|
||||||
|
.parse()?;
|
||||||
|
|
||||||
|
let mut rules = Vec::with_capacity(raw_body.len());
|
||||||
|
let mut body = Vec::new();
|
||||||
|
|
||||||
|
for stmt in raw_body {
|
||||||
|
match stmt {
|
||||||
|
Stmt::Style(..) => body.push(stmt),
|
||||||
|
_ => rules.push(stmt),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.super_selectors.last().is_empty() {
|
||||||
|
body = vec![Stmt::RuleSet {
|
||||||
|
selector: self.super_selectors.last().clone(),
|
||||||
|
body,
|
||||||
|
super_selector: Selector::new(),
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
body.append(&mut rules);
|
||||||
|
|
||||||
|
Ok(Stmt::Supports {
|
||||||
|
params: params.trim().to_owned(),
|
||||||
|
body,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unused_self)]
|
#[allow(clippy::unused_self)]
|
||||||
fn parse_keyframes(&mut self) -> SassResult<Stmt> {
|
fn parse_keyframes(&mut self) -> SassResult<Stmt> {
|
||||||
todo!("@keyframes not yet implemented")
|
todo!("@keyframes not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: we should use a specialized struct to represent these
|
||||||
|
fn parse_media_args(&mut self) -> SassResult<String> {
|
||||||
|
let mut params = String::new();
|
||||||
|
self.whitespace();
|
||||||
|
while let Some(tok) = self.toks.next() {
|
||||||
|
match tok.kind {
|
||||||
|
'{' => break,
|
||||||
|
'#' => {
|
||||||
|
if let Some(Token { kind: '{', pos }) = self.toks.peek().cloned() {
|
||||||
|
self.toks.next();
|
||||||
|
self.span_before = pos;
|
||||||
|
let interpolation = self.parse_interpolation()?;
|
||||||
|
params.push_str(&interpolation.node.to_css_string(interpolation.span)?);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
params.push(tok.kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'\n' | ' ' | '\t' => {
|
||||||
|
self.whitespace();
|
||||||
|
params.push(' ');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
params.push(tok.kind);
|
||||||
|
}
|
||||||
|
Ok(params)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user