diff --git a/src/parse/value.rs b/src/parse/value.rs index 957360d..60d8e53 100644 --- a/src/parse/value.rs +++ b/src/parse/value.rs @@ -526,41 +526,38 @@ impl<'a> Parser<'a> { } fn parse_hex(&mut self) -> SassResult> { - let mut s = String::with_capacity(8); + let mut s = String::with_capacity(7); + s.push('#'); if self .toks .peek() .ok_or(("Expected identifier.", self.span_before))? .kind - .is_ascii_digit() + .is_ascii_hexdigit() { while let Some(c) = self.toks.peek() { - if !c.kind.is_ascii_hexdigit() || s.len() == 8 { + if !c.kind.is_ascii_hexdigit() { break; } let tok = self.toks.next().unwrap(); self.span_before = self.span_before.merge(tok.pos()); s.push(tok.kind); } + // this branch exists so that we can emit `#` combined with + // identifiers. e.g. `#ooobar` should be emitted exactly as written; + // that is, `#ooobar`. } else { - let i = self.parse_identifier()?; - if i.node.chars().all(|c| c.is_ascii_hexdigit()) { - s = i.node; - self.span_before = self.span_before.merge(i.span); - } else { - return Ok(Spanned { - node: Value::String(format!("#{}", i.node), QuoteKind::None), - span: i.span, - }); - } + let ident = self.parse_identifier()?; + return Ok(Spanned { + node: Value::String(format!("#{}", ident.node), QuoteKind::None), + span: ident.span, + }); } - let v = match u32::from_str_radix(&s, 16) { + let v = match u32::from_str_radix(&s[1..], 16) { Ok(a) => a, - Err(_) => { - return Ok(Value::String(format!("#{}", s), QuoteKind::None).span(self.span_before)) - } + Err(_) => return Ok(Value::String(s, QuoteKind::None).span(self.span_before)), }; - let (red, green, blue, alpha) = match s.len() { + let (red, green, blue, alpha) = match s.len().saturating_sub(1) { 3 => ( (((v & 0x0f00) >> 8) * 0x11) as u8, (((v & 0x00f0) >> 4) * 0x11) as u8, @@ -587,7 +584,7 @@ impl<'a> Parser<'a> { ), _ => return Err(("Expected hex digit.", self.span_before).into()), }; - let color = Color::new(red, green, blue, alpha, format!("#{}", s)); + let color = Color::new(red, green, blue, alpha, s); Ok(Value::Color(Box::new(color)).span(self.span_before)) } diff --git a/tests/color.rs b/tests/color.rs index 2dcd2fe..e518003 100644 --- a/tests/color.rs +++ b/tests/color.rs @@ -582,3 +582,18 @@ test!( "a {\n color: hsl(-1 -1 -1);\n}\n", "a {\n color: black;\n}\n" ); +test!( + interpolation_after_hash_containing_only_hex_chars, + "a {\n color: ##{123};\n color: type-of(##{123});\n}\n", + "a {\n color: #123;\n color: string;\n}\n" +); +test!( + non_hex_chars_after_hash_are_still_touching_hash, + "a {\n color: #ooobar;\n}\n", + "a {\n color: #ooobar;\n}\n" +); +test!( + more_than_8_hex_chars_after_hash, + "a {\n color: #ffffffffff;\n}\n", + "a {\n color: #ffffffffff;\n}\n" +);