diff --git a/CHANGELOG.md b/CHANGELOG.md index edb125bd..7ea8a707 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ * Properly parse numbers with exponents. +* Don't crash when evaluating CSS variables whose names are entirely + interpolated (for example, `#{--foo}: ...`). + ## 1.0.0-beta.2 * Add support for the `::slotted()` pseudo-element. diff --git a/lib/src/ast/css/declaration.dart b/lib/src/ast/css/declaration.dart index 898c1813..7bec8573 100644 --- a/lib/src/ast/css/declaration.dart +++ b/lib/src/ast/css/declaration.dart @@ -19,12 +19,6 @@ class CssDeclaration extends CssNode { final FileSpan span; - /// Whether this is a custom property declaration, also known as a CSS - /// variable. - /// - /// Custom property declarations always have unquoted [SassString] values. - bool get isCustomProperty => name.value.startsWith("--"); - CssDeclaration(this.name, this.value, this.span); T accept(CssVisitor visitor) => visitor.visitDeclaration(this); diff --git a/lib/src/visitor/serialize.dart b/lib/src/visitor/serialize.dart index a36bef87..c156e379 100644 --- a/lib/src/visitor/serialize.dart +++ b/lib/src/visitor/serialize.dart @@ -230,8 +230,8 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor { _writeIndentation(); _buffer.write(node.name.value); _buffer.writeCharCode($colon); - if (node.isCustomProperty) { - _writeCustomPropertyValue(node); + if (_shouldReindentValue(node)) { + _writeReindentedValue(node); } else { _buffer.writeCharCode($space); _visitValue(node.value); @@ -239,10 +239,22 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor { _buffer.writeCharCode($semicolon); } - /// Emits the value of [node] as a custom property value. + /// Returns whether [node]'s value should be re-indented when being written to + /// the stylesheet. /// - /// This re-indents [node]'s value relative to the current indentation. - void _writeCustomPropertyValue(CssDeclaration node) { + /// We only re-indent custom property values that were parsed as custom + /// properties, which we detect as unquoted strings. It's possible to have + /// false positives here, since someone could write `#{--foo}: unquoted`, but + /// that's unlikely enough that we can spare the extra time a no-op + /// reindenting will take. + bool _shouldReindentValue(CssDeclaration node) { + if (!node.name.value.startsWith("--")) return false; + var value = node.value.value; + return value is SassString && !value.hasQuotes; + } + + /// Emits the value of [node], re-indented relative to the current indentation. + void _writeReindentedValue(CssDeclaration node) { var value = (node.value.value as SassString).text; var minimumIndentation = _minimumIndentation(value); diff --git a/pubspec.yaml b/pubspec.yaml index 7bb20042..e5e237e0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sass -version: 1.0.0-beta.2 +version: 1.0.0-dev description: A Sass implementation in Dart. author: Dart Team homepage: https://github.com/sass/dart-sass