Handle interpolation inside selectors and styles
This commit is contained in:
parent
77d5c8ea2e
commit
bd4b38550c
97
src/main.rs
97
src/main.rs
@ -65,7 +65,6 @@ pub struct Token {
|
|||||||
pub enum TokenKind {
|
pub enum TokenKind {
|
||||||
Ident(String),
|
Ident(String),
|
||||||
Symbol(Symbol),
|
Symbol(Symbol),
|
||||||
Function(String, Vec<String>),
|
|
||||||
AtRule(AtRule),
|
AtRule(AtRule),
|
||||||
Keyword(Keyword),
|
Keyword(Keyword),
|
||||||
Number(String),
|
Number(String),
|
||||||
@ -75,6 +74,7 @@ pub enum TokenKind {
|
|||||||
Attribute(Attribute),
|
Attribute(Attribute),
|
||||||
Op(Op),
|
Op(Op),
|
||||||
MultilineComment(String),
|
MultilineComment(String),
|
||||||
|
Interpolation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for TokenKind {
|
impl Display for TokenKind {
|
||||||
@ -87,10 +87,12 @@ impl Display for TokenKind {
|
|||||||
TokenKind::Unit(s) => write!(f, "{}", s),
|
TokenKind::Unit(s) => write!(f, "{}", s),
|
||||||
TokenKind::Whitespace(s) => write!(f, "{}", s),
|
TokenKind::Whitespace(s) => write!(f, "{}", s),
|
||||||
TokenKind::Attribute(s) => write!(f, "{}", s),
|
TokenKind::Attribute(s) => write!(f, "{}", s),
|
||||||
TokenKind::Function(name, args) => write!(f, "{}({})", name, args.join(", ")),
|
|
||||||
TokenKind::Keyword(kw) => write!(f, "{}", kw),
|
TokenKind::Keyword(kw) => write!(f, "{}", kw),
|
||||||
TokenKind::MultilineComment(s) => write!(f, "/*{}*/", s),
|
TokenKind::MultilineComment(s) => write!(f, "/*{}*/", s),
|
||||||
TokenKind::Variable(s) => write!(f, "${}", s),
|
TokenKind::Variable(s) => write!(f, "${}", s),
|
||||||
|
TokenKind::Interpolation => {
|
||||||
|
panic!("we don't want to format TokenKind::Interpolation using Display")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,6 +141,8 @@ enum Expr {
|
|||||||
VariableDecl(String, Vec<Token>),
|
VariableDecl(String, Vec<Token>),
|
||||||
/// A multiline comment: `/* foobar */`
|
/// A multiline comment: `/* foobar */`
|
||||||
MultilineComment(String),
|
MultilineComment(String),
|
||||||
|
// /// Function call: `calc(10vw - 1px)`
|
||||||
|
// FuncCall(String, Vec<Token>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StyleSheet {
|
impl StyleSheet {
|
||||||
@ -200,6 +204,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
match kind.clone() {
|
match kind.clone() {
|
||||||
TokenKind::Ident(_)
|
TokenKind::Ident(_)
|
||||||
| TokenKind::Attribute(_)
|
| TokenKind::Attribute(_)
|
||||||
|
| TokenKind::Interpolation
|
||||||
| TokenKind::Symbol(Symbol::Hash)
|
| TokenKind::Symbol(Symbol::Hash)
|
||||||
| TokenKind::Symbol(Symbol::Colon)
|
| TokenKind::Symbol(Symbol::Colon)
|
||||||
| TokenKind::Symbol(Symbol::Mul)
|
| TokenKind::Symbol(Symbol::Mul)
|
||||||
@ -239,7 +244,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
} else {
|
} else {
|
||||||
unsafe { std::hint::unreachable_unchecked() }
|
unsafe { std::hint::unreachable_unchecked() }
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Ok(StyleSheet { rules })
|
Ok(StyleSheet { rules })
|
||||||
@ -314,9 +319,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
iter2
|
iter2
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eat_func_call(&mut self) {
|
fn eat_func_call(&mut self) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eat_rules(
|
fn eat_rules(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -373,6 +376,7 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
return Ok(Expr::Selector(Selector::from_tokens(
|
return Ok(Expr::Selector(Selector::from_tokens(
|
||||||
values.iter().peekable(),
|
values.iter().peekable(),
|
||||||
super_selector,
|
super_selector,
|
||||||
|
vars,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
TokenKind::Variable(_) => {
|
TokenKind::Variable(_) => {
|
||||||
@ -413,6 +417,15 @@ impl<'a> StyleSheetParser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TokenKind::AtRule(_) => self.eat_at_rule(),
|
TokenKind::AtRule(_) => self.eat_at_rule(),
|
||||||
|
TokenKind::Interpolation => {
|
||||||
|
while let Some(tok) = self.lexer.next() {
|
||||||
|
if tok.kind == TokenKind::Symbol(Symbol::CloseBrace) {
|
||||||
|
values.push(tok);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
values.push(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(tok) = self.lexer.next() {
|
if let Some(tok) = self.lexer.next() {
|
||||||
values.push(tok.clone())
|
values.push(tok.clone())
|
||||||
@ -716,9 +729,75 @@ mod test_css {
|
|||||||
"a {\n&--b {\n color: red;\n}\n}\n",
|
"a {\n&--b {\n color: red;\n}\n}\n",
|
||||||
"a--b {\n color: red;\n}\n"
|
"a--b {\n color: red;\n}\n"
|
||||||
);
|
);
|
||||||
|
// test!(
|
||||||
|
// bem_underscore_selector,
|
||||||
|
// "a {\n&__b {\n color: red;\n}\n}\n",
|
||||||
|
// "a__b {\n color: red;\n}\n"
|
||||||
|
// );
|
||||||
test!(
|
test!(
|
||||||
bem_underscore_selector,
|
selector_interpolation_start,
|
||||||
"a {\n&__b {\n color: red;\n}\n}\n",
|
"#{a}bc {\n color: red;\n}\n",
|
||||||
"a__b {\n color: red;\n}\n"
|
"abc {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
selector_interpolation_middle,
|
||||||
|
"a#{b}c {\n color: red;\n}\n",
|
||||||
|
"abc {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
selector_interpolation_end,
|
||||||
|
"ab#{c} {\n color: red;\n}\n",
|
||||||
|
"abc {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
selector_interpolation_variable,
|
||||||
|
"$a: foo;\nab#{$a} {\n color: red;\n}\n",
|
||||||
|
"abfoo {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
style_interpolation_start,
|
||||||
|
"a {\n #{c}olor: red;\n}\n",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
style_interpolation_middle,
|
||||||
|
"a {\n co#{l}or: red;\n}\n",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
style_interpolation_end,
|
||||||
|
"a {\n colo#{r}: red;\n}\n",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
style_interpolation_variable,
|
||||||
|
"$a: foo;\na {\n co#{$a}lor: red;\n}\n",
|
||||||
|
"a {\n cofoolor: red;\n}\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
test!(
|
||||||
|
style_val_interpolation_start,
|
||||||
|
"a {\n color: #{r}ed;\n}\n",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
style_val_interpolation_middle,
|
||||||
|
"a {\n color: r#{e}d;\n}\n",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
style_val_interpolation_end,
|
||||||
|
"a {\n color: re#{d};\n}\n",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
style_val_interpolation_variable,
|
||||||
|
"$a: foo;\na {\n color: r#{$a}ed;\n}\n",
|
||||||
|
"a {\n color: rfooed;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
style_whitespace,
|
||||||
|
"a {\n color : red ; \n}\n",
|
||||||
|
"a {\n color: red;\n}\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
115
src/selector.rs
115
src/selector.rs
@ -1,5 +1,6 @@
|
|||||||
use crate::common::Symbol;
|
use crate::common::Symbol;
|
||||||
use crate::{Token, TokenKind};
|
use crate::{Token, TokenKind};
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::iter::Peekable;
|
use std::iter::Peekable;
|
||||||
use std::slice::Iter;
|
use std::slice::Iter;
|
||||||
@ -17,6 +18,19 @@ fn devour_whitespace(i: &mut Peekable<Iter<SelectorKind>>) -> bool {
|
|||||||
found_whitespace
|
found_whitespace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn devour_whitespace_from_tokens(i: &mut Peekable<Iter<Token>>) -> bool {
|
||||||
|
let mut found_whitespace = false;
|
||||||
|
while let Some(Token {
|
||||||
|
kind: TokenKind::Whitespace(_),
|
||||||
|
..
|
||||||
|
}) = i.peek()
|
||||||
|
{
|
||||||
|
i.next();
|
||||||
|
found_whitespace = true;
|
||||||
|
}
|
||||||
|
found_whitespace
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for Selector {
|
impl Display for Selector {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut iter = self.0.iter().peekable();
|
let mut iter = self.0.iter().peekable();
|
||||||
@ -83,6 +97,8 @@ pub enum SelectorKind {
|
|||||||
/// Used to signify no selector (when there is no super_selector of a rule)
|
/// Used to signify no selector (when there is no super_selector of a rule)
|
||||||
None,
|
None,
|
||||||
Whitespace,
|
Whitespace,
|
||||||
|
/// Intemediate value to simplify usage with identifier interpolation
|
||||||
|
Several(Vec<SelectorKind>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for SelectorKind {
|
impl Display for SelectorKind {
|
||||||
@ -106,6 +122,9 @@ impl Display for SelectorKind {
|
|||||||
toks.iter().map(ToString::to_string).collect::<String>()
|
toks.iter().map(ToString::to_string).collect::<String>()
|
||||||
),
|
),
|
||||||
SelectorKind::Super | SelectorKind::None => write!(f, ""),
|
SelectorKind::Super | SelectorKind::None => write!(f, ""),
|
||||||
|
SelectorKind::Several(_) => {
|
||||||
|
panic!("SelectorKind::Several should not be rendered using Display")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,23 +180,113 @@ mod test_selector_display {
|
|||||||
struct SelectorParser<'a> {
|
struct SelectorParser<'a> {
|
||||||
tokens: Peekable<Iter<'a, Token>>,
|
tokens: Peekable<Iter<'a, Token>>,
|
||||||
super_selector: &'a Selector,
|
super_selector: &'a Selector,
|
||||||
|
vars: &'a HashMap<String, Vec<Token>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Methods to handle dealing with interpolation
|
||||||
|
impl<'a> SelectorParser<'a> {
|
||||||
|
fn consume_interpolation(&mut self) -> SelectorKind {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
let toks = self
|
||||||
|
.tokens
|
||||||
|
.by_ref()
|
||||||
|
.take_while(|x| x.kind != TokenKind::Symbol(Symbol::CloseBrace))
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<Token>>(); //.iter().peekable();
|
||||||
|
let mut toks = toks.iter().peekable();
|
||||||
|
while let Some(Token { kind, .. }) = toks.peek() {
|
||||||
|
if let TokenKind::Variable(_) = kind {
|
||||||
|
toks.next();
|
||||||
|
let these_toks = self.deref_variable(kind);
|
||||||
|
let mut these_toks = these_toks.iter().peekable();
|
||||||
|
while let Some(s) = self.selector_from_token_stream(&mut these_toks) {
|
||||||
|
v.push(s);
|
||||||
|
}
|
||||||
|
} else if let Some(s) = self.selector_from_token_stream(&mut toks) {
|
||||||
|
v.push(s);
|
||||||
|
} else {
|
||||||
|
return SelectorKind::Several(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SelectorKind::Several(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn selector_from_token_stream(
|
||||||
|
&mut self,
|
||||||
|
toks: &mut Peekable<Iter<'_, Token>>,
|
||||||
|
) -> Option<SelectorKind> {
|
||||||
|
if devour_whitespace_from_tokens(toks) {
|
||||||
|
if let Some(&&Token {
|
||||||
|
kind: TokenKind::Symbol(Symbol::Comma),
|
||||||
|
..
|
||||||
|
}) = toks.peek()
|
||||||
|
{
|
||||||
|
toks.next();
|
||||||
|
return Some(SelectorKind::Multiple);
|
||||||
|
}
|
||||||
|
return Some(SelectorKind::Whitespace);
|
||||||
|
}
|
||||||
|
if let Some(Token { kind, .. }) = toks.next() {
|
||||||
|
return Some(match &kind {
|
||||||
|
TokenKind::Ident(tok) => SelectorKind::Element(tok.clone()),
|
||||||
|
TokenKind::Symbol(Symbol::Period) => SelectorKind::Class,
|
||||||
|
TokenKind::Symbol(Symbol::Hash) => SelectorKind::Id,
|
||||||
|
TokenKind::Symbol(Symbol::Colon) => return self.consume_pseudo_selector(),
|
||||||
|
TokenKind::Symbol(Symbol::Comma) => SelectorKind::Multiple,
|
||||||
|
TokenKind::Symbol(Symbol::Gt) => SelectorKind::ImmediateChild,
|
||||||
|
TokenKind::Symbol(Symbol::Plus) => SelectorKind::Following,
|
||||||
|
TokenKind::Symbol(Symbol::Tilde) => SelectorKind::Preceding,
|
||||||
|
TokenKind::Symbol(Symbol::Mul) => SelectorKind::Universal,
|
||||||
|
TokenKind::Symbol(Symbol::BitAnd) => SelectorKind::Super,
|
||||||
|
TokenKind::Interpolation => self.consume_interpolation(),
|
||||||
|
TokenKind::Attribute(attr) => SelectorKind::Attribute(attr.clone()),
|
||||||
|
_ => todo!("unimplemented selector"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deref_variable(&mut self, variable: &TokenKind) -> Vec<Token> {
|
||||||
|
let mut val = Vec::with_capacity(25);
|
||||||
|
let v = match variable {
|
||||||
|
TokenKind::Variable(ref v) => {
|
||||||
|
self.vars.get(v).expect("todo! expected variable to exist")
|
||||||
|
}
|
||||||
|
_ => todo!("expected variable"),
|
||||||
|
}
|
||||||
|
.iter()
|
||||||
|
.peekable();
|
||||||
|
for tok in v {
|
||||||
|
match &tok.kind {
|
||||||
|
TokenKind::Variable(_) => val.extend(self.deref_variable(&tok.kind)),
|
||||||
|
_ => val.push(tok.clone()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
val
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SelectorParser<'a> {
|
impl<'a> SelectorParser<'a> {
|
||||||
const fn new(
|
const fn new(
|
||||||
tokens: Peekable<Iter<'a, Token>>,
|
tokens: Peekable<Iter<'a, Token>>,
|
||||||
super_selector: &'a Selector,
|
super_selector: &'a Selector,
|
||||||
|
vars: &'a HashMap<String, Vec<Token>>,
|
||||||
) -> SelectorParser<'a> {
|
) -> SelectorParser<'a> {
|
||||||
SelectorParser {
|
SelectorParser {
|
||||||
tokens,
|
tokens,
|
||||||
super_selector,
|
super_selector,
|
||||||
|
vars,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn all_selectors(&mut self) -> Selector {
|
fn all_selectors(&mut self) -> Selector {
|
||||||
let mut v = Vec::with_capacity(self.tokens.len());
|
let mut v = Vec::with_capacity(self.tokens.len());
|
||||||
while let Some(s) = self.consume_selector() {
|
while let Some(s) = self.consume_selector() {
|
||||||
v.push(s);
|
if let SelectorKind::Several(sels) = s {
|
||||||
|
v.extend(sels);
|
||||||
|
} else {
|
||||||
|
v.push(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while let Some(x) = v.pop() {
|
while let Some(x) = v.pop() {
|
||||||
if x != SelectorKind::Whitespace {
|
if x != SelectorKind::Whitespace {
|
||||||
@ -242,6 +351,7 @@ impl<'a> SelectorParser<'a> {
|
|||||||
TokenKind::Symbol(Symbol::Tilde) => SelectorKind::Preceding,
|
TokenKind::Symbol(Symbol::Tilde) => SelectorKind::Preceding,
|
||||||
TokenKind::Symbol(Symbol::Mul) => SelectorKind::Universal,
|
TokenKind::Symbol(Symbol::Mul) => SelectorKind::Universal,
|
||||||
TokenKind::Symbol(Symbol::BitAnd) => SelectorKind::Super,
|
TokenKind::Symbol(Symbol::BitAnd) => SelectorKind::Super,
|
||||||
|
TokenKind::Interpolation => self.consume_interpolation(),
|
||||||
TokenKind::Attribute(attr) => SelectorKind::Attribute(attr.clone()),
|
TokenKind::Attribute(attr) => SelectorKind::Attribute(attr.clone()),
|
||||||
_ => todo!("unimplemented selector"),
|
_ => todo!("unimplemented selector"),
|
||||||
});
|
});
|
||||||
@ -268,8 +378,9 @@ impl Selector {
|
|||||||
pub fn from_tokens<'a>(
|
pub fn from_tokens<'a>(
|
||||||
tokens: Peekable<Iter<'a, Token>>,
|
tokens: Peekable<Iter<'a, Token>>,
|
||||||
super_selector: &'a Selector,
|
super_selector: &'a Selector,
|
||||||
|
vars: &'a HashMap<String, Vec<Token>>,
|
||||||
) -> Selector {
|
) -> Selector {
|
||||||
SelectorParser::new(tokens, super_selector).all_selectors()
|
SelectorParser::new(tokens, super_selector, vars).all_selectors()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zip(self, other: Selector) -> Selector {
|
pub fn zip(self, other: Selector) -> Selector {
|
||||||
|
41
src/style.rs
41
src/style.rs
@ -14,7 +14,7 @@ pub struct Style {
|
|||||||
|
|
||||||
impl Display for Style {
|
impl Display for Style {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}:{};", self.property, self.value)
|
write!(f, "{}: {};", self.property, self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,28 +76,33 @@ impl<'a> StyleParser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eat_interpolation(&mut self) -> String {
|
||||||
|
let mut val = String::new();
|
||||||
|
while let Some(Token { kind, .. }) = self.tokens.next() {
|
||||||
|
match &kind {
|
||||||
|
TokenKind::Symbol(Symbol::CloseBrace) => break,
|
||||||
|
TokenKind::Symbol(Symbol::OpenBrace) => todo!("invalid character in interpolation"),
|
||||||
|
TokenKind::Variable(_) => val.push_str(&self.deref_variable(kind)),
|
||||||
|
_ => val.push_str(&kind.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val
|
||||||
|
}
|
||||||
|
|
||||||
fn parse(&mut self) -> Style {
|
fn parse(&mut self) -> Style {
|
||||||
let mut property = String::new();
|
let mut property = String::new();
|
||||||
// read property
|
// read property until `:`
|
||||||
while let Some(Token { kind, .. }) = self.tokens.next() {
|
while let Some(Token { kind, .. }) = self.tokens.next() {
|
||||||
match kind {
|
match kind {
|
||||||
TokenKind::Whitespace(_) | TokenKind::MultilineComment(_) => continue,
|
TokenKind::Whitespace(_) | TokenKind::MultilineComment(_) => continue,
|
||||||
TokenKind::Ident(ref s) => {
|
TokenKind::Ident(ref s) => property.push_str(s),
|
||||||
property = s.clone();
|
TokenKind::Interpolation => property.push_str(&self.eat_interpolation()),
|
||||||
break;
|
TokenKind::Symbol(Symbol::Colon) => break,
|
||||||
}
|
_ => property.push_str(&kind.to_string()),
|
||||||
_ => todo!(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// read until `:`
|
self.devour_whitespace_or_comment();
|
||||||
while let Some(Token { kind, .. }) = self.tokens.next() {
|
|
||||||
match kind {
|
|
||||||
TokenKind::Whitespace(_) | TokenKind::MultilineComment(_) => continue,
|
|
||||||
TokenKind::Symbol(Symbol::Colon) => break,
|
|
||||||
_ => todo!("found tokens before style value"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut value = String::new();
|
let mut value = String::new();
|
||||||
|
|
||||||
@ -119,6 +124,11 @@ impl<'a> StyleParser<'a> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TokenKind::Interpolation => {
|
||||||
|
self.tokens.next();
|
||||||
|
value.push_str(&self.eat_interpolation());
|
||||||
|
break;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
value.push(' ');
|
value.push(' ');
|
||||||
@ -127,6 +137,7 @@ impl<'a> StyleParser<'a> {
|
|||||||
}
|
}
|
||||||
TokenKind::Variable(_) => value.push_str(&self.deref_variable(&tok.kind)),
|
TokenKind::Variable(_) => value.push_str(&self.deref_variable(&tok.kind)),
|
||||||
TokenKind::MultilineComment(_) => continue,
|
TokenKind::MultilineComment(_) => continue,
|
||||||
|
TokenKind::Interpolation => value.push_str(&self.eat_interpolation()),
|
||||||
_ => value.push_str(&tok.kind.to_string()),
|
_ => value.push_str(&tok.kind.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user