Support explicit @charset.

This commit is contained in:
Natalie Weizenbaum 2016-10-18 16:22:42 -07:00
parent dd4a9165a2
commit c8f0126f0b
4 changed files with 25 additions and 9 deletions

View File

@ -86,10 +86,12 @@ class StringExpression implements Expression {
int _bestQuote() { int _bestQuote() {
var containsDoubleQuote = false; var containsDoubleQuote = false;
for (var value in text.contents) { for (var value in text.contents) {
for (var i = 0; i < value.length; i++) { if (value is String) {
var codeUnit = value.codeUnitAt(i); for (var i = 0; i < value.length; i++) {
if (codeUnit == $single_quote) return $double_quote; var codeUnit = value.codeUnitAt(i);
if (codeUnit == $double_quote) containsDoubleQuote = true; if (codeUnit == $single_quote) return $double_quote;
if (codeUnit == $double_quote) containsDoubleQuote = true;
}
} }
} }
return containsDoubleQuote ? $single_quote : $double_quote; return containsDoubleQuote ? $single_quote : $double_quote;

View File

@ -79,7 +79,8 @@ class SassParser extends StylesheetParser {
var statements = <Statement>[]; var statements = <Statement>[];
while (!scanner.isDone) { while (!scanner.isDone) {
statements.add(_child(statement)); var child = _child(statement);
if (child != null) statements.add(child);
var indentation = _readIndentation(); var indentation = _readIndentation();
assert(indentation == 0); assert(indentation == 0);
} }

View File

@ -92,7 +92,8 @@ class ScssParser extends StylesheetParser {
statements.add(_loudComment()); statements.add(_loudComment());
break; break;
default: default:
statements.add(statement()); var child = statement();
if (child != null) statements.add(child);
break; break;
} }
break; break;
@ -103,7 +104,8 @@ class ScssParser extends StylesheetParser {
break; break;
default: default:
statements.add(statement()); var child = statement();
if (child != null) statements.add(child);
break; break;
} }
} }

View File

@ -71,7 +71,8 @@ abstract class StylesheetParser extends Parser {
/// Consumes a statement that's allowed at the top level of the stylesheet. /// Consumes a statement that's allowed at the top level of the stylesheet.
Statement _topLevelStatement() { Statement _topLevelStatement() {
if (scanner.peekChar() == $at) return _atRule(_topLevelStatement); if (scanner.peekChar() == $at)
return _atRule(_topLevelStatement, root: true);
return _styleRule(); return _styleRule();
} }
@ -301,13 +302,20 @@ abstract class StylesheetParser extends Parser {
/// This consumes at-rules that are allowed at all levels of the document; the /// This consumes at-rules that are allowed at all levels of the document; the
/// [child] parameter is called to consume any at-rules that are specifically /// [child] parameter is called to consume any at-rules that are specifically
/// allowed in the caller's context. /// allowed in the caller's context.
Statement _atRule(Statement child()) { ///
/// If [root] is `true`, this parses at-rules that are allowed only at the
/// root of the stylesheet.
Statement _atRule(Statement child(), {bool root: false}) {
var start = scanner.state; var start = scanner.state;
var name = _atRuleName(); var name = _atRuleName();
switch (name) { switch (name) {
case "at-root": case "at-root":
return _atRootRule(start); return _atRootRule(start);
case "charset":
if (!root) _disallowedAtRule(start);
string();
return null;
case "content": case "content":
return _contentRule(start); return _contentRule(start);
case "debug": case "debug":
@ -2193,5 +2201,8 @@ abstract class StylesheetParser extends Parser {
List<Statement> children(Statement child()); List<Statement> children(Statement child());
/// Consumes top-level statements. /// Consumes top-level statements.
///
/// The [statement] callback may return `null`, indicating that a statement
/// was consumed that shouldn't be added to the AST.
List<Statement> statements(Statement statement()); List<Statement> statements(Statement statement());
} }