refactor parsing of media queries to use predicate parsing
This commit is contained in:
parent
d5b2410a8c
commit
be032b66f0
@ -1,9 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::SassResult,
|
error::SassResult,
|
||||||
utils::{
|
utils::{is_name_start, peek_ident_no_interpolation},
|
||||||
is_name_start, peek_ident_no_interpolation, read_until_closing_paren,
|
|
||||||
read_until_closing_quote,
|
|
||||||
},
|
|
||||||
{Cow, Token},
|
{Cow, Token},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -35,38 +32,25 @@ impl<'a> Parser<'a> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: replace with predicate
|
|
||||||
pub fn expression_until_comparison(&mut self) -> SassResult<Cow<'static, str>> {
|
pub fn expression_until_comparison(&mut self) -> SassResult<Cow<'static, str>> {
|
||||||
let mut toks = Vec::new();
|
let value = self.parse_value(false, &|toks| match toks.peek() {
|
||||||
while let Some(tok) = self.toks.peek().cloned() {
|
Some(Token { kind: '>', .. })
|
||||||
match tok.kind {
|
| Some(Token { kind: '<', .. })
|
||||||
'=' => {
|
| Some(Token { kind: ':', .. })
|
||||||
self.toks.advance_cursor();
|
| Some(Token { kind: ')', .. }) => true,
|
||||||
if matches!(self.toks.peek(), Some(Token { kind: '=', .. })) {
|
Some(Token { kind: '=', .. }) => {
|
||||||
self.toks.reset_cursor();
|
if matches!(toks.peek_next(), Some(Token { kind: '=', .. })) {
|
||||||
break;
|
toks.reset_cursor();
|
||||||
}
|
true
|
||||||
self.toks.reset_cursor();
|
} else {
|
||||||
toks.push(tok);
|
toks.reset_cursor();
|
||||||
toks.push(tok);
|
false
|
||||||
self.toks.next();
|
|
||||||
self.toks.next();
|
|
||||||
}
|
|
||||||
'>' | '<' | ':' | ')' => {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
'\'' | '"' => {
|
|
||||||
toks.push(tok);
|
|
||||||
self.toks.next();
|
|
||||||
toks.append(&mut read_until_closing_quote(self.toks, tok.kind)?);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
toks.push(tok);
|
|
||||||
self.toks.next();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
_ => false,
|
||||||
self.parse_value_as_string_from_vec(toks, false)
|
})?;
|
||||||
|
|
||||||
|
value.node.unquote().to_css_string(value.span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn parse_media_query_list(&mut self) -> SassResult<String> {
|
pub(super) fn parse_media_query_list(&mut self) -> SassResult<String> {
|
||||||
@ -85,13 +69,10 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
fn parse_media_feature(&mut self) -> SassResult<String> {
|
fn parse_media_feature(&mut self) -> SassResult<String> {
|
||||||
if let Some(Token { kind: '#', .. }) = self.toks.peek() {
|
if let Some(Token { kind: '#', .. }) = self.toks.peek() {
|
||||||
if let Some(Token { kind: '{', .. }) = self.toks.peek_forward(1) {
|
|
||||||
self.toks.next();
|
|
||||||
self.toks.next();
|
self.toks.next();
|
||||||
|
self.expect_char('{')?;
|
||||||
return Ok(self.parse_interpolation_as_string()?.into_owned());
|
return Ok(self.parse_interpolation_as_string()?.into_owned());
|
||||||
}
|
}
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
let mut buf = String::with_capacity(2);
|
let mut buf = String::with_capacity(2);
|
||||||
self.expect_char('(')?;
|
self.expect_char('(')?;
|
||||||
buf.push('(');
|
buf.push('(');
|
||||||
@ -105,13 +86,14 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
buf.push(':');
|
buf.push(':');
|
||||||
buf.push(' ');
|
buf.push(' ');
|
||||||
let mut toks = read_until_closing_paren(self.toks)?;
|
|
||||||
if let Some(tok) = toks.pop() {
|
let value = self.parse_value(false, &|toks| match toks.peek() {
|
||||||
if tok.kind != ')' {
|
Some(Token { kind: ')', .. }) => true,
|
||||||
todo!()
|
_ => false,
|
||||||
}
|
})?;
|
||||||
}
|
self.expect_char(')')?;
|
||||||
buf.push_str(&self.parse_value_as_string_from_vec(toks, true)?);
|
|
||||||
|
buf.push_str(&value.node.to_css_string(value.span)?);
|
||||||
|
|
||||||
self.whitespace_or_comment();
|
self.whitespace_or_comment();
|
||||||
buf.push(')');
|
buf.push(')');
|
||||||
|
@ -531,19 +531,7 @@ impl<'a> Parser<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_value_as_string_from_vec(
|
// todo: this should also consume silent comments
|
||||||
&mut self,
|
|
||||||
toks: Vec<Token>,
|
|
||||||
quoted: bool,
|
|
||||||
) -> SassResult<Cow<'static, str>> {
|
|
||||||
let value = self.parse_value_from_vec(toks, false)?;
|
|
||||||
if quoted {
|
|
||||||
value.node.to_css_string(value.span)
|
|
||||||
} else {
|
|
||||||
value.node.unquote().to_css_string(value.span)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn whitespace(&mut self) -> bool {
|
pub fn whitespace(&mut self) -> bool {
|
||||||
let mut found_whitespace = false;
|
let mut found_whitespace = false;
|
||||||
while let Some(tok) = self.toks.peek() {
|
while let Some(tok) = self.toks.peek() {
|
||||||
|
@ -72,3 +72,29 @@ test!(
|
|||||||
}",
|
}",
|
||||||
"@media foo and (bar) {\n a {\n color: red;\n }\n}\n"
|
"@media foo and (bar) {\n a {\n color: red;\n }\n}\n"
|
||||||
);
|
);
|
||||||
|
test!(
|
||||||
|
comparison_in_query,
|
||||||
|
"@media (100px < 400px) {
|
||||||
|
a {
|
||||||
|
interpolation: in-parens
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
"@media (100px < 400px) {\n a {\n interpolation: in-parens;\n }\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
interpolated_comparison_in_query,
|
||||||
|
"@media (#{100px < 400px}) {
|
||||||
|
a {
|
||||||
|
interpolation: in-parens
|
||||||
|
}
|
||||||
|
}",
|
||||||
|
"@media (true) {\n a {\n interpolation: in-parens;\n }\n}\n"
|
||||||
|
);
|
||||||
|
error!(
|
||||||
|
media_feature_missing_closing_paren,
|
||||||
|
"@media foo and (bar:a", "Error: expected \")\"."
|
||||||
|
);
|
||||||
|
error!(
|
||||||
|
media_feature_missing_curly_brace_after_hash,
|
||||||
|
"@media foo and # {}", "Error: expected \"{\"."
|
||||||
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user