Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1084)

Side by Side Diff: pkg/csslib/lib/parser.dart

Issue 60983003: pkg/csslib: fixed analysis error, more cleanup (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: rebase Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/csslib/lib/src/analyzer.dart » ('j') | pkg/csslib/lib/src/css_printer.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library csslib.parser; 5 library csslib.parser;
6 6
7 import 'dart:math' as math; 7 import 'dart:math' as math;
8 8
9 import 'package:source_maps/span.dart' show SourceFile, Span, FileSpan; 9 import 'package:source_maps/span.dart' show SourceFile, Span, FileSpan;
10 10
(...skipping 12 matching lines...) Expand all
23 23
24 /** Used for parser lookup ahead (used for nested selectors Less support). */ 24 /** Used for parser lookup ahead (used for nested selectors Less support). */
25 class ParserState extends TokenizerState { 25 class ParserState extends TokenizerState {
26 final Token peekToken; 26 final Token peekToken;
27 final Token previousToken; 27 final Token previousToken;
28 28
29 ParserState(this.peekToken, this.previousToken, Tokenizer tokenizer) 29 ParserState(this.peekToken, this.previousToken, Tokenizer tokenizer)
30 : super(tokenizer); 30 : super(tokenizer);
31 } 31 }
32 32
33 void _createMessages({List errors, List options}) { 33 void _createMessages({List<Message> errors, List<String> options}) {
34 if (errors == null) errors = []; 34 if (errors == null) errors = [];
35 35
36 if (options == null) { 36 if (options == null) {
37 options = ['--no-colors', 'memory']; 37 options = ['--no-colors', 'memory'];
38 } 38 }
39 var opt = PreprocessorOptions.parse(options); 39 var opt = PreprocessorOptions.parse(options);
40 messages = new Messages(options: opt, printHandler: errors.add); 40 messages = new Messages(options: opt, printHandler: errors.add);
41 } 41 }
42 42
43 /** CSS checked mode enabled. */ 43 /** CSS checked mode enabled. */
44 bool get isChecked => messages.options.checked; 44 bool get isChecked => messages.options.checked;
45 45
46 // TODO(terry): Remove nested name parameter. 46 // TODO(terry): Remove nested name parameter.
47 /** Parse and analyze the CSS file. */ 47 /** Parse and analyze the CSS file. */
48 StyleSheet compile(var input, {List errors, List options, bool nested: true, 48 StyleSheet compile(var input, {List<Message> errors, List<String> options,
49 bool polyfill: false, List<StyleSheet> includes: null}) { 49 bool nested: true,
terry 2013/11/20 14:07:25 keep rest of params on same line indent +4
kevmoo-old 2013/11/20 19:13:11 Done.
50 bool polyfill: false,
51 List<StyleSheet> includes: null}) {
52
50 if (includes == null) { 53 if (includes == null) {
51 includes = []; 54 includes = [];
52 } 55 }
53 56
54 var source = _inputAsString(input); 57 var source = _inputAsString(input);
55 58
56 _createMessages(errors: errors, options: options); 59 _createMessages(errors: errors, options: options);
57 60
58 var file = new SourceFile.text(null, source); 61 var file = new SourceFile.text(null, source);
59 62
60 var tree = new _Parser(file, source).parse(); 63 var tree = new _Parser(file, source).parse();
61 64
62 analyze([tree], errors: errors, options: options); 65 analyze([tree], errors: errors, options: options);
63 66
64 if (polyfill) { 67 if (polyfill) {
65 var processCss = new PolyFill(messages, true); 68 var processCss = new PolyFill(messages, true);
66 processCss.process(tree, includes: includes); 69 processCss.process(tree, includes: includes);
67 } 70 }
68 71
69 return tree; 72 return tree;
70 } 73 }
71 74
72 /** Analyze the CSS file. */ 75 /** Analyze the CSS file. */
73 void analyze(List<StyleSheet> styleSheets, {List errors, List options}) { 76 void analyze(List<StyleSheet> styleSheets,
77 {List<Message> errors, List<String> options}) {
terry 2013/11/20 14:07:25 indent + 4
kevmoo-old 2013/11/20 19:13:11 Done.
78
74 _createMessages(errors: errors, options: options); 79 _createMessages(errors: errors, options: options);
75 new Analyzer(styleSheets, messages).run(); 80 new Analyzer(styleSheets, messages).run();
76 } 81 }
77 82
78 /** 83 /**
79 * Parse the [input] CSS stylesheet into a tree. The [input] can be a [String], 84 * Parse the [input] CSS stylesheet into a tree. The [input] can be a [String],
80 * or [List<int>] of bytes and returns a [StyleSheet] AST. The optional 85 * or [List<int>] of bytes and returns a [StyleSheet] AST. The optional
81 * [errors] list will contain each error/warning as a [Message]. 86 * [errors] list will contain each error/warning as a [Message].
82 */ 87 */
83 StyleSheet parse(var input, {List errors, List options}) { 88 StyleSheet parse(var input, {List<Message> errors, List<String> options}) {
84 var source = _inputAsString(input); 89 var source = _inputAsString(input);
85 90
86 _createMessages(errors: errors, options: options); 91 _createMessages(errors: errors, options: options);
87 92
88 var file = new SourceFile.text(null, source); 93 var file = new SourceFile.text(null, source);
89 94
90 return new _Parser(file, source).parse(); 95 return new _Parser(file, source).parse();
91 } 96 }
92 97
93 /** 98 /**
94 * Parse the [input] CSS selector into a tree. The [input] can be a [String], 99 * Parse the [input] CSS selector into a tree. The [input] can be a [String],
95 * or [List<int>] of bytes and returns a [StyleSheet] AST. The optional 100 * or [List<int>] of bytes and returns a [StyleSheet] AST. The optional
96 * [errors] list will contain each error/warning as a [Message]. 101 * [errors] list will contain each error/warning as a [Message].
97 */ 102 */
98 StyleSheet selector(var input, {List errors}) { 103 StyleSheet selector(var input, {List<Message> errors}) {
99 var source = _inputAsString(input); 104 var source = _inputAsString(input);
100 105
101 _createMessages(errors: errors); 106 _createMessages(errors: errors);
102 107
103 var file = new SourceFile.text(null, source); 108 var file = new SourceFile.text(null, source);
104 109
105 return new _Parser(file, source).parseSelector(); 110 return new _Parser(file, source).parseSelector();
106 } 111 }
107 112
108 String _inputAsString(var input) { 113 String _inputAsString(var input) {
109 String source; 114 String source;
terry 2013/11/20 14:07:25 var source;
kevmoo-old 2013/11/20 19:13:11 Since 'source' is not assigned immediately, the ty
110 115
111 if (input is String) { 116 if (input is String) {
112 source = input; 117 source = input;
113 } else if (input is List<int>) { 118 } else if (input is List<int>) {
114 // TODO(terry): The parse function needs an "encoding" argument and will 119 // TODO(terry): The parse function needs an "encoding" argument and will
115 // default to whatever encoding CSS defaults to. 120 // default to whatever encoding CSS defaults to.
116 // 121 //
117 // Here's some info about CSS encodings: 122 // Here's some info about CSS encodings:
118 // http://www.w3.org/International/questions/qa-css-charset.en.php 123 // http://www.w3.org/International/questions/qa-css-charset.en.php
119 // 124 //
(...skipping 23 matching lines...) Expand all
143 final _Parser _parser; 148 final _Parser _parser;
144 149
145 Parser(SourceFile file, String text, {int start: 0, String baseUrl}) : 150 Parser(SourceFile file, String text, {int start: 0, String baseUrl}) :
146 _parser = new _Parser(file, text, start: start, baseUrl: baseUrl); 151 _parser = new _Parser(file, text, start: start, baseUrl: baseUrl);
147 152
148 StyleSheet parse() => _parser.parse(); 153 StyleSheet parse() => _parser.parse();
149 } 154 }
150 155
151 /** A simple recursive descent parser for CSS. */ 156 /** A simple recursive descent parser for CSS. */
152 class _Parser { 157 class _Parser {
153 Tokenizer tokenizer; 158 final Tokenizer tokenizer;
154 159
155 /** Base url of CSS file. */ 160 /** Base url of CSS file. */
156 final String _baseUrl; 161 final String _baseUrl;
157 162
158 /** 163 /**
159 * File containing the source being parsed, used to report errors with 164 * File containing the source being parsed, used to report errors with
160 * source-span locations. 165 * source-span locations.
161 */ 166 */
162 final SourceFile file; 167 final SourceFile file;
163 168
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 } while (_maybeEat(TokenKind.COMMA)); 1182 } while (_maybeEat(TokenKind.COMMA));
1178 1183
1179 if (selectors.length > 0) { 1184 if (selectors.length > 0) {
1180 return new SelectorGroup(selectors, _makeSpan(start)); 1185 return new SelectorGroup(selectors, _makeSpan(start));
1181 } 1186 }
1182 } 1187 }
1183 1188
1184 /** 1189 /**
1185 * Return list of selectors 1190 * Return list of selectors
1186 */ 1191 */
1187 processSelector() { 1192 Selector processSelector() {
1188 List<SimpleSelectorSequence> simpleSequences = []; 1193 List<SimpleSelectorSequence> simpleSequences = [];
terry 2013/11/20 14:07:25 var simpleSequences = [];
kevmoo-old 2013/11/20 19:13:11 Done.
1189 int start = _peekToken.start; 1194 int start = _peekToken.start;
terry 2013/11/20 14:07:25 var start - _peekToken.start;
kevmoo-old 2013/11/20 19:13:11 Done.
1190 while (true) { 1195 while (true) {
1191 // First item is never descendant make sure it's COMBINATOR_NONE. 1196 // First item is never descendant make sure it's COMBINATOR_NONE.
1192 var selectorItem = simpleSelectorSequence(simpleSequences.length == 0); 1197 var selectorItem = simpleSelectorSequence(simpleSequences.length == 0);
1193 if (selectorItem != null) { 1198 if (selectorItem != null) {
1194 simpleSequences.add(selectorItem); 1199 simpleSequences.add(selectorItem);
1195 } else { 1200 } else {
1196 break; 1201 break;
1197 } 1202 }
1198 } 1203 }
1199 1204
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 * class 1277 * class
1273 * : '.' IDENT 1278 * : '.' IDENT
1274 */ 1279 */
1275 simpleSelector() { 1280 simpleSelector() {
1276 // TODO(terry): Nathan makes a good point parsing of namespace and element 1281 // TODO(terry): Nathan makes a good point parsing of namespace and element
1277 // are essentially the same (asterisk or identifier) other 1282 // are essentially the same (asterisk or identifier) other
1278 // than the error message for element. Should consolidate the 1283 // than the error message for element. Should consolidate the
1279 // code. 1284 // code.
1280 // TODO(terry): Need to handle attribute namespace too. 1285 // TODO(terry): Need to handle attribute namespace too.
1281 var first; 1286 var first;
1282 int start = _peekToken.start; 1287 int start = _peekToken.start;
terry 2013/11/20 14:07:25 var start = ...
1283 switch (_peek()) { 1288 switch (_peek()) {
1284 case TokenKind.ASTERISK: 1289 case TokenKind.ASTERISK:
1285 // Mark as universal namespace. 1290 // Mark as universal namespace.
1286 var tok = _next(); 1291 var tok = _next();
1287 first = new Wildcard(_makeSpan(tok.start)); 1292 first = new Wildcard(_makeSpan(tok.start));
1288 break; 1293 break;
1289 case TokenKind.IDENTIFIER: 1294 case TokenKind.IDENTIFIER:
1290 first = identifier(); 1295 first = identifier();
1291 break; 1296 break;
1292 default: 1297 default:
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 } 1342 }
1338 1343
1339 return false; 1344 return false;
1340 } 1345 }
1341 1346
1342 /** 1347 /**
1343 * type_selector | universal | HASH | class | attrib | pseudo 1348 * type_selector | universal | HASH | class | attrib | pseudo
1344 */ 1349 */
1345 simpleSelectorTail() { 1350 simpleSelectorTail() {
1346 // Check for HASH | class | attrib | pseudo | negation 1351 // Check for HASH | class | attrib | pseudo | negation
1347 int start = _peekToken.start; 1352 int start = _peekToken.start;
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Done.
1348 switch (_peek()) { 1353 switch (_peek()) {
1349 case TokenKind.HASH: 1354 case TokenKind.HASH:
1350 _eat(TokenKind.HASH); 1355 _eat(TokenKind.HASH);
1351 1356
1352 bool hasWhiteSpace = false; 1357 bool hasWhiteSpace = false;
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Done.
1353 if (_anyWhiteSpaceBeforePeekToken(TokenKind.HASH)) { 1358 if (_anyWhiteSpaceBeforePeekToken(TokenKind.HASH)) {
1354 _warning("Not a valid ID selector expected #id", _makeSpan(start)); 1359 _warning("Not a valid ID selector expected #id", _makeSpan(start));
1355 hasWhiteSpace = true; 1360 hasWhiteSpace = true;
1356 } 1361 }
1357 if (_peekIdentifier()) { 1362 if (_peekIdentifier()) {
1358 var id = identifier(); 1363 var id = identifier();
1359 if (hasWhiteSpace) { 1364 if (hasWhiteSpace) {
1360 // Generate bad selector id (normalized). 1365 // Generate bad selector id (normalized).
1361 id.name = " ${id.name}"; 1366 id.name = " ${id.name}";
1362 } 1367 }
(...skipping 25 matching lines...) Expand all
1388 _peekToken.span); 1393 _peekToken.span);
1389 _next(); 1394 _next();
1390 break; 1395 break;
1391 } 1396 }
1392 } 1397 }
1393 1398
1394 processPseudoSelector(int start) { 1399 processPseudoSelector(int start) {
1395 // :pseudo-class ::pseudo-element 1400 // :pseudo-class ::pseudo-element
1396 // TODO(terry): '::' should be token. 1401 // TODO(terry): '::' should be token.
1397 _eat(TokenKind.COLON); 1402 _eat(TokenKind.COLON);
1398 bool pseudoElement = _maybeEat(TokenKind.COLON); 1403 bool pseudoElement = _maybeEat(TokenKind.COLON);
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Done.
1399 1404
1400 // TODO(terry): If no identifier specified consider optimizing out the 1405 // TODO(terry): If no identifier specified consider optimizing out the
1401 // : or :: and making this a normal selector. For now, 1406 // : or :: and making this a normal selector. For now,
1402 // create an empty pseudoName. 1407 // create an empty pseudoName.
1403 var pseudoName; 1408 var pseudoName;
1404 if (_peekIdentifier()) { 1409 if (_peekIdentifier()) {
1405 pseudoName = identifier(); 1410 pseudoName = identifier();
1406 } else { 1411 } else {
1407 return null; 1412 return null;
1408 } 1413 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1449 * In CSS3, the expressions are identifiers, strings, or of the form "an+b". 1454 * In CSS3, the expressions are identifiers, strings, or of the form "an+b".
1450 * 1455 *
1451 * : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+ 1456 * : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+
1452 * 1457 *
1453 * num [0-9]+|[0-9]*\.[0-9]+ 1458 * num [0-9]+|[0-9]*\.[0-9]+
1454 * PLUS '+' 1459 * PLUS '+'
1455 * DIMENSION {num}{ident} 1460 * DIMENSION {num}{ident}
1456 * NUMBER {num} 1461 * NUMBER {num}
1457 */ 1462 */
1458 processSelectorExpression() { 1463 processSelectorExpression() {
1459 int start = _peekToken.start; 1464 int start = _peekToken.start;
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Done.
1460 1465
1461 var expression = new SelectorExpression(_makeSpan(start)); 1466 var expression = new SelectorExpression(_makeSpan(start));
1462 1467
1463 Token termToken; 1468 Token termToken;
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Leaving type since it's not inferred from a first
1464 var value; 1469 var value;
1465 1470
1466 // Special parsing for expressions in pseudo functions. Minus is used as 1471 // Special parsing for expressions in pseudo functions. Minus is used as
1467 // operator not identifier. 1472 // operator not identifier.
1468 tokenizer.selectorExpression = true; 1473 tokenizer.selectorExpression = true;
1469 1474
1470 bool keepParsing = true; 1475 bool keepParsing = true;
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Done.
1471 while (keepParsing) { 1476 while (keepParsing) {
1472 switch (_peek()) { 1477 switch (_peek()) {
1473 case TokenKind.PLUS: 1478 case TokenKind.PLUS:
1474 start = _peekToken.start; 1479 start = _peekToken.start;
1475 termToken = _next(); 1480 termToken = _next();
1476 expression.add(new OperatorPlus(_makeSpan(start))); 1481 expression.add(new OperatorPlus(_makeSpan(start)));
1477 break; 1482 break;
1478 case TokenKind.MINUS: 1483 case TokenKind.MINUS:
1479 start = _peekToken.start; 1484 start = _peekToken.start;
1480 termToken = _next(); 1485 termToken = _next();
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1532 // 1537 //
1533 // DASHMATCH: '|=' 1538 // DASHMATCH: '|='
1534 // 1539 //
1535 // PREFIXMATCH: '^=' 1540 // PREFIXMATCH: '^='
1536 // 1541 //
1537 // SUFFIXMATCH: '$=' 1542 // SUFFIXMATCH: '$='
1538 // 1543 //
1539 // SUBSTRMATCH: '*=' 1544 // SUBSTRMATCH: '*='
1540 // 1545 //
1541 // 1546 //
1542 processAttribute() { 1547 AttributeSelector processAttribute() {
1543 int start = _peekToken.start; 1548 int start = _peekToken.start;
terry 2013/11/20 14:07:25 var
1544 1549
1545 if (_maybeEat(TokenKind.LBRACK)) { 1550 if (_maybeEat(TokenKind.LBRACK)) {
1546 var attrName = identifier(); 1551 var attrName = identifier();
1547 1552
1548 int op; 1553 int op;
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Not assigned. Keeping type.
1549 switch (_peek()) { 1554 switch (_peek()) {
1550 case TokenKind.EQUALS: 1555 case TokenKind.EQUALS:
1551 case TokenKind.INCLUDES: // ~= 1556 case TokenKind.INCLUDES: // ~=
1552 case TokenKind.DASH_MATCH: // |= 1557 case TokenKind.DASH_MATCH: // |=
1553 case TokenKind.PREFIX_MATCH: // ^= 1558 case TokenKind.PREFIX_MATCH: // ^=
1554 case TokenKind.SUFFIX_MATCH: // $= 1559 case TokenKind.SUFFIX_MATCH: // $=
1555 case TokenKind.SUBSTRING_MATCH: // *= 1560 case TokenKind.SUBSTRING_MATCH: // *=
1556 op = _peek(); 1561 op = _peek();
1557 _next(); 1562 _next();
1558 break; 1563 break;
(...skipping 27 matching lines...) Expand all
1586 // 1591 //
1587 // property: IDENT [or IE hacks] 1592 // property: IDENT [or IE hacks]
1588 // prio: !important 1593 // prio: !important
1589 // expr: (see processExpr) 1594 // expr: (see processExpr)
1590 // 1595 //
1591 // Here are the ugly IE hacks we need to support: 1596 // Here are the ugly IE hacks we need to support:
1592 // property: expr prio? \9; - IE8 and below property, /9 before semi-colon 1597 // property: expr prio? \9; - IE8 and below property, /9 before semi-colon
1593 // *IDENT - IE7 or below 1598 // *IDENT - IE7 or below
1594 // _IDENT - IE6 property (automatically a valid ident) 1599 // _IDENT - IE6 property (automatically a valid ident)
1595 // 1600 //
1596 processDeclaration(List dartStyles) { 1601 Declaration processDeclaration(List dartStyles) {
1597 Declaration decl; 1602 Declaration decl;
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Not assigned, keeping type.
1598 1603
1599 int start = _peekToken.start; 1604 int start = _peekToken.start;
1600 1605
1601 // IE7 hack of * before property name if so the property is IE7 or below. 1606 // IE7 hack of * before property name if so the property is IE7 or below.
1602 var ie7 = _peekKind(TokenKind.ASTERISK); 1607 var ie7 = _peekKind(TokenKind.ASTERISK);
1603 if (ie7) { 1608 if (ie7) {
1604 _next(); 1609 _next();
1605 } 1610 }
1606 1611
1607 // IDENT ':' expr '!important'? 1612 // IDENT ':' expr '!important'?
(...skipping 22 matching lines...) Expand all
1630 1635
1631 Expressions exprs = processExpr(); 1636 Expressions exprs = processExpr();
1632 1637
1633 decl = new VarDefinition(definedName, exprs, _makeSpan(start)); 1638 decl = new VarDefinition(definedName, exprs, _makeSpan(start));
1634 } else if (_peekToken.kind == TokenKind.DIRECTIVE_INCLUDE) { 1639 } else if (_peekToken.kind == TokenKind.DIRECTIVE_INCLUDE) {
1635 // @include mixinName in the declaration area. 1640 // @include mixinName in the declaration area.
1636 var span = _makeSpan(start); 1641 var span = _makeSpan(start);
1637 var include = processInclude(span, eatSemiColon: false); 1642 var include = processInclude(span, eatSemiColon: false);
1638 decl = new IncludeMixinAtDeclaration(include, span); 1643 decl = new IncludeMixinAtDeclaration(include, span);
1639 } else if (_peekToken.kind == TokenKind.DIRECTIVE_EXTEND) { 1644 } else if (_peekToken.kind == TokenKind.DIRECTIVE_EXTEND) {
1640 List<SimpleSelectorSequence> simpleSequences = []; 1645 List<SimpleSelectorSequence> simpleSequences = [];
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Done.
1641 1646
1642 _next(); 1647 _next();
1643 var span = _makeSpan(start); 1648 var span = _makeSpan(start);
1644 var selector = simpleSelector(); 1649 var selector = simpleSelector();
1645 if (selector == null) { 1650 if (selector == null) {
1646 _warning("@extends expecting simple selector name", span); 1651 _warning("@extends expecting simple selector name", span);
1647 } else { 1652 } else {
1648 simpleSequences.add(selector); 1653 simpleSequences.add(selector);
1649 } 1654 }
1650 if (_peekKind(TokenKind.COLON)) { 1655 if (_peekKind(TokenKind.COLON)) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1723 'padding-top': _paddingPartTop, 1728 'padding-top': _paddingPartTop,
1724 'padding-right': _paddingPartRight, 1729 'padding-right': _paddingPartRight,
1725 'padding-bottom': _paddingPartBottom 1730 'padding-bottom': _paddingPartBottom
1726 }; 1731 };
1727 1732
1728 static const Map<String, int> _nameToFontWeight = const { 1733 static const Map<String, int> _nameToFontWeight = const {
1729 'bold' : FontWeight.bold, 1734 'bold' : FontWeight.bold,
1730 'normal' : FontWeight.normal 1735 'normal' : FontWeight.normal
1731 }; 1736 };
1732 1737
1733 static _findStyle(String styleName) { 1738 static _findStyle(String styleName) => _stylesToDart[styleName];
terry 2013/11/20 14:07:25 return type signature int
kevmoo-old 2013/11/20 19:13:11 Done.
1734 if (_stylesToDart.containsKey(styleName)) {
1735 return _stylesToDart[styleName];
1736 }
1737 }
1738 1739
1739 _styleForDart(Identifier property, Expressions exprs, List dartStyles) { 1740 DartStyleExpression _styleForDart(Identifier property, Expressions exprs, List dartStyles) {
terry 2013/11/20 14:07:25 new line after exprs param and indent +4 for remai
kevmoo-old 2013/11/20 19:13:11 Done.
1740 int styleType = _findStyle(property.name.toLowerCase()); 1741 int styleType = _findStyle(property.name.toLowerCase());
terry 2013/11/20 14:07:25 var styleType
kevmoo-old 2013/11/20 19:13:11 Done.
1741 if (styleType != null) { 1742 if (styleType != null) {
1742 return buildDartStyleNode(styleType, exprs, dartStyles); 1743 return buildDartStyleNode(styleType, exprs, dartStyles);
1743 } 1744 }
1744 } 1745 }
1745 1746
1746 FontExpression _mergeFontStyles(FontExpression fontExpr, List dartStyles) { 1747 FontExpression _mergeFontStyles(FontExpression fontExpr, List dartStyles) {
1747 // Merge all font styles for this class selector. 1748 // Merge all font styles for this class selector.
1748 for (var dartStyle in dartStyles) { 1749 for (var dartStyle in dartStyles) {
1749 if (dartStyle.isFont) { 1750 if (dartStyle.isFont) {
1750 fontExpr = new FontExpression.merge(dartStyle, fontExpr); 1751 fontExpr = new FontExpression.merge(dartStyle, fontExpr);
1751 } 1752 }
1752 } 1753 }
1753 1754
1754 return fontExpr; 1755 return fontExpr;
1755 } 1756 }
1756 1757
1757 buildDartStyleNode(int styleType, Expressions exprs, List dartStyles) { 1758 DartStyleExpression buildDartStyleNode(int styleType, Expressions exprs,
1759 List dartStyles) {
terry 2013/11/20 14:07:25 indent only +4 for new line.
kevmoo-old 2013/11/20 19:13:11 Done.
1760
1758 switch (styleType) { 1761 switch (styleType) {
1759 /* 1762 /*
1760 * Properties in order: 1763 * Properties in order:
1761 * 1764 *
1762 * font-style font-variant font-weight font-size/line-height font-family 1765 * font-style font-variant font-weight font-size/line-height font-family
1763 * 1766 *
1764 * The font-size and font-family values are required. If other values are 1767 * The font-size and font-family values are required. If other values are
1765 * missing; a default, if it exist, will be used. 1768 * missing; a default, if it exist, will be used.
1766 */ 1769 */
1767 case _fontPartFont: 1770 case _fontPartFont:
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1890 } 1893 }
1891 break; 1894 break;
1892 default: 1895 default:
1893 // Don't handle it. 1896 // Don't handle it.
1894 return null; 1897 return null;
1895 } 1898 }
1896 } 1899 }
1897 1900
1898 // TODO(terry): Look at handling width of thin, thick, etc. any none numbers 1901 // TODO(terry): Look at handling width of thin, thick, etc. any none numbers
1899 // to convert to a number. 1902 // to convert to a number.
1900 processOneNumber(Expressions exprs, int part) { 1903 DartStyleExpression processOneNumber(Expressions exprs, int part) {
1901 var value = marginValue(exprs.expressions[0]); 1904 var value = marginValue(exprs.expressions[0]);
1902 if (value != null) { 1905 if (value != null) {
1903 switch (part) { 1906 switch (part) {
1904 case _marginPartLeft: 1907 case _marginPartLeft:
1905 return new MarginExpression(exprs.span, left: value); 1908 return new MarginExpression(exprs.span, left: value);
1906 case _marginPartTop: 1909 case _marginPartTop:
1907 return new MarginExpression(exprs.span, top: value); 1910 return new MarginExpression(exprs.span, top: value);
1908 case _marginPartRight: 1911 case _marginPartRight:
1909 return new MarginExpression(exprs.span, right: value); 1912 return new MarginExpression(exprs.span, right: value);
1910 case _marginPartBottom: 1913 case _marginPartBottom:
(...skipping 29 matching lines...) Expand all
1940 /** 1943 /**
1941 * Margins are of the format: 1944 * Margins are of the format:
1942 * 1945 *
1943 * top,right,bottom,left (4 parameters) 1946 * top,right,bottom,left (4 parameters)
1944 * top,right/left, bottom (3 parameters) 1947 * top,right/left, bottom (3 parameters)
1945 * top/bottom,right/left (2 parameters) 1948 * top/bottom,right/left (2 parameters)
1946 * top/right/bottom/left (1 parameter) 1949 * top/right/bottom/left (1 parameter)
1947 * 1950 *
1948 * The values of the margins can be a unit or unitless or auto. 1951 * The values of the margins can be a unit or unitless or auto.
1949 */ 1952 */
1950 processFourNums(Expressions exprs) { 1953 BoxEdge processFourNums(Expressions exprs) {
1951 num top; 1954 num top;
1952 num right; 1955 num right;
1953 num bottom; 1956 num bottom;
1954 num left; 1957 num left;
1955 1958
1956 int totalExprs = exprs.expressions.length; 1959 int totalExprs = exprs.expressions.length;
1957 switch (totalExprs) { 1960 switch (totalExprs) {
1958 case 1: 1961 case 1:
1959 top = marginValue(exprs.expressions[0]); 1962 top = marginValue(exprs.expressions[0]);
1960 right = top; 1963 right = top;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1993 } 1996 }
1994 } 1997 }
1995 1998
1996 // Expression grammar: 1999 // Expression grammar:
1997 // 2000 //
1998 // expression: term [ operator? term]* 2001 // expression: term [ operator? term]*
1999 // 2002 //
2000 // operator: '/' | ',' 2003 // operator: '/' | ','
2001 // term: (see processTerm) 2004 // term: (see processTerm)
2002 // 2005 //
2003 processExpr([bool ieFilter = false]) { 2006 Expression processExpr([bool ieFilter = false]) {
terry 2013/11/20 14:07:25 returns Expressions
kevmoo-old 2013/11/20 19:13:11 Done.
2004 int start = _peekToken.start; 2007 int start = _peekToken.start;
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Done.
2005 Expressions expressions = new Expressions(_makeSpan(start)); 2008 Expressions expressions = new Expressions(_makeSpan(start));
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Done.
2006 2009
2007 bool keepGoing = true; 2010 bool keepGoing = true;
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Done.
2008 var expr; 2011 var expr;
2009 while (keepGoing && (expr = processTerm(ieFilter)) != null) { 2012 while (keepGoing && (expr = processTerm(ieFilter)) != null) {
2010 var op; 2013 var op;
2011 2014
2012 int opStart = _peekToken.start; 2015 int opStart = _peekToken.start;
2013 2016
2014 switch (_peek()) { 2017 switch (_peek()) {
2015 case TokenKind.SLASH: 2018 case TokenKind.SLASH:
2016 op = new OperatorSlash(_makeSpan(opStart)); 2019 op = new OperatorSlash(_makeSpan(opStart));
2017 break; 2020 break;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2054 keepGoing = false; 2057 keepGoing = false;
2055 } else { 2058 } else {
2056 _next(); 2059 _next();
2057 } 2060 }
2058 } 2061 }
2059 } 2062 }
2060 2063
2061 return expressions; 2064 return expressions;
2062 } 2065 }
2063 2066
2064 static int MAX_UNICODE = int.parse('0x10FFFF'); 2067 static final int MAX_UNICODE = int.parse('0x10FFFF');
2065 2068
2066 // Term grammar: 2069 // Term grammar:
2067 // 2070 //
2068 // term: 2071 // term:
2069 // unary_operator? 2072 // unary_operator?
2070 // [ term_value ] 2073 // [ term_value ]
2071 // | STRING S* | IDENT S* | URI S* | UNICODERANGE S* | hexcolor 2074 // | STRING S* | IDENT S* | URI S* | UNICODERANGE S* | hexcolor
2072 // 2075 //
2073 // term_value: 2076 // term_value:
2074 // NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* | 2077 // NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
2075 // TIME S* | FREQ S* | function 2078 // TIME S* | FREQ S* | function
2076 // 2079 //
2077 // NUMBER: {num} 2080 // NUMBER: {num}
2078 // PERCENTAGE: {num}% 2081 // PERCENTAGE: {num}%
2079 // LENGTH: {num}['px' | 'cm' | 'mm' | 'in' | 'pt' | 'pc'] 2082 // LENGTH: {num}['px' | 'cm' | 'mm' | 'in' | 'pt' | 'pc']
2080 // EMS: {num}'em' 2083 // EMS: {num}'em'
2081 // EXS: {num}'ex' 2084 // EXS: {num}'ex'
2082 // ANGLE: {num}['deg' | 'rad' | 'grad'] 2085 // ANGLE: {num}['deg' | 'rad' | 'grad']
2083 // TIME: {num}['ms' | 's'] 2086 // TIME: {num}['ms' | 's']
2084 // FREQ: {num}['hz' | 'khz'] 2087 // FREQ: {num}['hz' | 'khz']
2085 // function: IDENT '(' expr ')' 2088 // function: IDENT '(' expr ')'
2086 // 2089 //
2087 processTerm([bool ieFilter = false]) { 2090 processTerm([bool ieFilter = false]) {
2088 int start = _peekToken.start; 2091 int start = _peekToken.start;
terry 2013/11/20 14:07:25 var
kevmoo-old 2013/11/20 19:13:11 Done.
2089 Token t; // token for term's value 2092 Token t; // token for term's value
terry 2013/11/20 14:07:25 var
2090 var value; // value of term (numeric values) 2093 var value; // value of term (numeric values)
2091 2094
2092 var unary = ""; 2095 var unary = "";
2093 switch (_peek()) { 2096 switch (_peek()) {
2094 case TokenKind.HASH: 2097 case TokenKind.HASH:
2095 this._eat(TokenKind.HASH); 2098 this._eat(TokenKind.HASH);
2096 if (!_anyWhiteSpaceBeforePeekToken(TokenKind.HASH)) { 2099 if (!_anyWhiteSpaceBeforePeekToken(TokenKind.HASH)) {
2097 String hexText; 2100 String hexText;
2098 if (_peekKind(TokenKind.INTEGER)) { 2101 if (_peekKind(TokenKind.INTEGER)) {
2099 String hexText1 = _peekToken.text; 2102 String hexText1 = _peekToken.text;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2186 var propName = nameValue.name; 2189 var propName = nameValue.name;
2187 var errMsg = TokenKind.isPredefinedName(propName) ? 2190 var errMsg = TokenKind.isPredefinedName(propName) ?
2188 "Improper use of property value ${propName}" : 2191 "Improper use of property value ${propName}" :
2189 "Unknown property value ${propName}"; 2192 "Unknown property value ${propName}";
2190 _warning(errMsg, _makeSpan(start)); 2193 _warning(errMsg, _makeSpan(start));
2191 } 2194 }
2192 return new LiteralTerm(nameValue, nameValue.name, _makeSpan(start)); 2195 return new LiteralTerm(nameValue, nameValue.name, _makeSpan(start));
2193 } 2196 }
2194 2197
2195 // Yes, process the color as an RGB value. 2198 // Yes, process the color as an RGB value.
2196 String rgbColor = TokenKind.decimalToHex( 2199 String rgbColor = TokenKind.decimalToHex(
terry 2013/11/20 14:07:25 var
2197 TokenKind.colorValue(colorEntry), 6); 2200 TokenKind.colorValue(colorEntry), 6);
2198 return _parseHex(rgbColor, _makeSpan(start)); 2201 return _parseHex(rgbColor, _makeSpan(start));
2199 case TokenKind.UNICODE_RANGE: 2202 case TokenKind.UNICODE_RANGE:
2200 var first; 2203 var first;
2201 var second; 2204 var second;
2202 var firstNumber; 2205 var firstNumber;
2203 var secondNumber; 2206 var secondNumber;
2204 _eat(TokenKind.UNICODE_RANGE, unicodeRange: true); 2207 _eat(TokenKind.UNICODE_RANGE, unicodeRange: true);
2205 if (_maybeEat(TokenKind.HEX_INTEGER, unicodeRange: true)) { 2208 if (_maybeEat(TokenKind.HEX_INTEGER, unicodeRange: true)) {
2206 first = _previousToken.text; 2209 first = _previousToken.text;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2241 expr.expressions[0] = varUsage; 2244 expr.expressions[0] = varUsage;
2242 return expr.expressions; 2245 return expr.expressions;
2243 } 2246 }
2244 break; 2247 break;
2245 } 2248 }
2246 2249
2247 return processDimension(t, value, _makeSpan(start)); 2250 return processDimension(t, value, _makeSpan(start));
2248 } 2251 }
2249 2252
2250 /** Process all dimension units. */ 2253 /** Process all dimension units. */
2251 processDimension(Token t, var value, Span span) { 2254 LiteralTerm processDimension(Token t, var value, Span span) {
2252 var term; 2255 LiteralTerm term;
terry 2013/11/20 14:07:25 style is to use var.
2253 var unitType = this._peek(); 2256 var unitType = this._peek();
2254 2257
2255 switch (unitType) { 2258 switch (unitType) {
2256 case TokenKind.UNIT_EM: 2259 case TokenKind.UNIT_EM:
2257 term = new EmTerm(value, t.text, span); 2260 term = new EmTerm(value, t.text, span);
2258 _next(); // Skip the unit 2261 _next(); // Skip the unit
2259 break; 2262 break;
2260 case TokenKind.UNIT_EX: 2263 case TokenKind.UNIT_EX:
2261 term = new ExTerm(value, t.text, span); 2264 term = new ExTerm(value, t.text, span);
2262 _next(); // Skip the unit 2265 _next(); // Skip the unit
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2321 term = (value is Identifier) 2324 term = (value is Identifier)
2322 ? new LiteralTerm(value, value.name, span) 2325 ? new LiteralTerm(value, value.name, span)
2323 : new NumberTerm(value, t.text, span); 2326 : new NumberTerm(value, t.text, span);
2324 } 2327 }
2325 break; 2328 break;
2326 } 2329 }
2327 2330
2328 return term; 2331 return term;
2329 } 2332 }
2330 2333
2331 processQuotedString([bool urlString = false]) { 2334 String processQuotedString([bool urlString = false]) {
2332 int start = _peekToken.start; 2335 int start = _peekToken.start;
terry 2013/11/20 14:07:25 var
2333 2336
2334 // URI term sucks up everything inside of quotes(' or ") or between parens 2337 // URI term sucks up everything inside of quotes(' or ") or between parens
2335 int stopToken = urlString ? TokenKind.RPAREN : -1; 2338 int stopToken = urlString ? TokenKind.RPAREN : -1;
2336 switch (_peek()) { 2339 switch (_peek()) {
2337 case TokenKind.SINGLE_QUOTE: 2340 case TokenKind.SINGLE_QUOTE:
2338 stopToken = TokenKind.SINGLE_QUOTE; 2341 stopToken = TokenKind.SINGLE_QUOTE;
2339 start = _peekToken.start + 1; // Skip the quote might have whitespace. 2342 start = _peekToken.start + 1; // Skip the quote might have whitespace.
2340 _next(); // Skip the SINGLE_QUOTE. 2343 _next(); // Skip the SINGLE_QUOTE.
2341 break; 2344 break;
2342 case TokenKind.DOUBLE_QUOTE: 2345 case TokenKind.DOUBLE_QUOTE:
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2463 if (!_maybeEat(TokenKind.RPAREN)) { 2466 if (!_maybeEat(TokenKind.RPAREN)) {
2464 _error("problem parsing function expected ), ", _peekToken.span); 2467 _error("problem parsing function expected ), ", _peekToken.span);
2465 } 2468 }
2466 2469
2467 return new FunctionTerm(name, name, expr, _makeSpan(start)); 2470 return new FunctionTerm(name, name, expr, _makeSpan(start));
2468 } 2471 }
2469 2472
2470 return null; 2473 return null;
2471 } 2474 }
2472 2475
2473 identifier() { 2476 Identifier identifier() {
2474 var tok = _next(); 2477 var tok = _next();
2475 2478
2476 if (!TokenKind.isIdentifier(tok.kind) && 2479 if (!TokenKind.isIdentifier(tok.kind) &&
2477 !TokenKind.isKindIdentifier(tok.kind)) { 2480 !TokenKind.isKindIdentifier(tok.kind)) {
2478 if (isChecked) { 2481 if (isChecked) {
2479 _warning('expected identifier, but found $tok', tok.span); 2482 _warning('expected identifier, but found $tok', tok.span);
2480 } 2483 }
2481 return new Identifier("", _makeSpan(tok.start)); 2484 return new Identifier("", _makeSpan(tok.start));
2482 } 2485 }
2483 2486
2484 return new Identifier(tok.text, _makeSpan(tok.start)); 2487 return new Identifier(tok.text, _makeSpan(tok.start));
2485 } 2488 }
2486 2489
2487 // TODO(terry): Move this to base <= 36 and into shared code. 2490 // TODO(terry): Move this to base <= 36 and into shared code.
2488 static int _hexDigit(int c) { 2491 static int _hexDigit(int c) {
2489 if(c >= 48/*0*/ && c <= 57/*9*/) { 2492 if(c >= 48/*0*/ && c <= 57/*9*/) {
terry 2013/11/20 14:07:25 space between if and (
kevmoo-old 2013/11/20 19:13:11 Done.
2490 return c - 48; 2493 return c - 48;
2491 } else if (c >= 97/*a*/ && c <= 102/*f*/) { 2494 } else if (c >= 97/*a*/ && c <= 102/*f*/) {
2492 return c - 87; 2495 return c - 87;
2493 } else if (c >= 65/*A*/ && c <= 70/*F*/) { 2496 } else if (c >= 65/*A*/ && c <= 70/*F*/) {
2494 return c - 55; 2497 return c - 55;
2495 } else { 2498 } else {
2496 return -1; 2499 return -1;
2497 } 2500 }
2498 } 2501 }
2499 2502
(...skipping 28 matching lines...) Expand all
2528 } 2531 }
2529 } 2532 }
2530 2533
2531 class ExpressionsProcessor { 2534 class ExpressionsProcessor {
2532 final Expressions _exprs; 2535 final Expressions _exprs;
2533 int _index = 0; 2536 int _index = 0;
2534 2537
2535 ExpressionsProcessor(this._exprs); 2538 ExpressionsProcessor(this._exprs);
2536 2539
2537 // TODO(terry): Only handles ##px unit. 2540 // TODO(terry): Only handles ##px unit.
2538 processFontSize() { 2541 FontExpression processFontSize() {
2539 /* font-size[/line-height] 2542 /* font-size[/line-height]
2540 * 2543 *
2541 * Possible size values: 2544 * Possible size values:
2542 * xx-small 2545 * xx-small
2543 * small 2546 * small
2544 * medium [default] 2547 * medium [default]
2545 * large 2548 * large
2546 * x-large 2549 * x-large
2547 * xx-large 2550 * xx-large
2548 * smaller 2551 * smaller
2549 * larger 2552 * larger
2550 * ##length in px, pt, etc. 2553 * ##length in px, pt, etc.
2551 * ##%, percent of parent elem's font-size 2554 * ##%, percent of parent elem's font-size
2552 * inherit 2555 * inherit
2553 */ 2556 */
2554 LengthTerm size; 2557 LengthTerm size;
terry 2013/11/20 14:07:25 var
2555 LineHeight lineHt; 2558 LineHeight lineHt;
terry 2013/11/20 14:07:25 var
2556 bool nextIsLineHeight = false; 2559 bool nextIsLineHeight = false;
terry 2013/11/20 14:07:25 var
2557 for (; _index < _exprs.expressions.length; _index++) { 2560 for (; _index < _exprs.expressions.length; _index++) {
2558 var expr = _exprs.expressions[_index]; 2561 var expr = _exprs.expressions[_index];
2559 if (size == null && expr is LengthTerm) { 2562 if (size == null && expr is LengthTerm) {
2560 // font-size part. 2563 // font-size part.
2561 size = expr; 2564 size = expr;
2562 } else if (size != null) { 2565 } else if (size != null) {
2563 if (expr is OperatorSlash) { 2566 if (expr is OperatorSlash) {
2564 // LineHeight could follow? 2567 // LineHeight could follow?
2565 nextIsLineHeight = true; 2568 nextIsLineHeight = true;
2566 } else if (nextIsLineHeight && expr is LengthTerm) { 2569 } else if (nextIsLineHeight && expr is LengthTerm) {
2567 assert(expr.unit == TokenKind.UNIT_LENGTH_PX); 2570 assert(expr.unit == TokenKind.UNIT_LENGTH_PX);
2568 lineHt = new LineHeight(expr.value, inPixels: true); 2571 lineHt = new LineHeight(expr.value, inPixels: true);
2569 nextIsLineHeight = false; 2572 nextIsLineHeight = false;
2570 _index++; 2573 _index++;
2571 break; 2574 break;
2572 } else { 2575 } else {
2573 break; 2576 break;
2574 } 2577 }
2575 } else { 2578 } else {
2576 break; 2579 break;
2577 } 2580 }
2578 } 2581 }
2579 2582
2580 return new FontExpression(_exprs.span, size: size, lineHeight: lineHt); 2583 return new FontExpression(_exprs.span, size: size, lineHeight: lineHt);
2581 } 2584 }
2582 2585
2583 processFontFamily() { 2586 FontExpression processFontFamily() {
2584 final List<String> family = <String>[]; 2587 final List<String> family = <String>[];
terry 2013/11/20 14:07:25 var family = [];
2585 2588
2586 /* Possible family values: 2589 /* Possible family values:
2587 * font-family: arial, Times new roman ,Lucida Sans Unicode,Courier; 2590 * font-family: arial, Times new roman ,Lucida Sans Unicode,Courier;
2588 * font-family: "Times New Roman", arial, Lucida Sans Unicode, Courier; 2591 * font-family: "Times New Roman", arial, Lucida Sans Unicode, Courier;
2589 */ 2592 */
2590 bool moreFamilies = false; 2593 bool moreFamilies = false;
2591 2594
2592 for (; _index < _exprs.expressions.length; _index++) { 2595 for (; _index < _exprs.expressions.length; _index++) {
2593 Expression expr = _exprs.expressions[_index]; 2596 Expression expr = _exprs.expressions[_index];
2594 if (expr is LiteralTerm) { 2597 if (expr is LiteralTerm) {
2595 if (family.length == 0 || moreFamilies) { 2598 if (family.length == 0 || moreFamilies) {
2596 // It's font-family now. 2599 // It's font-family now.
2597 family.add(expr.toString()); 2600 family.add(expr.toString());
2598 moreFamilies = false; 2601 moreFamilies = false;
2599 } else if (isChecked) { 2602 } else if (isChecked) {
2600 messages.warning('Only font-family can be a list', _exprs.span); 2603 messages.warning('Only font-family can be a list', _exprs.span);
2601 } 2604 }
2602 } else if (expr is OperatorComma && family.length > 0) { 2605 } else if (expr is OperatorComma && family.length > 0) {
2603 moreFamilies = true; 2606 moreFamilies = true;
2604 } else { 2607 } else {
2605 break; 2608 break;
2606 } 2609 }
2607 } 2610 }
2608 2611
2609 return new FontExpression(_exprs.span, family: family); 2612 return new FontExpression(_exprs.span, family: family);
2610 } 2613 }
2611 2614
2612 processFont() { 2615 FontExpression processFont() {
2613 var family; 2616 var family;
2614 2617
2615 // Process all parts of the font expression. 2618 // Process all parts of the font expression.
2616 FontExpression fontSize; 2619 FontExpression fontSize;
terry 2013/11/20 14:07:25 var
2617 FontExpression fontFamily; 2620 FontExpression fontFamily;
terry 2013/11/20 14:07:25 var
2618 for (; _index < _exprs.expressions.length; _index++) { 2621 for (; _index < _exprs.expressions.length; _index++) {
2619 var expr = _exprs.expressions[_index]; 2622 var expr = _exprs.expressions[_index];
2620 // Order is font-size font-family 2623 // Order is font-size font-family
2621 if (fontSize == null) { 2624 if (fontSize == null) {
2622 fontSize = processFontSize(); 2625 fontSize = processFontSize();
2623 } 2626 }
2624 if (fontFamily == null) { 2627 if (fontFamily == null) {
2625 fontFamily = processFontFamily(); 2628 fontFamily = processFontFamily();
2626 } 2629 }
2627 //TODO(terry): Handle font-weight, font-style, and font-variant. See 2630 //TODO(terry): Handle font-weight, font-style, and font-variant. See
2628 // https://github.com/dart-lang/csslib/issues/3 2631 // https://github.com/dart-lang/csslib/issues/3
2629 // https://github.com/dart-lang/csslib/issues/4 2632 // https://github.com/dart-lang/csslib/issues/4
2630 // https://github.com/dart-lang/csslib/issues/5 2633 // https://github.com/dart-lang/csslib/issues/5
2631 } 2634 }
2632 2635
2633 return new FontExpression(_exprs.span, 2636 return new FontExpression(_exprs.span,
2634 size: fontSize.font.size, 2637 size: fontSize.font.size,
2635 lineHeight: fontSize.font.lineHeight, 2638 lineHeight: fontSize.font.lineHeight,
2636 family: fontFamily.font.family); 2639 family: fontFamily.font.family);
2637 } 2640 }
2638 } 2641 }
2639 2642
2640 /** 2643 /**
2641 * Escapes [text] for use in a CSS string. 2644 * Escapes [text] for use in a CSS string.
2642 * [single] specifies single quote `'` vs double quote `"`. 2645 * [single] specifies single quote `'` vs double quote `"`.
2643 */ 2646 */
2644 String _escapeString(String text, {bool single: false}) { 2647 String _escapeString(String text, {bool single: false}) {
2645 StringBuffer result = null; 2648 StringBuffer result = null;
terry 2013/11/20 14:07:25 var
2646 2649
2647 for (int i = 0; i < text.length; i++) { 2650 for (int i = 0; i < text.length; i++) {
2648 int code = text.codeUnitAt(i); 2651 int code = text.codeUnitAt(i);
terry 2013/11/20 14:07:25 var
2649 var replace = null; 2652 var replace = null;
2650 switch (code) { 2653 switch (code) {
2651 case 34/*'"'*/: if (!single) replace = r'\"'; break; 2654 case 34/*'"'*/: if (!single) replace = r'\"'; break;
2652 case 39/*"'"*/: if (single) replace = r"\'"; break; 2655 case 39/*"'"*/: if (single) replace = r"\'"; break;
2653 } 2656 }
2654 2657
2655 if (replace != null && result == null) { 2658 if (replace != null && result == null) {
2656 result = new StringBuffer(text.substring(0, i)); 2659 result = new StringBuffer(text.substring(0, i));
2657 } 2660 }
2658 2661
2659 if (result != null) result.write(replace != null ? replace : text[i]); 2662 if (result != null) result.write(replace != null ? replace : text[i]);
2660 } 2663 }
2661 2664
2662 return result == null ? text : result.toString(); 2665 return result == null ? text : result.toString();
2663 } 2666 }
OLDNEW
« no previous file with comments | « no previous file | pkg/csslib/lib/src/analyzer.dart » ('j') | pkg/csslib/lib/src/css_printer.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698