Allow declarations in @at-root.

This commit is contained in:
Natalie Weizenbaum 2016-10-19 20:44:53 -07:00
parent 4e6a3d0ea9
commit 3941e4debd
3 changed files with 23 additions and 6 deletions

View File

@ -15,8 +15,8 @@ class AtRootQueryParser extends Parser {
return wrapSpanFormatException(() { return wrapSpanFormatException(() {
scanner.expectChar($lparen); scanner.expectChar($lparen);
whitespace(); whitespace();
expectIdentifier("with", ignoreCase: true); var include = scanIdentifier("with");
var include = !scanIdentifier("out", ignoreCase: true); if (!include) expectIdentifier("without");
whitespace(); whitespace();
scanner.expectChar($colon); scanner.expectChar($colon);
whitespace(); whitespace();

View File

@ -428,7 +428,7 @@ abstract class StylesheetParser extends Parser {
var next = scanner.peekChar(); var next = scanner.peekChar();
var query = next == $hash || next == $lparen ? _queryExpression() : null; var query = next == $hash || next == $lparen ? _queryExpression() : null;
whitespace(); whitespace();
return new AtRootRule(children(_topLevelStatement), scanner.spanFrom(start), return new AtRootRule(children(_ruleChild), scanner.spanFrom(start),
query: query); query: query);
} }

View File

@ -71,6 +71,9 @@ class _PerformVisitor
/// This is used to provide `call()` with a span. /// This is used to provide `call()` with a span.
FileSpan _callableSpan; FileSpan _callableSpan;
/// Whether we're currently building the output of an unknown at rule.
var _inUnknownAtRule = false;
/// The resolved URLs for each [ImportRule] that's been seen so far. /// The resolved URLs for each [ImportRule] that's been seen so far.
/// ///
/// This is cached in case the same file is imported multiple times, and thus /// This is cached in case the same file is imported multiple times, and thus
@ -155,7 +158,7 @@ class _PerformVisitor
} }
if (outerCopy != null) root.addChild(outerCopy); if (outerCopy != null) root.addChild(outerCopy);
_scopeForAtRoot(innerCopy ?? root, query)(() { _scopeForAtRoot(innerCopy ?? root, query, included)(() {
for (var child in node.children) { for (var child in node.children) {
child.accept(this); child.accept(this);
} }
@ -198,7 +201,8 @@ class _PerformVisitor
/// This returns a callback that adjusts various instance variables for its /// This returns a callback that adjusts various instance variables for its
/// duration, based on which rules are excluded by [query]. It always assigns /// duration, based on which rules are excluded by [query]. It always assigns
/// [_parent] to [newParent]. /// [_parent] to [newParent].
_ScopeCallback _scopeForAtRoot(CssParentNode newParent, AtRootQuery query) { _ScopeCallback _scopeForAtRoot(CssParentNode newParent, AtRootQuery query,
List<CssParentNode> included) {
var scope = (callback()) { var scope = (callback()) {
// We can't use [_withParent] here because it'll add the node to the tree // We can't use [_withParent] here because it'll add the node to the tree
// in the wrong place. // in the wrong place.
@ -216,6 +220,16 @@ class _PerformVisitor
var innerScope = scope; var innerScope = scope;
scope = (callback) => _withSelector(null, () => innerScope(callback)); scope = (callback) => _withSelector(null, () => innerScope(callback));
} }
if (_inUnknownAtRule && !included.any((parent) => parent is CssAtRule)) {
var innerScope = scope;
scope = (callback) {
var wasInUnknownAtRule = _inUnknownAtRule;
_inUnknownAtRule = false;
var result = innerScope(callback);
_inUnknownAtRule = wasInUnknownAtRule;
return result;
};
}
return scope; return scope;
} }
@ -248,7 +262,7 @@ class _PerformVisitor
} }
Value visitDeclaration(Declaration node) { Value visitDeclaration(Declaration node) {
if (_selector == null) { if (_selector == null && !_inUnknownAtRule) {
throw _exception( throw _exception(
"Declarations may only be used within style rules.", node.span); "Declarations may only be used within style rules.", node.span);
} }
@ -335,6 +349,8 @@ class _PerformVisitor
"At-rules may not be used within nested declarations.", node.span); "At-rules may not be used within nested declarations.", node.span);
} }
var wasInUnknownAtRule = _inUnknownAtRule;
_inUnknownAtRule = true;
var value = node.value == null var value = node.value == null
? null ? null
: _interpolationToValue(node.value, trim: true); : _interpolationToValue(node.value, trim: true);
@ -363,6 +379,7 @@ class _PerformVisitor
} }
}, through: (node) => node is CssStyleRule); }, through: (node) => node is CssStyleRule);
_inUnknownAtRule = wasInUnknownAtRule;
return null; return null;
} }