remove QuoteKind::Single variant

This commit is contained in:
ConnorSkees 2020-04-18 13:19:30 -04:00
parent a83aef04ca
commit 52c6ed0b64
6 changed files with 46 additions and 143 deletions

View File

@ -71,7 +71,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
.into()) .into())
} }
}; };
Ok(Value::Ident(unit, QuoteKind::Double)) Ok(Value::Ident(unit, QuoteKind::Quoted))
}), }),
); );
f.insert( f.insert(

View File

@ -71,7 +71,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
Builtin::new(|mut args, scope, super_selector| { Builtin::new(|mut args, scope, super_selector| {
max_args!(args, 1); max_args!(args, 1);
match arg!(args, scope, super_selector, 0, "string") { 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(( v => Err((
format!( format!(
"$string: {} is not a string.", "$string: {} is not a string.",
@ -191,7 +191,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
} }
if start > end || start > str_len { if start > end || start > str_len {
Ok(Value::Ident(String::new(), quotes.normalize())) Ok(Value::Ident(String::new(), quotes))
} else { } else {
Ok(Value::Ident( Ok(Value::Ident(
string string
@ -199,7 +199,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
.skip(start - 1) .skip(start - 1)
.take(end - start + 1) .take(end - start + 1)
.collect(), .collect(),
quotes.normalize(), quotes,
)) ))
} }
}), }),
@ -247,7 +247,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
Builtin::new(|mut args, scope, super_selector| { Builtin::new(|mut args, scope, super_selector| {
max_args!(args, 3); max_args!(args, 3);
let (s1, quotes) = match arg!(args, scope, super_selector, 0, "string") { 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 => { v => {
return Err(( return Err((
format!( format!(

View File

@ -63,28 +63,15 @@ impl Op {
#[derive(Debug, Copy, Clone, Eq, PartialEq)] #[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub(crate) enum QuoteKind { pub(crate) enum QuoteKind {
Single, Quoted,
Double,
None, 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 { impl Display for QuoteKind {
#[inline] #[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Self::Single => write!(f, "'"), Self::Quoted => write!(f, "\""),
Self::Double => write!(f, "\""),
Self::None => write!(f, ""), Self::None => write!(f, ""),
} }
} }

View File

@ -585,7 +585,6 @@ pub(crate) fn parse_quoted_string<I: Iterator<Item = Token>>(
) -> SassResult<Spanned<Value>> { ) -> SassResult<Spanned<Value>> {
let mut s = String::new(); let mut s = String::new();
let mut is_escaped = false; let mut is_escaped = false;
let mut found_interpolation = false;
let mut span = if let Some(tok) = toks.peek() { let mut span = if let Some(tok) = toks.peek() {
tok.pos() tok.pos()
} else { } else {
@ -615,7 +614,6 @@ pub(crate) fn parse_quoted_string<I: Iterator<Item = Token>>(
'#' if !is_escaped => { '#' if !is_escaped => {
if toks.peek().unwrap().kind == '{' { if toks.peek().unwrap().kind == '{' {
toks.next(); toks.next();
found_interpolation = true;
let interpolation = parse_interpolation(toks, scope, super_selector)?; let interpolation = parse_interpolation(toks, scope, super_selector)?;
s.push_str(&interpolation.node.to_css_string(interpolation.span)?); s.push_str(&interpolation.node.to_css_string(interpolation.span)?);
continue; continue;
@ -657,17 +655,8 @@ pub(crate) fn parse_quoted_string<I: Iterator<Item = Token>>(
s.push_str(&tok.kind.to_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 { Ok(Spanned {
node: Value::Ident(s, quotes), node: Value::Ident(s, QuoteKind::Quoted),
span, span,
}) })
} }

View File

@ -95,10 +95,8 @@ impl Value {
format!("{}", self.clone().eval(span)?.to_css_string(span)?) format!("{}", self.clone().eval(span)?.to_css_string(span)?)
} }
Self::Paren(val) => format!("{}", val.to_css_string(span)?), Self::Paren(val) => format!("{}", val.to_css_string(span)?),
Self::Ident(val, kind) => { Self::Ident(val, QuoteKind::None) => return Ok(val.clone()),
if kind == &QuoteKind::None { Self::Ident(val, QuoteKind::Quoted) => {
return Ok(val.clone());
}
let has_single_quotes = val.contains(|x| x == '\''); let has_single_quotes = val.contains(|x| x == '\'');
let has_double_quotes = val.contains(|x| x == '"'); let has_double_quotes = val.contains(|x| x == '"');
if has_single_quotes && !has_double_quotes { if has_single_quotes && !has_double_quotes {
@ -108,23 +106,18 @@ impl Value {
} else if !has_single_quotes && !has_double_quotes { } else if !has_single_quotes && !has_double_quotes {
format!("\"{}\"", val) format!("\"{}\"", val)
} else { } else {
let quote_char = match kind {
QuoteKind::Double => '"',
QuoteKind::Single => '\'',
_ => unreachable!(),
};
let mut buf = String::with_capacity(val.len() + 2); let mut buf = String::with_capacity(val.len() + 2);
buf.push(quote_char); buf.push('"');
for c in val.chars() { for c in val.chars() {
match c { match c {
'"' | '\'' if c == quote_char => { '"' => {
buf.push('\\'); buf.push('\\');
buf.push(quote_char); buf.push('"');
} }
v => buf.push(v), v => buf.push(v),
} }
} }
buf.push(quote_char); buf.push('"');
buf buf
} }
} }

View File

@ -14,12 +14,10 @@ impl Value {
Ok(match self { Ok(match self {
Self::Function(..) | Self::ArgList(..) | Self::Map(..) => todo!(), Self::Function(..) | Self::ArgList(..) | Self::Map(..) => todo!(),
Self::Important | Self::True | Self::False => match other { Self::Important | Self::True | Self::False => match other {
Self::Ident(s, QuoteKind::Double) | Self::Ident(s, QuoteKind::Single) => { Self::Ident(s, QuoteKind::Quoted) => Value::Ident(
Value::Ident( format!("{}{}", self.to_css_string(span)?, s),
format!("{}{}", self.to_css_string(span)?, s), QuoteKind::Quoted,
QuoteKind::Double, ),
)
}
Self::Null => Value::Ident(self.to_css_string(span)?, QuoteKind::None), Self::Null => Value::Ident(self.to_css_string(span)?, QuoteKind::None),
_ => Value::Ident( _ => Value::Ident(
format!( 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::Null => Value::Ident(format!("{}{}", num, unit), QuoteKind::None),
Self::List(..) => Value::Ident( Self::List(..) => Value::Ident(
format!("{}{}{}", num, unit, other.to_css_string(span)?), format!("{}{}{}", num, unit, other.to_css_string(span)?),
@ -76,7 +74,7 @@ impl Value {
} }
}, },
Self::Color(c) => match other { 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::Null => Value::Ident(c.to_string(), QuoteKind::None),
Self::List(..) => Value::Ident( Self::List(..) => Value::Ident(
format!("{}{}", c, other.to_css_string(span)?), 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::UnaryOp(..) | Self::Paren(..) => self.eval(span)?.node.add(other, span)?,
Self::Ident(s1, quotes1) => match other { Self::Ident(s1, quotes1) => match other {
Self::Ident(s2, _) => Value::Ident(format!("{}{}", s1, s2), quotes1.normalize()), Self::Ident(s2, _) => Value::Ident(format!("{}{}", s1, s2), quotes1),
Self::Important | Self::True | Self::False | Self::Dimension(..) => Value::Ident( Self::Important | Self::True | Self::False | Self::Dimension(..) => {
format!("{}{}", s1, other.to_css_string(span)?), Value::Ident(format!("{}{}", s1, other.to_css_string(span)?), quotes1)
quotes1.normalize(), }
), Self::Null => Value::Ident(s1, quotes1),
Self::Null => Value::Ident(s1, quotes1.normalize()), Self::Color(c) => Value::Ident(format!("{}{}", s1, c), quotes1),
Self::Color(c) => Value::Ident(format!("{}{}", s1, c), quotes1.normalize()),
Self::List(..) => { Self::List(..) => {
Value::Ident(format!("{}{}", s1, other.to_css_string(span)?), quotes1) Value::Ident(format!("{}{}", s1, other.to_css_string(span)?), quotes1)
} }
@ -131,9 +128,7 @@ impl Value {
Self::Function(..) | Self::ArgList(..) | Self::Map(..) => todo!(), Self::Function(..) | Self::ArgList(..) | Self::Map(..) => todo!(),
}, },
Self::List(..) => match other { Self::List(..) => match other {
Self::Ident(s, q) => { Self::Ident(s, q) => Value::Ident(format!("{}{}", self.to_css_string(span)?, s), q),
Value::Ident(format!("{}{}", self.to_css_string(span)?, s), q.normalize())
}
Self::Paren(..) => (self.add(other.eval(span)?.node, span))?, Self::Paren(..) => (self.add(other.eval(span)?.node, span))?,
_ => Value::Ident( _ => Value::Ident(
format!( format!(
@ -187,10 +182,9 @@ impl Value {
_ => todo!(), _ => todo!(),
}, },
Self::Color(c) => match other { Self::Color(c) => match other {
Self::Ident(s, q) => Value::Ident( Self::Ident(s, q) => {
format!("{}-{}{}{}", c, q.normalize(), s, q.normalize()), Value::Ident(format!("{}-{}{}{}", c, q, s, q), QuoteKind::None)
QuoteKind::None, }
),
Self::Null => Value::Ident(format!("{}-", c), QuoteKind::None), Self::Null => Value::Ident(format!("{}-", c), QuoteKind::None),
Self::Dimension(..) | Self::Color(..) => { Self::Dimension(..) | Self::Color(..) => {
return Err(( return Err((
@ -231,15 +225,7 @@ impl Value {
Self::Paren(..) => self.eval(span)?.node.sub(other, span)?, Self::Paren(..) => self.eval(span)?.node.sub(other, span)?,
Self::Ident(s1, q1) => match other { Self::Ident(s1, q1) => match other {
Self::Ident(s2, q2) => Value::Ident( Self::Ident(s2, q2) => Value::Ident(
format!( format!("{}{}{}-{}{}{}", q1, s1, q1, q2, s2, q2),
"{}{}{}-{}{}{}",
q1.normalize(),
s1,
q1.normalize(),
q2.normalize(),
s2,
q2.normalize()
),
QuoteKind::None, QuoteKind::None,
), ),
Self::Important Self::Important
@ -247,40 +233,19 @@ impl Value {
| Self::False | Self::False
| Self::Dimension(..) | Self::Dimension(..)
| Self::Color(..) => Value::Ident( | Self::Color(..) => Value::Ident(
format!( format!("{}{}{}-{}", q1, s1, q1, other.to_css_string(span)?),
"{}{}{}-{}",
q1.normalize(),
s1,
q1.normalize(),
other.to_css_string(span)?
),
QuoteKind::None,
),
Self::Null => Value::Ident(
format!("{}{}{}-", q1.normalize(), s1, q1.normalize()),
QuoteKind::None, QuoteKind::None,
), ),
Self::Null => Value::Ident(format!("{}{}{}-", q1, s1, q1), QuoteKind::None),
Self::List(..) => Value::Ident( Self::List(..) => Value::Ident(
format!( format!("{}{}{}-{}", q1, s1, q1, other.to_css_string(span)?),
"{}{}{}-{}",
q1.normalize(),
s1,
q1.normalize(),
other.to_css_string(span)?
),
QuoteKind::None, QuoteKind::None,
), ),
_ => todo!(), _ => todo!(),
}, },
Self::List(..) => match other { Self::List(..) => match other {
Self::Ident(s, q) => Value::Ident( Self::Ident(s, q) => Value::Ident(
format!( format!("{}-{}{}{}", self.to_css_string(span)?, q, s, q),
"{}-{}{}{}",
self.to_css_string(span)?,
q.normalize(),
s,
q.normalize()
),
QuoteKind::None, QuoteKind::None,
), ),
_ => Value::Ident( _ => Value::Ident(
@ -294,13 +259,7 @@ impl Value {
}, },
_ => match other { _ => match other {
Self::Ident(s, q) => Value::Ident( Self::Ident(s, q) => Value::Ident(
format!( format!("{}-{}{}{}", self.to_css_string(span)?, q, s, q),
"{}-{}{}{}",
self.to_css_string(span)?,
q.normalize(),
s,
q.normalize()
),
QuoteKind::None, QuoteKind::None,
), ),
Self::Null => { Self::Null => {
@ -416,20 +375,18 @@ impl Value {
) )
} }
} }
Self::Ident(s, q) => Value::Ident( Self::Ident(s, q) => {
format!("{}{}/{}{}{}", num, unit, q.normalize(), s, q.normalize()), Value::Ident(format!("{}{}/{}{}{}", num, unit, q, s, q), QuoteKind::None)
QuoteKind::None, }
),
Self::BinaryOp(..) | Self::Paren(..) => { Self::BinaryOp(..) | Self::Paren(..) => {
Self::Dimension(num, unit).div(other.eval(span)?.node, span)? Self::Dimension(num, unit).div(other.eval(span)?.node, span)?
} }
_ => todo!(), _ => todo!(),
}, },
Self::Color(c) => match other { Self::Color(c) => match other {
Self::Ident(s, q) => Value::Ident( Self::Ident(s, q) => {
format!("{}/{}{}{}", c, q.normalize(), s, q.normalize()), Value::Ident(format!("{}/{}{}{}", c, q, s, q), QuoteKind::None)
QuoteKind::None, }
),
Self::Null => Value::Ident(format!("{}/", c), QuoteKind::None), Self::Null => Value::Ident(format!("{}/", c), QuoteKind::None),
Self::Dimension(..) | Self::Color(..) => { Self::Dimension(..) | Self::Color(..) => {
return Err(( return Err((
@ -470,15 +427,7 @@ impl Value {
Self::Paren(..) => self.eval(span)?.node.div(other, span)?, Self::Paren(..) => self.eval(span)?.node.div(other, span)?,
Self::Ident(s1, q1) => match other { Self::Ident(s1, q1) => match other {
Self::Ident(s2, q2) => Value::Ident( Self::Ident(s2, q2) => Value::Ident(
format!( format!("{}{}{}/{}{}{}", q1, s1, q1, q2, s2, q2),
"{}{}{}/{}{}{}",
q1.normalize(),
s1,
q1.normalize(),
q2.normalize(),
s2,
q2.normalize()
),
QuoteKind::None, QuoteKind::None,
), ),
Self::Important Self::Important
@ -486,30 +435,15 @@ impl Value {
| Self::False | Self::False
| Self::Dimension(..) | Self::Dimension(..)
| Self::Color(..) => Value::Ident( | Self::Color(..) => Value::Ident(
format!( format!("{}{}{}/{}", q1, s1, q1, other.to_css_string(span)?),
"{}{}{}/{}",
q1.normalize(),
s1,
q1.normalize(),
other.to_css_string(span)?
),
QuoteKind::None,
),
Self::Null => Value::Ident(
format!("{}{}{}/", q1.normalize(), s1, q1.normalize()),
QuoteKind::None, QuoteKind::None,
), ),
Self::Null => Value::Ident(format!("{}{}{}/", q1, s1, q1), QuoteKind::None),
_ => todo!(), _ => todo!(),
}, },
_ => match other { _ => match other {
Self::Ident(s, q) => Value::Ident( Self::Ident(s, q) => Value::Ident(
format!( format!("{}/{}{}{}", self.to_css_string(span)?, q, s, q),
"{}/{}{}{}",
self.to_css_string(span)?,
q.normalize(),
s,
q.normalize()
),
QuoteKind::None, QuoteKind::None,
), ),
Self::Null => { Self::Null => {