diff --git a/.travis.yml b/.travis.yml index a0d382a01..4ec6709ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -74,26 +74,21 @@ jobs: # They next need to be rotated April 2021. See # https://github.com/nodejs/Release. - &node-tests - # TODO(nweiz): Run Node tests against Dart stable once #1104 is fixed. - name: Node tests | Dart 2.9 | Node stable + name: Node tests | Dart stable | Node stable language: node_js node_js: node install: pub run grinder before-test script: tool/travis/task/node_tests.sh - env: DART_VERSION=2.9.3 - <<: *node-tests - name: Node tests | Dart 2.9 | Node Dubnium + name: Node tests | Dart stable | Node Dubnium node_js: lts/dubnium - <<: *node-tests - name: Node tests | Dart 2.9 | Node Erbium + name: Node tests | Dart stable | Node Erbium node_js: lts/erbium - <<: *node-tests os: windows - <<: *node-tests os: osx - - <<: *node-tests - name: Node tests | Dart stable | Node stable - env: DART_VERSION=latest - <<: *node-tests name: Node tests | Dart dev | Node stable env: DART_CHANNEL=dev @@ -151,8 +146,6 @@ jobs: - name: npm if: *deploy-if env: - # TODO(nweiz): Compile Node release with Dart stable once #1104 is fixed. - - DART_VERSION=2.9.3 # NPM_TOKEN="..." - secure: "pwOMlV/hUTYYKrdULkhM0pHKCjXR1uWAuBbfxMxWCPH/AGkW3CP/WED8p5/Q6B8Itzca6eYg85PnkzeLl4hK9ANnYrQsHutfszGyzcqqAeWWPXm3Bq6Rqt5XpA4JCSdZBPKOLZ7yGzMCPVRMAet4fvORRU6nFCTJcm/B1JZNIAWY5TnjgcjwLa77Eo4Bflv58CTA5FyngN7hAMIo2JaassmReRHxtyVBh631IYFBvmo8vmC0gruPY0axj9a/4+F1Nx2ChOAjji0SRMJP1FSp7zOXCG+VrcqXMW3KCfBu/70szcdDVXOYYyJpCeiP6vVtRgi+9zqin9wOATIklRPMTy/zVbT4r9kfA7+GFSfsfAQ7K79VbvJQHbxon3E5JnWANjZr3q+iicX+sElL6IngoSw8pXRUHVJD979WcPTcKX+dd2KKqDR0S+rG8d7ZgyjIggCSGsyxvuX0vd/VaPmZA/4+tVfSHYxCq3P3sncVX9raP41UNFW9KyEQzKfxTs6I4U5IffFcLZRRoP1uMSdiru9cIvVCX64UTk6+TTiPXRj4o84dG/NQkYoc3EhHsRL4E7SAq827Ya1gA8GLSCJidtvGPG16VimvgT372pHPZ+l9Pb5XkMnZ+dji3o37xYTSbRESOk+pnMwq3f4lQz6YFuI+EjbO5RYCs5IxHjgW8Ak=" script: skip diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d6b06cd7..f00053ab5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,9 @@ [map-deep-remove]: https://sass-lang.com/documentation/modules/map#deep-remove +* Fix a bug where custom property values in plain CSS were being parsed as + normal property values. + ### Dart API * Add a `Value.tryMap()` function which returns the `Value` as a `SassMap` if diff --git a/lib/src/ast/css/declaration.dart b/lib/src/ast/css/declaration.dart index 7edaf2af5..1bd7279fc 100644 --- a/lib/src/ast/css/declaration.dart +++ b/lib/src/ast/css/declaration.dart @@ -31,7 +31,8 @@ abstract class CssDeclaration extends CssNode { /// opposed to using something like `#{--foo}: ...` to cause it to be parsed /// as a normal Sass declaration. /// - /// If this is `true`, [isCustomProperty] will also be `true`. + /// If this is `true`, [isCustomProperty] will also be `true` and [value] will + /// contain a [SassString]. bool get parsedAsCustomProperty; T accept(CssVisitor visitor); diff --git a/lib/src/ast/css/modifiable/declaration.dart b/lib/src/ast/css/modifiable/declaration.dart index 8d4645506..e4bb7fc44 100644 --- a/lib/src/ast/css/modifiable/declaration.dart +++ b/lib/src/ast/css/modifiable/declaration.dart @@ -27,10 +27,16 @@ class ModifiableCssDeclaration extends ModifiableCssNode {@required bool parsedAsCustomProperty, FileSpan valueSpanForMap}) : parsedAsCustomProperty = parsedAsCustomProperty, valueSpanForMap = valueSpanForMap ?? span { - if (!isCustomProperty && parsedAsCustomProperty) { - throw ArgumentError( - 'sassSyntaxCustomProperty must be false if name doesn\'t begin with ' - '"--".'); + if (parsedAsCustomProperty) { + if (!isCustomProperty) { + throw ArgumentError( + 'parsedAsCustomProperty must be false if name doesn\'t begin with ' + '"--".'); + } else if (value.value is! SassString) { + throw ArgumentError( + 'If parsedAsCustomProperty is true, value must contain a SassString ' + '(was `$value` of type ${value.value.runtimeType}).'); + } } } diff --git a/lib/src/ast/sass/statement/declaration.dart b/lib/src/ast/sass/statement/declaration.dart index a720b998b..6d6240ece 100644 --- a/lib/src/ast/sass/statement/declaration.dart +++ b/lib/src/ast/sass/statement/declaration.dart @@ -6,6 +6,7 @@ import 'package:source_span/source_span.dart'; import '../../../visitor/interface/statement.dart'; import '../expression.dart'; +import '../expression/string.dart'; import '../interpolation.dart'; import '../statement.dart'; import 'parent.dart'; @@ -25,10 +26,19 @@ class Declaration extends ParentStatement { /// Note that this can return `false` for declarations that will ultimately be /// serialized as custom properties if they aren't *parsed as* custom /// properties, such as `#{--foo}: ...`. + /// + /// If this is `true`, then `value` will be a [StringExpression]. bool get isCustomProperty => name.initialPlain.startsWith('--'); Declaration(this.name, this.span, {this.value, Iterable children}) - : super(children = children == null ? null : List.unmodifiable(children)); + : super( + children = children == null ? null : List.unmodifiable(children)) { + if (isCustomProperty && value is! StringExpression) { + throw ArgumentError( + 'Declarations whose names begin with "--" must have StringExpression ' + 'values (was `${value}` of type ${value.runtimeType}).'); + } + } T accept(StatementVisitor visitor) => visitor.visitDeclaration(this); } diff --git a/lib/src/parse/stylesheet.dart b/lib/src/parse/stylesheet.dart index 831654cc5..3fea27a0e 100644 --- a/lib/src/parse/stylesheet.dart +++ b/lib/src/parse/stylesheet.dart @@ -503,8 +503,11 @@ abstract class StylesheetParser extends Parser { /// This is only used in contexts where declarations are allowed but style /// rules are not, such as nested declarations. Otherwise, /// [_declarationOrStyleRule] is used instead. - @protected - Statement _propertyOrVariableDeclaration() { + /// + /// If [parseCustomProperties] is `true`, properties that begin with `--` will + /// be parsed using custom property parsing rules. + Statement _propertyOrVariableDeclaration( + {bool parseCustomProperties = true}) { var start = scanner.state; Interpolation name; @@ -533,6 +536,13 @@ abstract class StylesheetParser extends Parser { whitespace(); scanner.expectChar($colon); + + if (parseCustomProperties && name.initialPlain.startsWith('--')) { + var value = _interpolatedDeclarationValue(); + expectStatementSeparator("custom property"); + return Declaration(name, scanner.spanFrom(start), value: value); + } + whitespace(); if (lookingAtChildren()) { @@ -562,7 +572,7 @@ abstract class StylesheetParser extends Parser { /// Consumes a statement that's allowed within a declaration. Statement _declarationChild() { if (scanner.peekChar() == $at) return _declarationAtRule(); - return _propertyOrVariableDeclaration(); + return _propertyOrVariableDeclaration(parseCustomProperties: false); } // ## At Rules