processDirective method
Directive grammar:
import: '@import' [string | URI] media_list?
media: '@media' media_query_list '{' ruleset '}'
page: '@page' [':' IDENT]? '{' declarations '}'
stylet: '@stylet' IDENT '{' ruleset '}'
media_query_list: IDENT [',' IDENT]
keyframes: '@-webkit-keyframes ...' (see grammar below).
font_face: '@font-face' '{' declarations '}'
namespace: '@namespace name url("xmlns")
host: '@host '{' ruleset '}'
mixin: '@mixin name [(args,...)] '{' declarations/ruleset '}'
include: '@include name [(@arg,@arg1)]
'@include name [(@arg...)]
content: '@content'
-moz-document: '@-moz-document' [ <url> | url-prefix(<string>) |
domain(<string>) | regexp(<string) ]# '{'
declarations
'}'
supports: '@supports' supports_condition group_rule_body
Implementation
CSSRule? processDirective() {
var tokenId = _peek();
switch (tokenId) {
case TokenKind.DIRECTIVE_IMPORT:
_next();
return null;
case TokenKind.DIRECTIVE_MEDIA:
while (!_maybeEat(TokenKind.END_OF_FILE) && !_maybeEat(TokenKind.RBRACE)) {
_next();
}
return null;
case TokenKind.DIRECTIVE_HOST:
_next();
return null;
case TokenKind.DIRECTIVE_PAGE:
// @page S* IDENT? pseudo_page?
// S* '{' S*
// [ declaration | margin ]?
// [ ';' S* [ declaration | margin ]? ]* '}' S*
//
// pseudo_page :
// ':' [ "left" | "right" | "first" ]
//
// margin :
// margin_sym S* '{' declaration [ ';' S* declaration? ]* '}' S*
//
// margin_sym : @top-left-corner, @top-left, @bottom-left, etc.
//
// See http://www.w3.org/TR/css3-page/#CSS21
_next();
return null;
case TokenKind.DIRECTIVE_CHARSET:
// @charset S* STRING S* ';'
_next();
processQuotedString(false);
return null;
// TODO(terry): Workaround Dart2js bug continue not implemented in switch
// see https://code.google.com/p/dart/issues/detail?id=8270
/*
case TokenKind.DIRECTIVE_MS_KEYFRAMES:
// TODO(terry): For now only IE 10 (are base level) supports @keyframes,
// -moz- has only been optional since Oct 2012 release of Firefox, not
// all versions of webkit support @keyframes and opera doesn't yet
// support w/o -o- prefix. Add more warnings for other prefixes when
// they become optional.
if (isChecked) {
_warning('@-ms-keyframes should be @keyframes');
}
continue keyframeDirective;
keyframeDirective:
*/
case TokenKind.DIRECTIVE_KEYFRAMES:
case TokenKind.DIRECTIVE_WEB_KIT_KEYFRAMES:
case TokenKind.DIRECTIVE_MOZ_KEYFRAMES:
case TokenKind.DIRECTIVE_O_KEYFRAMES:
// TODO(terry): Remove workaround when bug 8270 is fixed.
case TokenKind.DIRECTIVE_MS_KEYFRAMES:
if (tokenId == TokenKind.DIRECTIVE_MS_KEYFRAMES && isChecked) {
_warning('@-ms-keyframes should be @keyframes');
}
// TODO(terry): End of workaround.
// Key frames grammar:
//
// @[browser]? keyframes [IDENT|STRING] '{' keyframes-blocks '}';
//
// browser: [-webkit-, -moz-, -ms-, -o-]
//
// keyframes-blocks:
// [keyframe-selectors '{' declarations '}']* ;
//
// keyframe-selectors:
// ['from'|'to'|PERCENTAGE] [',' ['from'|'to'|PERCENTAGE] ]* ;
_next();
String name = '';
if (_peekIdentifier()) {
name = identifier().name;
}
assert(name.isNotEmpty, 'keyframes rule name must not be null');
_eat(TokenKind.LBRACE);
var keyframe = CSSKeyframesRule(tokenId, name);
do {
List<String> selectors = [];
do {
var selector = _next().text;
final text = _peekToken.text;
// ignore unit type
if (TokenKind.matchUnits(text, 0, text.length) != -1) {
if (_peekToken.kind == TokenKind.PERCENT) {
selector += text; // join selector & unit
}
_next();
}
selectors.add(selector);
} while (_maybeEat(TokenKind.COMMA));
final declarations = processDeclarations();
if (declarations.last is CSSStyleDeclaration) {
keyframe.add(KeyFrameBlock(selectors, declarations.last));
}
} while (!_maybeEat(TokenKind.RBRACE) && !isPrematureEndOfFile());
return keyframe;
case TokenKind.DIRECTIVE_FONTFACE:
_next();
_eat(TokenKind.LBRACE);
List data = processDeclarations();
assert(data.isNotEmpty);
return CSSFontFaceRule(data[0]);
case TokenKind.DIRECTIVE_STYLET:
// Stylet grammar:
//
// @stylet IDENT '{'
// ruleset
// '}'
_next();
return null;
case TokenKind.DIRECTIVE_NAMESPACE:
// Namespace grammar:
//
// @namespace S* [namespace_prefix S*]? [STRING|URI] S* ';' S*
// namespace_prefix : IDENT
_next();
return null;
case TokenKind.DIRECTIVE_MIXIN:
return null;
case TokenKind.DIRECTIVE_INCLUDE:
return null;
case TokenKind.DIRECTIVE_CONTENT:
// TODO(terry): TBD
_warning('@content not implemented.');
return null;
case TokenKind.DIRECTIVE_MOZ_DOCUMENT:
return null;
case TokenKind.DIRECTIVE_SUPPORTS:
return null;
case TokenKind.DIRECTIVE_VIEWPORT:
case TokenKind.DIRECTIVE_MS_VIEWPORT:
return null;
}
return null;
}