Handle curly braces in quotes in styles
This commit is contained in:
parent
c2e339fb5b
commit
8c6be57872
@ -100,6 +100,13 @@ impl Token {
|
||||
pub fn equals_symbol(&self, s: Symbol) -> bool {
|
||||
self.kind.equals_symbol(s)
|
||||
}
|
||||
|
||||
pub fn from_string(s: String) -> Self {
|
||||
Token {
|
||||
kind: TokenKind::Ident(s),
|
||||
pos: Pos::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IsWhitespace for Token {
|
||||
|
28
src/style.rs
28
src/style.rs
@ -1,7 +1,7 @@
|
||||
use crate::common::{Pos, Scope, Symbol};
|
||||
use crate::error::SassResult;
|
||||
use crate::selector::Selector;
|
||||
use crate::utils::{devour_whitespace, parse_interpolation};
|
||||
use crate::utils::{devour_whitespace, parse_interpolation, parse_quoted_string};
|
||||
use crate::value::Value;
|
||||
use crate::{Expr, Token, TokenKind};
|
||||
use std::fmt::{self, Display};
|
||||
@ -35,7 +35,7 @@ impl Style {
|
||||
scope: &Scope,
|
||||
super_selector: &Selector,
|
||||
) -> SassResult<Value> {
|
||||
StyleParser::new(scope, super_selector).parse_style_value(toks)
|
||||
StyleParser::new(scope, super_selector).parse_style_value(toks, scope)
|
||||
}
|
||||
|
||||
pub fn from_tokens<I: Iterator<Item = Token>>(
|
||||
@ -44,7 +44,7 @@ impl Style {
|
||||
super_selector: &Selector,
|
||||
super_property: String,
|
||||
) -> SassResult<Expr> {
|
||||
StyleParser::new(scope, super_selector).eat_style_group(toks, super_property)
|
||||
StyleParser::new(scope, super_selector).eat_style_group(toks, super_property, scope)
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +64,7 @@ impl<'a> StyleParser<'a> {
|
||||
pub(crate) fn parse_style_value<I: Iterator<Item = Token>>(
|
||||
&self,
|
||||
toks: &mut Peekable<I>,
|
||||
scope: &Scope,
|
||||
) -> SassResult<Value> {
|
||||
let mut style = Vec::new();
|
||||
let mut n = 0;
|
||||
@ -83,6 +84,16 @@ impl<'a> StyleParser<'a> {
|
||||
n -= 1;
|
||||
}
|
||||
}
|
||||
ref q @ TokenKind::Symbol(Symbol::DoubleQuote)
|
||||
| ref q @ TokenKind::Symbol(Symbol::SingleQuote) => {
|
||||
let q = q.clone();
|
||||
let tok = toks.next().unwrap();
|
||||
style.push(tok.clone());
|
||||
style.push(Token::from_string(
|
||||
parse_quoted_string(toks, scope, q)?.unquote().to_string(),
|
||||
));
|
||||
style.push(tok);
|
||||
}
|
||||
TokenKind::Symbol(Symbol::OpenCurlyBrace)
|
||||
| TokenKind::Symbol(Symbol::SemiColon) => break,
|
||||
TokenKind::Symbol(Symbol::BitAnd) => {
|
||||
@ -104,6 +115,7 @@ impl<'a> StyleParser<'a> {
|
||||
&self,
|
||||
toks: &mut Peekable<I>,
|
||||
super_property: String,
|
||||
scope: &Scope,
|
||||
) -> SassResult<Expr> {
|
||||
let mut styles = Vec::new();
|
||||
devour_whitespace(toks);
|
||||
@ -116,7 +128,7 @@ impl<'a> StyleParser<'a> {
|
||||
let property = self.parse_property(toks, super_property.clone())?;
|
||||
if let Some(tok) = toks.peek() {
|
||||
if tok.equals_symbol(Symbol::OpenCurlyBrace) {
|
||||
match self.eat_style_group(toks, property)? {
|
||||
match self.eat_style_group(toks, property, scope)? {
|
||||
Expr::Styles(s) => styles.extend(s),
|
||||
Expr::Style(s) => styles.push(*s),
|
||||
_ => unreachable!(),
|
||||
@ -134,7 +146,7 @@ impl<'a> StyleParser<'a> {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let value = self.parse_style_value(toks)?;
|
||||
let value = self.parse_style_value(toks, scope)?;
|
||||
match toks.peek().unwrap().kind {
|
||||
TokenKind::Symbol(Symbol::CloseCurlyBrace) => {
|
||||
styles.push(Style { property, value });
|
||||
@ -149,7 +161,7 @@ impl<'a> StyleParser<'a> {
|
||||
property: property.clone(),
|
||||
value,
|
||||
});
|
||||
match self.eat_style_group(toks, property)? {
|
||||
match self.eat_style_group(toks, property, scope)? {
|
||||
Expr::Style(s) => styles.push(*s),
|
||||
Expr::Styles(s) => styles.extend(s),
|
||||
_ => unreachable!(),
|
||||
@ -173,7 +185,7 @@ impl<'a> StyleParser<'a> {
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let val = self.parse_style_value(toks)?;
|
||||
let val = self.parse_style_value(toks, scope)?;
|
||||
match toks.peek().unwrap().kind {
|
||||
TokenKind::Symbol(Symbol::CloseCurlyBrace) => {}
|
||||
TokenKind::Symbol(Symbol::SemiColon) => {
|
||||
@ -185,7 +197,7 @@ impl<'a> StyleParser<'a> {
|
||||
property: super_property.clone(),
|
||||
value: val,
|
||||
}];
|
||||
match self.eat_style_group(toks, super_property)? {
|
||||
match self.eat_style_group(toks, super_property, scope)? {
|
||||
Expr::Style(s) => v.push(*s),
|
||||
Expr::Styles(s) => v.extend(s),
|
||||
_ => unreachable!(),
|
||||
|
22
src/utils.rs
22
src/utils.rs
@ -171,14 +171,26 @@ pub(crate) fn parse_quoted_string<I: Iterator<Item = Token>>(
|
||||
{
|
||||
break
|
||||
}
|
||||
TokenKind::Symbol(Symbol::DoubleQuote) if is_escaped => {
|
||||
s.push('\\');
|
||||
s.push('"');
|
||||
is_escaped = false;
|
||||
continue;
|
||||
}
|
||||
TokenKind::Symbol(Symbol::SingleQuote)
|
||||
if !is_escaped && q == TokenKind::Symbol(Symbol::SingleQuote) =>
|
||||
{
|
||||
break
|
||||
}
|
||||
TokenKind::Symbol(Symbol::SingleQuote) if is_escaped => {
|
||||
s.push('\\');
|
||||
s.push('\'');
|
||||
is_escaped = false;
|
||||
continue;
|
||||
}
|
||||
TokenKind::Symbol(Symbol::BackSlash) if !is_escaped => is_escaped = true,
|
||||
TokenKind::Symbol(Symbol::BackSlash) => s.push('\\'),
|
||||
TokenKind::Interpolation => {
|
||||
TokenKind::Interpolation if !is_escaped => {
|
||||
found_interpolation = true;
|
||||
s.push_str(
|
||||
&parse_interpolation(toks, scope)?
|
||||
@ -188,13 +200,21 @@ pub(crate) fn parse_quoted_string<I: Iterator<Item = Token>>(
|
||||
);
|
||||
continue;
|
||||
}
|
||||
TokenKind::Interpolation => {
|
||||
s.push('#');
|
||||
s.push('{');
|
||||
is_escaped = false;
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if is_escaped && tok.kind != TokenKind::Symbol(Symbol::BackSlash) {
|
||||
is_escaped = false;
|
||||
}
|
||||
if tok.kind != TokenKind::Symbol(Symbol::BackSlash) {
|
||||
s.push_str(&tok.kind.to_string());
|
||||
}
|
||||
}
|
||||
let quotes = if found_interpolation {
|
||||
QuoteKind::Double
|
||||
} else {
|
||||
|
@ -141,3 +141,9 @@ test!(
|
||||
"foo {\n a: b {\n c: d {\n e: f;\n }\n }\n}\n",
|
||||
"foo {\n a: b;\n a-c: d;\n a-c-e: f;\n}\n"
|
||||
);
|
||||
test!(curly_braces_in_quotes, "a {\n color: \"{foo}\";\n}\n");
|
||||
test!(
|
||||
escaped_interpolation,
|
||||
"a {\n color: \"\\#{foo}\";\n}\n",
|
||||
"a {\n color: \"#{foo}\";\n}\n"
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user