more robustly handle escaping
This commit is contained in:
parent
680790c49a
commit
34b886b758
22
src/lib.rs
22
src/lib.rs
@ -99,7 +99,7 @@ use crate::style::Style;
|
|||||||
pub(crate) use crate::token::Token;
|
pub(crate) use crate::token::Token;
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
devour_whitespace, eat_comment, eat_ident, eat_ident_no_interpolation, eat_variable_value,
|
devour_whitespace, eat_comment, eat_ident, eat_ident_no_interpolation, eat_variable_value,
|
||||||
parse_quoted_string, read_until_newline, VariableDecl,
|
parse_quoted_string, read_until_closing_curly_brace, read_until_newline, VariableDecl,
|
||||||
};
|
};
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
|
|
||||||
@ -676,7 +676,8 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
|||||||
values.push(toks.next().unwrap());
|
values.push(toks.next().unwrap());
|
||||||
if toks.peek().unwrap().kind == '{' {
|
if toks.peek().unwrap().kind == '{' {
|
||||||
values.push(toks.next().unwrap());
|
values.push(toks.next().unwrap());
|
||||||
values.extend(eat_interpolation(toks));
|
values.extend(read_until_closing_curly_brace(toks));
|
||||||
|
values.push(toks.next().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'\\' => {
|
'\\' => {
|
||||||
@ -689,23 +690,6 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eat_interpolation<I: Iterator<Item = Token>>(toks: &mut PeekMoreIterator<I>) -> Vec<Token> {
|
|
||||||
let mut vals = Vec::new();
|
|
||||||
let mut n = 1;
|
|
||||||
for tok in toks {
|
|
||||||
match tok.kind {
|
|
||||||
'{' => n += 1,
|
|
||||||
'}' => n -= 1,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
vals.push(tok);
|
|
||||||
if n == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vals
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Functions that print to stdout or stderr
|
/// Functions that print to stdout or stderr
|
||||||
impl<'a> StyleSheetParser<'a> {
|
impl<'a> StyleSheetParser<'a> {
|
||||||
fn debug(&self, span: Span, message: &str) {
|
fn debug(&self, span: Span, message: &str) {
|
||||||
|
@ -12,7 +12,7 @@ use super::{devour_whitespace, read_until_newline};
|
|||||||
pub(crate) fn read_until_open_curly_brace<I: Iterator<Item = Token>>(
|
pub(crate) fn read_until_open_curly_brace<I: Iterator<Item = Token>>(
|
||||||
toks: &mut PeekMoreIterator<I>,
|
toks: &mut PeekMoreIterator<I>,
|
||||||
) -> Vec<Token> {
|
) -> Vec<Token> {
|
||||||
let mut val = Vec::new();
|
let mut t = Vec::new();
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
while let Some(tok) = toks.peek() {
|
while let Some(tok) = toks.peek() {
|
||||||
match tok.kind {
|
match tok.kind {
|
||||||
@ -22,19 +22,25 @@ pub(crate) fn read_until_open_curly_brace<I: Iterator<Item = Token>>(
|
|||||||
let next = toks.next().unwrap();
|
let next = toks.next().unwrap();
|
||||||
match toks.peek().unwrap().kind {
|
match toks.peek().unwrap().kind {
|
||||||
'/' => read_until_newline(toks),
|
'/' => read_until_newline(toks),
|
||||||
_ => val.push(next),
|
_ => t.push(next),
|
||||||
};
|
};
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
'\\' => {
|
||||||
|
t.push(toks.next().unwrap());
|
||||||
|
if toks.peek().is_some() {
|
||||||
|
t.push(toks.next().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if n == 1 {
|
if n == 1 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
val.push(toks.next().unwrap());
|
t.push(toks.next().unwrap());
|
||||||
}
|
}
|
||||||
val
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_until_closing_curly_brace<I: Iterator<Item = Token>>(
|
pub(crate) fn read_until_closing_curly_brace<I: Iterator<Item = Token>>(
|
||||||
@ -72,6 +78,12 @@ pub(crate) fn read_until_closing_curly_brace<I: Iterator<Item = Token>>(
|
|||||||
t.push(toks.next().unwrap());
|
t.push(toks.next().unwrap());
|
||||||
t.extend(read_until_closing_paren(toks));
|
t.extend(read_until_closing_paren(toks));
|
||||||
}
|
}
|
||||||
|
'\\' => {
|
||||||
|
t.push(toks.next().unwrap());
|
||||||
|
if toks.peek().is_some() {
|
||||||
|
t.push(toks.next().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => t.push(toks.next().unwrap()),
|
_ => t.push(toks.next().unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,8 +108,10 @@ pub(crate) fn read_until_closing_quote<I: Iterator<Item = Token>>(
|
|||||||
}
|
}
|
||||||
'\\' => {
|
'\\' => {
|
||||||
t.push(tok);
|
t.push(tok);
|
||||||
|
if toks.peek().is_some() {
|
||||||
t.push(toks.next().unwrap());
|
t.push(toks.next().unwrap());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
'#' => {
|
'#' => {
|
||||||
t.push(tok);
|
t.push(tok);
|
||||||
let next = toks.peek().unwrap();
|
let next = toks.peek().unwrap();
|
||||||
@ -124,8 +138,10 @@ pub(crate) fn read_until_semicolon_or_closing_curly_brace<I: Iterator<Item = Tok
|
|||||||
}
|
}
|
||||||
'\\' => {
|
'\\' => {
|
||||||
t.push(toks.next().unwrap());
|
t.push(toks.next().unwrap());
|
||||||
|
if toks.peek().is_some() {
|
||||||
t.push(toks.next().unwrap());
|
t.push(toks.next().unwrap());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
'"' | '\'' => {
|
'"' | '\'' => {
|
||||||
let quote = toks.next().unwrap();
|
let quote = toks.next().unwrap();
|
||||||
t.push(quote);
|
t.push(quote);
|
||||||
@ -170,8 +186,10 @@ pub(crate) fn read_until_semicolon_or_open_or_closing_curly_brace<I: Iterator<It
|
|||||||
}
|
}
|
||||||
'\\' => {
|
'\\' => {
|
||||||
t.push(toks.next().unwrap());
|
t.push(toks.next().unwrap());
|
||||||
|
if toks.peek().is_some() {
|
||||||
t.push(toks.next().unwrap());
|
t.push(toks.next().unwrap());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
'"' | '\'' => {
|
'"' | '\'' => {
|
||||||
let quote = toks.next().unwrap();
|
let quote = toks.next().unwrap();
|
||||||
t.push(quote);
|
t.push(quote);
|
||||||
@ -224,55 +242,68 @@ pub(crate) fn read_until_semicolon_or_open_or_closing_curly_brace<I: Iterator<It
|
|||||||
pub(crate) fn read_until_closing_paren<I: Iterator<Item = Token>>(
|
pub(crate) fn read_until_closing_paren<I: Iterator<Item = Token>>(
|
||||||
toks: &mut PeekMoreIterator<I>,
|
toks: &mut PeekMoreIterator<I>,
|
||||||
) -> Vec<Token> {
|
) -> Vec<Token> {
|
||||||
let mut v = Vec::new();
|
let mut t = Vec::new();
|
||||||
let mut scope = 0;
|
let mut scope = 0;
|
||||||
while let Some(tok) = toks.next() {
|
while let Some(tok) = toks.next() {
|
||||||
match tok.kind {
|
match tok.kind {
|
||||||
')' => {
|
')' => {
|
||||||
if scope < 1 {
|
if scope < 1 {
|
||||||
v.push(tok);
|
t.push(tok);
|
||||||
return v;
|
return t;
|
||||||
} else {
|
} else {
|
||||||
scope -= 1;
|
scope -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'(' => scope += 1,
|
'(' => scope += 1,
|
||||||
'"' | '\'' => {
|
'"' | '\'' => {
|
||||||
v.push(tok);
|
t.push(tok);
|
||||||
v.extend(read_until_closing_quote(toks, tok.kind));
|
t.extend(read_until_closing_quote(toks, tok.kind));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
'\\' => {
|
||||||
|
t.push(tok);
|
||||||
|
if toks.peek().is_some() {
|
||||||
|
t.push(toks.next().unwrap());
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
v.push(tok)
|
t.push(tok)
|
||||||
}
|
}
|
||||||
v
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn read_until_closing_square_brace<I: Iterator<Item = Token>>(
|
pub(crate) fn read_until_closing_square_brace<I: Iterator<Item = Token>>(
|
||||||
toks: &mut PeekMoreIterator<I>,
|
toks: &mut PeekMoreIterator<I>,
|
||||||
) -> Vec<Token> {
|
) -> Vec<Token> {
|
||||||
let mut v = Vec::new();
|
let mut t = Vec::new();
|
||||||
let mut scope = 0;
|
let mut scope = 0;
|
||||||
while let Some(tok) = toks.next() {
|
while let Some(tok) = toks.next() {
|
||||||
match tok.kind {
|
match tok.kind {
|
||||||
']' => {
|
']' => {
|
||||||
if scope < 1 {
|
if scope < 1 {
|
||||||
v.push(tok);
|
t.push(tok);
|
||||||
return v;
|
return t;
|
||||||
} else {
|
} else {
|
||||||
scope -= 1;
|
scope -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'[' => scope += 1,
|
'[' => scope += 1,
|
||||||
'"' | '\'' => {
|
'"' | '\'' => {
|
||||||
v.push(tok);
|
t.push(tok);
|
||||||
v.extend(read_until_closing_quote(toks, tok.kind));
|
t.extend(read_until_closing_quote(toks, tok.kind));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
'\\' => {
|
||||||
|
t.push(tok);
|
||||||
|
if toks.peek().is_some() {
|
||||||
|
t.push(toks.next().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
v.push(tok)
|
t.push(tok)
|
||||||
}
|
}
|
||||||
v
|
t
|
||||||
}
|
}
|
||||||
|
@ -58,3 +58,13 @@ test!(
|
|||||||
"a {\n color: #{\"\\a\"};\n}\n",
|
"a {\n color: #{\"\\a\"};\n}\n",
|
||||||
"a {\n color: ;\n}\n"
|
"a {\n color: ;\n}\n"
|
||||||
);
|
);
|
||||||
|
test!(
|
||||||
|
interpolate_escaped_quotes,
|
||||||
|
"a {\n color: #{\\\"\\'};\n}\n",
|
||||||
|
"a {\n color: \\\"\\';\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
interpolate_escaped_quotes_in_quotes,
|
||||||
|
"a {\n color: \"#{\\\"\\'}\";\n}\n",
|
||||||
|
"a {\n color: \"\\\\\\\"\\\\'\";\n}\n"
|
||||||
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user