diff --git a/src/parse/media.rs b/src/parse/media.rs index 7b443fd..f541847 100644 --- a/src/parse/media.rs +++ b/src/parse/media.rs @@ -1,9 +1,6 @@ use crate::{ error::SassResult, - utils::{ - is_name_start, peek_ident_no_interpolation, read_until_closing_paren, - read_until_closing_quote, - }, + utils::{is_name_start, peek_ident_no_interpolation}, {Cow, Token}, }; @@ -35,38 +32,25 @@ impl<'a> Parser<'a> { false } - // todo: replace with predicate pub fn expression_until_comparison(&mut self) -> SassResult> { - let mut toks = Vec::new(); - while let Some(tok) = self.toks.peek().cloned() { - match tok.kind { - '=' => { - self.toks.advance_cursor(); - if matches!(self.toks.peek(), Some(Token { kind: '=', .. })) { - self.toks.reset_cursor(); - break; - } - self.toks.reset_cursor(); - toks.push(tok); - toks.push(tok); - 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(); + let value = self.parse_value(false, &|toks| match toks.peek() { + Some(Token { kind: '>', .. }) + | Some(Token { kind: '<', .. }) + | Some(Token { kind: ':', .. }) + | Some(Token { kind: ')', .. }) => true, + Some(Token { kind: '=', .. }) => { + if matches!(toks.peek_next(), Some(Token { kind: '=', .. })) { + toks.reset_cursor(); + true + } else { + toks.reset_cursor(); + false } } - } - self.parse_value_as_string_from_vec(toks, false) + _ => false, + })?; + + value.node.unquote().to_css_string(value.span) } pub(super) fn parse_media_query_list(&mut self) -> SassResult { @@ -85,12 +69,9 @@ impl<'a> Parser<'a> { fn parse_media_feature(&mut self) -> SassResult { if let Some(Token { kind: '#', .. }) = self.toks.peek() { - if let Some(Token { kind: '{', .. }) = self.toks.peek_forward(1) { - self.toks.next(); - self.toks.next(); - return Ok(self.parse_interpolation_as_string()?.into_owned()); - } - todo!() + self.toks.next(); + self.expect_char('{')?; + return Ok(self.parse_interpolation_as_string()?.into_owned()); } let mut buf = String::with_capacity(2); self.expect_char('(')?; @@ -105,13 +86,14 @@ impl<'a> Parser<'a> { buf.push(':'); buf.push(' '); - let mut toks = read_until_closing_paren(self.toks)?; - if let Some(tok) = toks.pop() { - if tok.kind != ')' { - todo!() - } - } - buf.push_str(&self.parse_value_as_string_from_vec(toks, true)?); + + let value = self.parse_value(false, &|toks| match toks.peek() { + Some(Token { kind: ')', .. }) => true, + _ => false, + })?; + self.expect_char(')')?; + + buf.push_str(&value.node.to_css_string(value.span)?); self.whitespace_or_comment(); buf.push(')'); diff --git a/src/parse/mod.rs b/src/parse/mod.rs index f47aa5a..7385687 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -531,19 +531,7 @@ impl<'a> Parser<'a> { }) } - pub fn parse_value_as_string_from_vec( - &mut self, - toks: Vec, - quoted: bool, - ) -> SassResult> { - 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) - } - } - + // todo: this should also consume silent comments pub fn whitespace(&mut self) -> bool { let mut found_whitespace = false; while let Some(tok) = self.toks.peek() { diff --git a/tests/media.rs b/tests/media.rs index 33d751b..0c04adf 100644 --- a/tests/media.rs +++ b/tests/media.rs @@ -72,3 +72,29 @@ test!( }", "@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 \"{\"." +);