diff --git a/src/builtin/meta.rs b/src/builtin/meta.rs index f97d008..f2eaf5c 100644 --- a/src/builtin/meta.rs +++ b/src/builtin/meta.rs @@ -71,7 +71,7 @@ pub(crate) fn register(f: &mut HashMap) { .into()) } }; - Ok(Value::Ident(unit, QuoteKind::Double)) + Ok(Value::Ident(unit, QuoteKind::Quoted)) }), ); f.insert( diff --git a/src/builtin/string.rs b/src/builtin/string.rs index 2d42b29..95fda11 100644 --- a/src/builtin/string.rs +++ b/src/builtin/string.rs @@ -71,7 +71,7 @@ pub(crate) fn register(f: &mut HashMap) { Builtin::new(|mut args, scope, super_selector| { max_args!(args, 1); match arg!(args, scope, super_selector, 0, "string") { - Value::Ident(i, _) => Ok(Value::Ident(i, QuoteKind::Double)), + Value::Ident(i, _) => Ok(Value::Ident(i, QuoteKind::Quoted)), v => Err(( format!( "$string: {} is not a string.", @@ -191,7 +191,7 @@ pub(crate) fn register(f: &mut HashMap) { } if start > end || start > str_len { - Ok(Value::Ident(String::new(), quotes.normalize())) + Ok(Value::Ident(String::new(), quotes)) } else { Ok(Value::Ident( string @@ -199,7 +199,7 @@ pub(crate) fn register(f: &mut HashMap) { .skip(start - 1) .take(end - start + 1) .collect(), - quotes.normalize(), + quotes, )) } }), @@ -247,7 +247,7 @@ pub(crate) fn register(f: &mut HashMap) { Builtin::new(|mut args, scope, super_selector| { max_args!(args, 3); let (s1, quotes) = match arg!(args, scope, super_selector, 0, "string") { - Value::Ident(i, q) => (i, q.normalize()), + Value::Ident(i, q) => (i, q), v => { return Err(( format!( diff --git a/src/common.rs b/src/common.rs index bd3f970..b9e60b7 100644 --- a/src/common.rs +++ b/src/common.rs @@ -63,28 +63,15 @@ impl Op { #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub(crate) enum QuoteKind { - Single, - Double, + Quoted, None, } -impl QuoteKind { - /// SASS will prefer double quotes over single quotes after - /// operations, e.g. `'foo' + red` => `"foored"` - pub fn normalize(self) -> QuoteKind { - match self { - QuoteKind::Double | QuoteKind::Single => QuoteKind::Double, - QuoteKind::None => QuoteKind::None, - } - } -} - impl Display for QuoteKind { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::Single => write!(f, "'"), - Self::Double => write!(f, "\""), + Self::Quoted => write!(f, "\""), Self::None => write!(f, ""), } } diff --git a/src/utils.rs b/src/utils.rs index d50eccc..46ecb08 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -585,7 +585,6 @@ pub(crate) fn parse_quoted_string>( ) -> SassResult> { let mut s = String::new(); let mut is_escaped = false; - let mut found_interpolation = false; let mut span = if let Some(tok) = toks.peek() { tok.pos() } else { @@ -615,7 +614,6 @@ pub(crate) fn parse_quoted_string>( '#' if !is_escaped => { if toks.peek().unwrap().kind == '{' { toks.next(); - found_interpolation = true; let interpolation = parse_interpolation(toks, scope, super_selector)?; s.push_str(&interpolation.node.to_css_string(interpolation.span)?); continue; @@ -657,17 +655,8 @@ pub(crate) fn parse_quoted_string>( s.push_str(&tok.kind.to_string()); } } - let quotes = if found_interpolation { - QuoteKind::Double - } else { - match q { - '"' => QuoteKind::Double, - '\'' => QuoteKind::Single, - _ => unreachable!(), - } - }; Ok(Spanned { - node: Value::Ident(s, quotes), + node: Value::Ident(s, QuoteKind::Quoted), span, }) } diff --git a/src/value/mod.rs b/src/value/mod.rs index 9eeff7e..f9e1ab7 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -95,10 +95,8 @@ impl Value { format!("{}", self.clone().eval(span)?.to_css_string(span)?) } Self::Paren(val) => format!("{}", val.to_css_string(span)?), - Self::Ident(val, kind) => { - if kind == &QuoteKind::None { - return Ok(val.clone()); - } + Self::Ident(val, QuoteKind::None) => return Ok(val.clone()), + Self::Ident(val, QuoteKind::Quoted) => { let has_single_quotes = val.contains(|x| x == '\''); let has_double_quotes = val.contains(|x| x == '"'); if has_single_quotes && !has_double_quotes { @@ -108,23 +106,18 @@ impl Value { } else if !has_single_quotes && !has_double_quotes { format!("\"{}\"", val) } else { - let quote_char = match kind { - QuoteKind::Double => '"', - QuoteKind::Single => '\'', - _ => unreachable!(), - }; let mut buf = String::with_capacity(val.len() + 2); - buf.push(quote_char); + buf.push('"'); for c in val.chars() { match c { - '"' | '\'' if c == quote_char => { + '"' => { buf.push('\\'); - buf.push(quote_char); + buf.push('"'); } v => buf.push(v), } } - buf.push(quote_char); + buf.push('"'); buf } } diff --git a/src/value/ops.rs b/src/value/ops.rs index 9b7fc48..9e2a330 100644 --- a/src/value/ops.rs +++ b/src/value/ops.rs @@ -14,12 +14,10 @@ impl Value { Ok(match self { Self::Function(..) | Self::ArgList(..) | Self::Map(..) => todo!(), Self::Important | Self::True | Self::False => match other { - Self::Ident(s, QuoteKind::Double) | Self::Ident(s, QuoteKind::Single) => { - Value::Ident( - format!("{}{}", self.to_css_string(span)?, s), - QuoteKind::Double, - ) - } + Self::Ident(s, QuoteKind::Quoted) => Value::Ident( + format!("{}{}", self.to_css_string(span)?, s), + QuoteKind::Quoted, + ), Self::Null => Value::Ident(self.to_css_string(span)?, QuoteKind::None), _ => Value::Ident( format!( @@ -56,7 +54,7 @@ impl Value { ) } } - Self::Ident(s, q) => Value::Ident(format!("{}{}{}", num, unit, s), q.normalize()), + Self::Ident(s, q) => Value::Ident(format!("{}{}{}", num, unit, s), q), Self::Null => Value::Ident(format!("{}{}", num, unit), QuoteKind::None), Self::List(..) => Value::Ident( format!("{}{}{}", num, unit, other.to_css_string(span)?), @@ -76,7 +74,7 @@ impl Value { } }, Self::Color(c) => match other { - Self::Ident(s, q) => Value::Ident(format!("{}{}", c, s), q.normalize()), + Self::Ident(s, q) => Value::Ident(format!("{}{}", c, s), q), Self::Null => Value::Ident(c.to_string(), QuoteKind::None), Self::List(..) => Value::Ident( format!("{}{}", c, other.to_css_string(span)?), @@ -116,13 +114,12 @@ impl Value { } Self::UnaryOp(..) | Self::Paren(..) => self.eval(span)?.node.add(other, span)?, Self::Ident(s1, quotes1) => match other { - Self::Ident(s2, _) => Value::Ident(format!("{}{}", s1, s2), quotes1.normalize()), - Self::Important | Self::True | Self::False | Self::Dimension(..) => Value::Ident( - format!("{}{}", s1, other.to_css_string(span)?), - quotes1.normalize(), - ), - Self::Null => Value::Ident(s1, quotes1.normalize()), - Self::Color(c) => Value::Ident(format!("{}{}", s1, c), quotes1.normalize()), + Self::Ident(s2, _) => Value::Ident(format!("{}{}", s1, s2), quotes1), + Self::Important | Self::True | Self::False | Self::Dimension(..) => { + Value::Ident(format!("{}{}", s1, other.to_css_string(span)?), quotes1) + } + Self::Null => Value::Ident(s1, quotes1), + Self::Color(c) => Value::Ident(format!("{}{}", s1, c), quotes1), Self::List(..) => { Value::Ident(format!("{}{}", s1, other.to_css_string(span)?), quotes1) } @@ -131,9 +128,7 @@ impl Value { Self::Function(..) | Self::ArgList(..) | Self::Map(..) => todo!(), }, Self::List(..) => match other { - Self::Ident(s, q) => { - Value::Ident(format!("{}{}", self.to_css_string(span)?, s), q.normalize()) - } + Self::Ident(s, q) => Value::Ident(format!("{}{}", self.to_css_string(span)?, s), q), Self::Paren(..) => (self.add(other.eval(span)?.node, span))?, _ => Value::Ident( format!( @@ -187,10 +182,9 @@ impl Value { _ => todo!(), }, Self::Color(c) => match other { - Self::Ident(s, q) => Value::Ident( - format!("{}-{}{}{}", c, q.normalize(), s, q.normalize()), - QuoteKind::None, - ), + Self::Ident(s, q) => { + Value::Ident(format!("{}-{}{}{}", c, q, s, q), QuoteKind::None) + } Self::Null => Value::Ident(format!("{}-", c), QuoteKind::None), Self::Dimension(..) | Self::Color(..) => { return Err(( @@ -231,15 +225,7 @@ impl Value { Self::Paren(..) => self.eval(span)?.node.sub(other, span)?, Self::Ident(s1, q1) => match other { Self::Ident(s2, q2) => Value::Ident( - format!( - "{}{}{}-{}{}{}", - q1.normalize(), - s1, - q1.normalize(), - q2.normalize(), - s2, - q2.normalize() - ), + format!("{}{}{}-{}{}{}", q1, s1, q1, q2, s2, q2), QuoteKind::None, ), Self::Important @@ -247,40 +233,19 @@ impl Value { | Self::False | Self::Dimension(..) | Self::Color(..) => Value::Ident( - format!( - "{}{}{}-{}", - q1.normalize(), - s1, - q1.normalize(), - other.to_css_string(span)? - ), - QuoteKind::None, - ), - Self::Null => Value::Ident( - format!("{}{}{}-", q1.normalize(), s1, q1.normalize()), + format!("{}{}{}-{}", q1, s1, q1, other.to_css_string(span)?), QuoteKind::None, ), + Self::Null => Value::Ident(format!("{}{}{}-", q1, s1, q1), QuoteKind::None), Self::List(..) => Value::Ident( - format!( - "{}{}{}-{}", - q1.normalize(), - s1, - q1.normalize(), - other.to_css_string(span)? - ), + format!("{}{}{}-{}", q1, s1, q1, other.to_css_string(span)?), QuoteKind::None, ), _ => todo!(), }, Self::List(..) => match other { Self::Ident(s, q) => Value::Ident( - format!( - "{}-{}{}{}", - self.to_css_string(span)?, - q.normalize(), - s, - q.normalize() - ), + format!("{}-{}{}{}", self.to_css_string(span)?, q, s, q), QuoteKind::None, ), _ => Value::Ident( @@ -294,13 +259,7 @@ impl Value { }, _ => match other { Self::Ident(s, q) => Value::Ident( - format!( - "{}-{}{}{}", - self.to_css_string(span)?, - q.normalize(), - s, - q.normalize() - ), + format!("{}-{}{}{}", self.to_css_string(span)?, q, s, q), QuoteKind::None, ), Self::Null => { @@ -416,20 +375,18 @@ impl Value { ) } } - Self::Ident(s, q) => Value::Ident( - format!("{}{}/{}{}{}", num, unit, q.normalize(), s, q.normalize()), - QuoteKind::None, - ), + Self::Ident(s, q) => { + Value::Ident(format!("{}{}/{}{}{}", num, unit, q, s, q), QuoteKind::None) + } Self::BinaryOp(..) | Self::Paren(..) => { Self::Dimension(num, unit).div(other.eval(span)?.node, span)? } _ => todo!(), }, Self::Color(c) => match other { - Self::Ident(s, q) => Value::Ident( - format!("{}/{}{}{}", c, q.normalize(), s, q.normalize()), - QuoteKind::None, - ), + Self::Ident(s, q) => { + Value::Ident(format!("{}/{}{}{}", c, q, s, q), QuoteKind::None) + } Self::Null => Value::Ident(format!("{}/", c), QuoteKind::None), Self::Dimension(..) | Self::Color(..) => { return Err(( @@ -470,15 +427,7 @@ impl Value { Self::Paren(..) => self.eval(span)?.node.div(other, span)?, Self::Ident(s1, q1) => match other { Self::Ident(s2, q2) => Value::Ident( - format!( - "{}{}{}/{}{}{}", - q1.normalize(), - s1, - q1.normalize(), - q2.normalize(), - s2, - q2.normalize() - ), + format!("{}{}{}/{}{}{}", q1, s1, q1, q2, s2, q2), QuoteKind::None, ), Self::Important @@ -486,30 +435,15 @@ impl Value { | Self::False | Self::Dimension(..) | Self::Color(..) => Value::Ident( - format!( - "{}{}{}/{}", - q1.normalize(), - s1, - q1.normalize(), - other.to_css_string(span)? - ), - QuoteKind::None, - ), - Self::Null => Value::Ident( - format!("{}{}{}/", q1.normalize(), s1, q1.normalize()), + format!("{}{}{}/{}", q1, s1, q1, other.to_css_string(span)?), QuoteKind::None, ), + Self::Null => Value::Ident(format!("{}{}{}/", q1, s1, q1), QuoteKind::None), _ => todo!(), }, _ => match other { Self::Ident(s, q) => Value::Ident( - format!( - "{}/{}{}{}", - self.to_css_string(span)?, - q.normalize(), - s, - q.normalize() - ), + format!("{}/{}{}{}", self.to_css_string(span)?, q, s, q), QuoteKind::None, ), Self::Null => {