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

Side by Side Diff: pkg/csslib/lib/src/polyfill.dart

Issue 23868008: Added polyfill for var (moved from web_ui) (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: merged Created 7 years, 3 months 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 | « pkg/csslib/lib/parser.dart ('k') | pkg/csslib/test/testing.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of csslib.parser;
6
7 /**
8 * CSS polyfill emits CSS to be understood by older parsers that which do not
9 * understand (var, calc, etc.).
10 */
11 class PolyFill {
12 final Messages _messages;
13 final bool _warningsAsErrors;
14
15 Set<StyleSheet> allStyleSheets = new Set<StyleSheet>();
16
17 /**
18 * [_pseudoElements] list of known pseudo attributes found in HTML, any
19 * CSS pseudo-elements 'name::custom-element' is mapped to the manged name
20 * associated with the pseudo-element key.
21 */
22 PolyFill(this._messages, this._warningsAsErrors);
23
24 /**
25 * Run the analyzer on every file that is a style sheet or any component that
26 * has a style tag.
27 */
28 void process(StyleSheet stylesheet) {
29 // TODO(terry): Process all imported stylesheets.
30
31 var styleSheets = processVars([stylesheet]);
32 allStyleSheets.addAll(styleSheets);
33
34 normalize();
35 }
36
37 void normalize() {
38 // Remove all var definitions for all style sheets analyzed.
39 for (var tree in allStyleSheets)
40 new _RemoveVarDefinitions().visitTree(tree);
41 }
42
43 List<StyleSheet> processVars(List<StyleSheet> styleSheets) {
44 // TODO(terry): Process all dependencies.
45 // Build list of all var definitions.
46 Map varDefs = new Map();
47 for (var tree in styleSheets) {
48 var allDefs = (new _VarDefinitions()..visitTree(tree)).found;
49 allDefs.forEach((key, value) {
50 varDefs[key] = value;
51 });
52 }
53
54 // Resolve all definitions to a non-VarUsage (terminal expression).
55 varDefs.forEach((key, value) {
56 for (var expr in (value.expression as Expressions).expressions) {
57 var def = _findTerminalVarDefinition(varDefs, value);
58 varDefs[key] = def;
59 }
60 });
61
62 // Resolve all var usages.
63 for (var tree in styleSheets) {
64 new _ResolveVarUsages(varDefs).visitTree(tree);
65 }
66
67 return styleSheets;
68 }
69 }
70
71 /**
72 * Find var- definitions in a style sheet.
73 * [found] list of known definitions.
74 */
75 class _VarDefinitions extends Visitor {
76 final Map<String, VarDefinition> found = new Map();
77
78 void visitTree(StyleSheet tree) {
79 visitStyleSheet(tree);
80 }
81
82 visitVarDefinition(VarDefinition node) {
83 // Replace with latest variable definition.
84 found[node.definedName] = node;
85 super.visitVarDefinition(node);
86 }
87
88 void visitVarDefinitionDirective(VarDefinitionDirective node) {
89 visitVarDefinition(node.def);
90 }
91 }
92
93 /**
94 * Resolve any CSS expression which contains a var() usage to the ultimate real
95 * CSS expression value e.g.,
96 *
97 * var-one: var(two);
98 * var-two: #ff00ff;
99 *
100 * .test {
101 * color: var(one);
102 * }
103 *
104 * then .test's color would be #ff00ff
105 */
106 class _ResolveVarUsages extends Visitor {
107 final Map<String, VarDefinition> varDefs;
108 bool inVarDefinition = false;
109 bool inUsage = false;
110 Expressions currentExpressions;
111
112 _ResolveVarUsages(this.varDefs);
113
114 void visitTree(StyleSheet tree) {
115 visitStyleSheet(tree);
116 }
117
118 void visitVarDefinition(VarDefinition varDef) {
119 inVarDefinition = true;
120 super.visitVarDefinition(varDef);
121 inVarDefinition = false;
122 }
123
124 void visitExpressions(Expressions node) {
125 currentExpressions = node;
126 super.visitExpressions(node);
127 currentExpressions = null;
128 }
129
130 void visitVarUsage(VarUsage node) {
131 // Don't process other var() inside of a varUsage. That implies that the
132 // default is a var() too. Also, don't process any var() inside of a
133 // varDefinition (they're just place holders until we've resolved all real
134 // usages.
135 if (!inUsage && !inVarDefinition && currentExpressions != null) {
136 var expressions = currentExpressions.expressions;
137 var index = expressions.indexOf(node);
138 assert(index >= 0);
139 var def = varDefs[node.name];
140 if (def != null) {
141 // Found a VarDefinition use it.
142 _resolveVarUsage(currentExpressions.expressions, index, def);
143 } else if (node.defaultValues.any((e) => e is VarUsage)) {
144 // Don't have a VarDefinition need to use default values resolve all
145 // default values.
146 var terminalDefaults = [];
147 for (var defaultValue in node.defaultValues) {
148 terminalDefaults.addAll(resolveUsageTerminal(defaultValue));
149 }
150 expressions.replaceRange(index, index + 1, terminalDefaults);
151 } else {
152 // No VarDefinition but default value is a terminal expression; use it.
153 expressions.replaceRange(index, index + 1, node.defaultValues);
154 }
155 }
156
157 inUsage = true;
158 super.visitVarUsage(node);
159 inUsage = false;
160 }
161
162 List<Expression> resolveUsageTerminal(VarUsage usage) {
163 var result = [];
164
165 var varDef = varDefs[usage.name];
166 var expressions;
167 if (varDef == null) {
168 // VarDefinition not found try the defaultValues.
169 expressions = usage.defaultValues;
170 } else {
171 // Use the VarDefinition found.
172 expressions = (varDef.expression as Expressions).expressions;
173 }
174
175 for (var expr in expressions) {
176 if (expr is VarUsage) {
177 // Get terminal value.
178 result.addAll(resolveUsageTerminal(expr));
179 }
180 }
181
182 // We're at a terminal just return the VarDefinition expression.
183 if (result.isEmpty && varDef != null) {
184 result = (varDef.expression as Expressions).expressions;
185 }
186
187 return result;
188 }
189
190 _resolveVarUsage(List<Expressions> expressions, int index,
191 VarDefinition def) {
192 var defExpressions = (def.expression as Expressions).expressions;
193 expressions.replaceRange(index, index + 1, defExpressions);
194 }
195 }
196
197 /** Remove all var definitions. */
198 class _RemoveVarDefinitions extends Visitor {
199 void visitTree(StyleSheet tree) {
200 visitStyleSheet(tree);
201 }
202
203 void visitStyleSheet(StyleSheet ss) {
204 ss.topLevels.removeWhere((e) => e is VarDefinitionDirective);
205 super.visitStyleSheet(ss);
206 }
207
208 void visitDeclarationGroup(DeclarationGroup node) {
209 node.declarations.removeWhere((e) => e is VarDefinition);
210 super.visitDeclarationGroup(node);
211 }
212 }
213
214 /** Find terminal definition (non VarUsage implies real CSS value). */
215 VarDefinition _findTerminalVarDefinition(Map<String, VarDefinition> varDefs,
216 VarDefinition varDef) {
217 var expressions = varDef.expression as Expressions;
218 for (var expr in expressions.expressions) {
219 if (expr is VarUsage) {
220 var usageName = (expr as VarUsage).name;
221 var foundDef = varDefs[usageName];
222
223 // If foundDef is unknown check if defaultValues; if it exist then resolve
224 // to terminal value.
225 if (foundDef == null) {
226 // We're either a VarUsage or terminal definition if in varDefs;
227 // either way replace VarUsage with it's default value because the
228 // VarDefinition isn't found.
229 var defaultValues = (expr as VarUsage).defaultValues;
230 var replaceExprs = expressions.expressions;
231 assert(replaceExprs.length == 1);
232 replaceExprs.replaceRange(0, 1, defaultValues);
233 return varDef;
234 }
235 if (foundDef is VarDefinition) {
236 return _findTerminalVarDefinition(varDefs, foundDef);
237 }
238 } else {
239 // Return real CSS property.
240 return varDef;
241 }
242 }
243
244 // Didn't point to a var definition that existed.
245 return varDef;
246 }
OLDNEW
« no previous file with comments | « pkg/csslib/lib/parser.dart ('k') | pkg/csslib/test/testing.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698