Merge branch 'master' into feature.nested-maps

This commit is contained in:
Natalie Weizenbaum 2020-10-05 17:59:59 -07:00 committed by GitHub
commit c14cb73b08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 51 additions and 23 deletions

View File

@ -69,6 +69,11 @@
retrieve maps even if they're internally stored as empty lists, without having
to catch exceptions from `Value.assertMap()`.
## 1.26.12
* Fix a bug where nesting properties beneath a Sass-syntax custom property
(written as `#{--foo}: ...`) would crash.
## 1.26.11
* **Potentially breaking bug fix:** `selector.nest()` now throws an error

View File

@ -24,5 +24,15 @@ abstract class CssDeclaration extends CssNode {
/// the variable was used. Otherwise, this is identical to [value.span].
FileSpan get valueSpanForMap;
T accept<T>(CssVisitor<T> visitor) => visitor.visitCssDeclaration(this);
/// Returns whether this is a CSS Custom Property declaration.
bool get isCustomProperty;
/// Whether this is was originally parsed as a custom property declaration, as
/// 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`.
bool get parsedAsCustomProperty;
T accept<T>(CssVisitor<T> visitor);
}

View File

@ -2,6 +2,7 @@
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'package:meta/meta.dart';
import 'package:source_span/source_span.dart';
import '../../../value.dart';
@ -15,13 +16,26 @@ class ModifiableCssDeclaration extends ModifiableCssNode
implements CssDeclaration {
final CssValue<String> name;
final CssValue<Value> value;
final bool parsedAsCustomProperty;
final FileSpan valueSpanForMap;
final FileSpan span;
bool get isCustomProperty => name.value.startsWith('--');
/// Returns a new CSS declaration with the given properties.
ModifiableCssDeclaration(this.name, this.value, this.span,
{FileSpan valueSpanForMap})
: valueSpanForMap = valueSpanForMap ?? span;
{@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 '
'"--".');
}
}
T accept<T>(ModifiableCssVisitor<T> visitor) =>
visitor.visitCssDeclaration(this);
String toString() => "$name: $value;";
}

View File

@ -20,10 +20,15 @@ class Declaration extends ParentStatement {
final FileSpan span;
/// Returns whether this is a CSS Custom Property declaration.
///
/// 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}: ...`.
bool get isCustomProperty => name.initialPlain.startsWith('--');
Declaration(this.name, this.span, {this.value, Iterable<Statement> children})
: super(children = children == null ? null : List.unmodifiable(children));
T accept<T>(StatementVisitor<T> visitor) => visitor.visitDeclaration(this);
String toString() => "$name: $value;";
}

View File

@ -1039,8 +1039,9 @@ class _EvaluateVisitor
if (cssValue != null &&
(!cssValue.value.isBlank || _isEmptyList(cssValue.value))) {
_parent.addChild(ModifiableCssDeclaration(name, cssValue, node.span,
parsedAsCustomProperty: node.isCustomProperty,
valueSpanForMap: _expressionNode(node.value)?.span));
} else if (name.value.startsWith('--')) {
} else if (name.value.startsWith('--') && node.children == null) {
throw _exception(
"Custom property values may not be empty.", node.value.span);
}
@ -2559,6 +2560,7 @@ class _EvaluateVisitor
Future<void> visitCssDeclaration(CssDeclaration node) async {
_parent.addChild(ModifiableCssDeclaration(node.name, node.value, node.span,
parsedAsCustomProperty: node.isCustomProperty,
valueSpanForMap: node.valueSpanForMap));
}

View File

@ -44,6 +44,7 @@ class _CloneCssVisitor implements CssVisitor<ModifiableCssNode> {
ModifiableCssDeclaration visitCssDeclaration(CssDeclaration node) =>
ModifiableCssDeclaration(node.name, node.value, node.span,
parsedAsCustomProperty: node.parsedAsCustomProperty,
valueSpanForMap: node.valueSpanForMap);
ModifiableCssImport visitCssImport(CssImport node) =>

View File

@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_evaluate.dart.
// See tool/grind/synchronize.dart for details.
//
// Checksum: f6fe6645ccec58216ef623851bd2594de291a360
// Checksum: 651a7e9f78b68bfd440241304301cf78711553a4
//
// ignore_for_file: unused_import
@ -1041,8 +1041,9 @@ class _EvaluateVisitor
if (cssValue != null &&
(!cssValue.value.isBlank || _isEmptyList(cssValue.value))) {
_parent.addChild(ModifiableCssDeclaration(name, cssValue, node.span,
parsedAsCustomProperty: node.isCustomProperty,
valueSpanForMap: _expressionNode(node.value)?.span));
} else if (name.value.startsWith('--')) {
} else if (name.value.startsWith('--') && node.children == null) {
throw _exception(
"Custom property values may not be empty.", node.value.span);
}
@ -2541,6 +2542,7 @@ class _EvaluateVisitor
void visitCssDeclaration(CssDeclaration node) {
_parent.addChild(ModifiableCssDeclaration(node.name, node.value, node.span,
parsedAsCustomProperty: node.isCustomProperty,
valueSpanForMap: node.valueSpanForMap));
}

View File

@ -333,7 +333,10 @@ class _SerializeVisitor
_write(node.name);
_buffer.writeCharCode($colon);
if (_isParsedCustomProperty(node)) {
// If `node` is a custom property that was parsed as a normal Sass-syntax
// property (such as `#{--foo}: ...`), we serialize its value using the
// normal Sass property logic as well.
if (node.isCustomProperty && node.parsedAsCustomProperty) {
_for(node.value, () {
if (_isCompressed) {
_writeFoldedValue(node);
@ -355,20 +358,6 @@ class _SerializeVisitor
}
}
/// Returns whether [node] is a custom property that was parsed as a custom
/// property (rather than being dynamically generated, as in `#{--foo}: ...`).
///
/// 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 _isParsedCustomProperty(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], with all newlines followed by whitespace
void _writeFoldedValue(CssDeclaration node) {
var scanner = StringScanner((node.value.value as SassString).text);