Add support for interpolation in at-rule names (#509)

Closes #496
This commit is contained in:
Natalie Weizenbaum 2018-11-01 14:31:46 -07:00 committed by GitHub
parent 9e18b7e95b
commit bf71ca359d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 43 additions and 37 deletions

View File

@ -1,4 +1,9 @@
## 1.14.5
## 1.15.0
* Add support for interpolation in at-rule names. See [the
proposal][at-rule-interpolation] for details.
[at-rule-interpolation]: https://github.com/sass/language/blob/master/accepted/at-rule-interpolation.md
### JavaScript API

View File

@ -11,7 +11,7 @@ import 'value.dart';
/// An unknown plain CSS at-rule.
class CssAtRule extends CssParentNode {
/// The name of this rule.
final String name;
final CssValue<String> name;
/// The value of this rule.
final CssValue<String> value;

View File

@ -72,7 +72,7 @@ class AtRootQuery {
String _nameFor(CssParentNode node) {
if (node is CssMediaRule) return "media";
if (node is CssSupportsRule) return "supports";
if (node is CssAtRule) return node.name.toLowerCase();
if (node is CssAtRule) return node.name.value.toLowerCase();
return null;
}
}

View File

@ -4,7 +4,6 @@
import 'package:source_span/source_span.dart';
import '../../../value.dart';
import '../../../visitor/interface/expression.dart';
import '../expression.dart';

View File

@ -4,7 +4,6 @@
import 'package:source_span/source_span.dart';
import '../../../utils.dart';
import '../../../visitor/interface/statement.dart';
import '../interpolation.dart';
import '../statement.dart';
@ -13,20 +12,15 @@ import 'parent.dart';
/// An unknown at-rule.
class AtRule extends ParentStatement {
/// The name of this rule.
final String name;
/// Like [name], but without any vendor prefixes.
final String normalizedName;
final Interpolation name;
/// The value of this rule.
final Interpolation value;
final FileSpan span;
AtRule(String name, this.span, {this.value, Iterable<Statement> children})
: name = name,
normalizedName = unvendor(name),
super(children == null ? null : new List.unmodifiable(children));
AtRule(this.name, this.span, {this.value, Iterable<Statement> children})
: super(children == null ? null : new List.unmodifiable(children));
T accept<T>(StatementVisitor<T> visitor) => visitor.visitAtRule(this);

View File

@ -41,9 +41,11 @@ class CssParser extends ScssParser {
// here should be mirrored there.
var start = scanner.state;
var name = atRuleName();
scanner.expectChar($at);
var name = interpolatedIdentifier();
whitespace();
switch (name) {
switch (name.asPlain) {
case "at-root":
case "content":
case "debug":
@ -74,7 +76,7 @@ class CssParser extends ScssParser {
case "media":
return mediaRule(start);
case "-moz-document":
return mozDocumentRule(start);
return mozDocumentRule(start, name);
case "supports":
return supportsRule(start);
default:

View File

@ -436,9 +436,11 @@ abstract class StylesheetParser extends Parser {
// here should be mirrored there.
var start = scanner.state;
var name = atRuleName();
scanner.expectChar($at);
var name = interpolatedIdentifier();
whitespace();
switch (name) {
switch (name.asPlain) {
case "at-root":
return _atRootRule(start);
case "charset":
@ -472,7 +474,7 @@ abstract class StylesheetParser extends Parser {
case "mixin":
return _mixinRule(start);
case "-moz-document":
return mozDocumentRule(start);
return mozDocumentRule(start, name);
case "return":
return _disallowedAtRule(start);
case "supports":
@ -489,7 +491,7 @@ abstract class StylesheetParser extends Parser {
/// Consumes an at-rule allowed within a property declaration.
Statement _declarationAtRule() {
var start = scanner.state;
var name = atRuleName();
var name = _plainAtRuleName();
switch (name) {
case "content":
@ -520,7 +522,7 @@ abstract class StylesheetParser extends Parser {
/// Consumes an at-rule allowed within a function.
Statement _functionAtRule() {
var start = scanner.state;
switch (atRuleName()) {
switch (_plainAtRuleName()) {
case "debug":
return _debugRule(start);
case "each":
@ -544,9 +546,8 @@ abstract class StylesheetParser extends Parser {
}
}
/// Consumes an at-rule's name.
@protected
String atRuleName() {
/// Consumes an at-rule's name, with interpolation disallowed.
String _plainAtRuleName() {
scanner.expectChar($at);
var name = identifier();
whitespace();
@ -956,7 +957,7 @@ abstract class StylesheetParser extends Parser {
///
/// [the specificiation]: http://www.w3.org/TR/css3-conditional/
@protected
AtRule mozDocumentRule(LineScannerState start) {
AtRule mozDocumentRule(LineScannerState start, Interpolation name) {
var valueStart = scanner.state;
var buffer = new InterpolationBuffer();
var needsDeprecationWarning = false;
@ -1029,7 +1030,7 @@ relase. For details, see http://bit.ly/moz-document.
""", span: span, deprecation: true);
}
return new AtRule("-moz-document", span, value: value, children: children);
return new AtRule(name, span, value: value, children: children);
}
/// Consumes a `@return` rule.
@ -1078,7 +1079,7 @@ relase. For details, see http://bit.ly/moz-document.
///
/// [start] should point before the `@`. [name] is the name of the at-rule.
@protected
AtRule unknownAtRule(LineScannerState start, String name) {
AtRule unknownAtRule(LineScannerState start, Interpolation name) {
var wasInUnknownAtRule = _inUnknownAtRule;
_inUnknownAtRule = true;
@ -2698,6 +2699,8 @@ relase. For details, see http://bit.ly/moz-document.
buffer.write(escape(identifierStart: true));
} else if (first == $hash && scanner.peekChar(1) == $lbrace) {
buffer.add(singleInterpolation());
} else {
scanner.error("Expected identifier.");
}
while (true) {

View File

@ -619,6 +619,8 @@ class _EvaluateVisitor
"At-rules may not be used within nested declarations.", node.span);
}
var name = await _interpolationToValue(node.name);
var value = node.value == null
? null
: await _interpolationToValue(node.value,
@ -626,20 +628,19 @@ class _EvaluateVisitor
if (node.children == null) {
_parent.addChild(
new CssAtRule(node.name, node.span, childless: true, value: value));
new CssAtRule(name, node.span, childless: true, value: value));
return null;
}
var wasInKeyframes = _inKeyframes;
var wasInUnknownAtRule = _inUnknownAtRule;
if (node.normalizedName == 'keyframes') {
if (unvendor(name.value) == 'keyframes') {
_inKeyframes = true;
} else {
_inUnknownAtRule = true;
}
await _withParent(new CssAtRule(node.name, node.span, value: value),
() async {
await _withParent(new CssAtRule(name, node.span, value: value), () async {
if (!_inStyleRule) {
for (var child in node.children) {
await child.accept(this);

View File

@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_evaluate.dart.
// See tool/synchronize.dart for details.
//
// Checksum: ce258987d3496f06c82ca1f31df4a0ac778fe326
// Checksum: e1af2918e6bfbf4b4d281b9f98756cd0ec910a28
import 'async_evaluate.dart' show EvaluateResult;
export 'async_evaluate.dart' show EvaluateResult;
@ -620,25 +620,27 @@ class _EvaluateVisitor
"At-rules may not be used within nested declarations.", node.span);
}
var name = _interpolationToValue(node.name);
var value = node.value == null
? null
: _interpolationToValue(node.value, trim: true, warnForColor: true);
if (node.children == null) {
_parent.addChild(
new CssAtRule(node.name, node.span, childless: true, value: value));
new CssAtRule(name, node.span, childless: true, value: value));
return null;
}
var wasInKeyframes = _inKeyframes;
var wasInUnknownAtRule = _inUnknownAtRule;
if (node.normalizedName == 'keyframes') {
if (unvendor(name.value) == 'keyframes') {
_inKeyframes = true;
} else {
_inUnknownAtRule = true;
}
_withParent(new CssAtRule(node.name, node.span, value: value), () {
_withParent(new CssAtRule(name, node.span, value: value), () {
if (!_inStyleRule) {
for (var child in node.children) {
child.accept(this);

View File

@ -207,7 +207,7 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor {
_for(node, () {
_buffer.writeCharCode($at);
_buffer.write(node.name);
_write(node.name);
if (node.value != null) {
_buffer.writeCharCode($space);

View File

@ -1,5 +1,5 @@
name: sass
version: 1.14.4
version: 1.15.0-dev
description: A Sass implementation in Dart.
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/sass/dart-sass