Merge branch 'master' into support-ident-ie-filter
diff --git a/example/call_parser.dart b/example/call_parser.dart
index c77cf03..9a993ea 100644
--- a/example/call_parser.dart
+++ b/example/call_parser.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
import 'package:csslib/parser.dart' as css;
-import 'package:csslib/src/messages.dart';
import 'package:csslib/visitor.dart';
const _default = const css.PreprocessorOptions(
@@ -17,7 +16,7 @@
* tests (by default) will ensure that the CSS is really valid.
*/
StyleSheet parseCss(String cssInput,
- {List<Message> errors, css.PreprocessorOptions opts}) {
+ {List<css.Message> errors, css.PreprocessorOptions opts}) {
return css.parse(cssInput,
errors: errors, options: opts == null ? _default : opts);
}
@@ -28,7 +27,7 @@
(emitCss..visitTree(ss, pretty: true)).toString();
main() {
- var errors = <Message>[];
+ var errors = <css.Message>[];
// Parse a simple stylesheet.
print('1. Good CSS, parsed CSS emitted:');
diff --git a/lib/css.dart b/lib/css.dart
index a6539cf..c417354 100644
--- a/lib/css.dart
+++ b/lib/css.dart
@@ -10,9 +10,8 @@
import 'package:source_span/source_span.dart';
import 'parser.dart';
+import 'src/messages.dart' show Messages;
import 'visitor.dart';
-import 'src/messages.dart';
-import 'src/options.dart';
void main(List<String> arguments) {
// TODO(jmesserly): fix this to return a proper exit code
diff --git a/lib/parser.dart b/lib/parser.dart
index 7dfe184..6b05c85 100644
--- a/lib/parser.dart
+++ b/lib/parser.dart
@@ -8,10 +8,11 @@
import 'package:source_span/source_span.dart';
-import "visitor.dart";
+import 'visitor.dart';
import 'src/messages.dart';
import 'src/options.dart';
+export 'src/messages.dart' show Message;
export 'src/options.dart';
part 'src/analyzer.dart';
@@ -1218,6 +1219,20 @@
return new Selector(simpleSequences, _makeSpan(start));
}
+ /// Same as [processSelector] but reports an error for each combinator.
+ ///
+ /// This is a quick fix for parsing <compound-selectors> until the parser
+ /// supports Selector Level 4 grammar:
+ /// https://drafts.csswg.org/selectors-4/#typedef-compound-selector
+ Selector processCompoundSelector() {
+ return processSelector()
+ ..simpleSelectorSequences.forEach((sequence) {
+ if (!sequence.isCombinatorNone) {
+ _error('compound selector can not contain combinator', sequence.span);
+ }
+ });
+ }
+
simpleSelectorSequence(bool forceCombinatorNone) {
var start = _peekToken.span;
var combinatorType = TokenKind.COMBINATOR_NONE;
@@ -1428,7 +1443,8 @@
// Functional pseudo?
if (_peekToken.kind == TokenKind.LPAREN) {
- if (!pseudoElement && pseudoName.name.toLowerCase() == 'not') {
+ var name = pseudoName.name.toLowerCase();
+ if (!pseudoElement && name == 'not') {
_eat(TokenKind.LPAREN);
// Negation : ':NOT(' S* negation_arg S* ')'
@@ -1436,6 +1452,12 @@
_eat(TokenKind.RPAREN);
return new NegationSelector(negArg, _makeSpan(start));
+ } else if (!pseudoElement && (name == 'host' || name == 'host-context')) {
+ _eat(TokenKind.LPAREN);
+ var selector = processCompoundSelector();
+ _eat(TokenKind.RPAREN);
+ var span = _makeSpan(start);
+ return new PseudoClassFunctionSelector(pseudoName, selector, span);
} else {
// Special parsing for expressions in pseudo functions. Minus is used
// as operator not identifier.
diff --git a/lib/src/css_printer.dart b/lib/src/css_printer.dart
index a62ca47..d3b62d0 100644
--- a/lib/src/css_printer.dart
+++ b/lib/src/css_printer.dart
@@ -107,16 +107,14 @@
emit(node._ident);
emit(node.hasPseudoPage ? ':${node._pseudoPage}' : '');
}
- emit(' ');
var declsMargin = node._declsMargin;
var declsMarginLength = declsMargin.length;
+ emit(' {$_newLine');
for (var i = 0; i < declsMarginLength; i++) {
- if (i > 0) emit(_newLine);
- emit('{$_newLine');
declsMargin[i].visit(this);
- emit('}');
}
+ emit('}');
}
/** @charset "charset encoding" */
@@ -326,7 +324,7 @@
void visitPseudoClassFunctionSelector(PseudoClassFunctionSelector node) {
emit(":${node.name}(");
- node.expression.visit(this);
+ node.argument.visit(this);
emit(')');
}
diff --git a/lib/src/tree.dart b/lib/src/tree.dart
index a6a64fc..63c7301 100644
--- a/lib/src/tree.dart
+++ b/lib/src/tree.dart
@@ -291,15 +291,19 @@
String toString() => "::$name";
}
-// :pseudoClassFunction(expression)
+// :pseudoClassFunction(argument)
class PseudoClassFunctionSelector extends PseudoClassSelector {
- final SelectorExpression expression;
+ final TreeNode _argument; // Selector, SelectorExpression
- PseudoClassFunctionSelector(Identifier name, this.expression, SourceSpan span)
+ PseudoClassFunctionSelector(Identifier name, this._argument, SourceSpan span)
: super(name, span);
PseudoClassFunctionSelector clone() =>
- new PseudoClassFunctionSelector(_name, expression, span);
+ new PseudoClassFunctionSelector(_name, _argument, span);
+
+ TreeNode get argument => _argument;
+ Selector get selector => _argument as Selector;
+ SelectorExpression get expression => _argument as SelectorExpression;
visit(VisitorBase visitor) => visitor.visitPseudoClassFunctionSelector(this);
}
diff --git a/lib/src/tree_printer.dart b/lib/src/tree_printer.dart
index 9b0a6c2..97c6acc 100644
--- a/lib/src/tree_printer.dart
+++ b/lib/src/tree_printer.dart
@@ -338,7 +338,7 @@
void visitPseudoClassFunctionSelector(PseudoClassFunctionSelector node) {
heading('Pseudo Class Function Selector', node);
output.depth++;
- visitSelectorExpression(node.expression);
+ node.argument.visit(this);
super.visitPseudoClassFunctionSelector(node);
output.depth--;
}
diff --git a/pubspec.yaml b/pubspec.yaml
index f1cac20..8ed29b6 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: csslib
-version: 0.13.3
+version: 0.13.6
author: Dart Team <misc@dartlang.org>
description: A library for parsing CSS.
homepage: https://github.com/dart-lang/csslib
diff --git a/test/declaration_test.dart b/test/declaration_test.dart
index c92d68a..007916d 100644
--- a/test/declaration_test.dart
+++ b/test/declaration_test.dart
@@ -287,6 +287,7 @@
width: 10px;
}
@page bar : left { @top-left { margin: 8px; } }
+@page { @top-left { margin: 8px; } width: 10px; }
@charset "ISO-8859-1";
@charset 'ASCII';''';
@@ -308,6 +309,12 @@
margin: 8px;
}
}
+@page {
+@top-left {
+ margin: 8px;
+}
+ width: 10px;
+}
@charset "ISO-8859-1";
@charset "ASCII";''';
diff --git a/test/selector_test.dart b/test/selector_test.dart
index dff4415..87fb60a 100644
--- a/test/selector_test.dart
+++ b/test/selector_test.dart
@@ -46,6 +46,18 @@
selectorAst = selector('#_privateId', errors: errors..clear());
expect(errors.isEmpty, true, reason: errors.toString());
expect('#_privateId', compactOuptut(selectorAst));
+
+ selectorAst = selector(':host', errors: errors..clear());
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(compactOuptut(selectorAst), ':host');
+
+ selectorAst = selector(':host(.foo)', errors: errors..clear());
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(compactOuptut(selectorAst), ':host(.foo)');
+
+ selectorAst = selector(':host-context(.foo)', errors: errors..clear());
+ expect(errors.isEmpty, true, reason: errors.toString());
+ expect(compactOuptut(selectorAst), ':host-context(.foo)');
}
// TODO(terry): Move this failure case to a failure_test.dart when the analyzer