OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 html_css_fixup; | 5 library html_css_fixup; |
6 | 6 |
7 import 'dart:json' as json; | 7 import 'dart:json' as json; |
8 | 8 |
9 import 'package:html5lib/dom.dart'; | 9 import 'package:html5lib/dom.dart'; |
10 import 'package:html5lib/dom_parsing.dart'; | 10 import 'package:html5lib/dom_parsing.dart'; |
11 import 'package:csslib/visitor.dart'; | 11 import 'package:csslib/visitor.dart'; |
12 | 12 |
| 13 import 'file_system/path.dart'; |
13 import 'info.dart'; | 14 import 'info.dart'; |
14 import 'messages.dart'; | 15 import 'messages.dart'; |
15 import 'options.dart'; | 16 import 'options.dart'; |
16 | 17 |
17 /** | 18 /** |
18 * If processCss is enabled, prefix any component's HTML attributes for id or | 19 * If processCss is enabled, prefix any component's HTML attributes for id or |
19 * class to reference the mangled CSS class name or id. | 20 * class to reference the mangled CSS class name or id. |
20 * | 21 * |
21 * Adds prefix error/warning messages to [messages], if [messages] is | 22 * Adds prefix error/warning messages to [messages], if [messages] is |
22 * supplied. | 23 * supplied. |
23 */ | 24 */ |
24 void fixupHtmlCss(FileInfo fileInfo, CompilerOptions opts) { | 25 void fixupHtmlCss(FileInfo fileInfo, CompilerOptions opts) { |
25 // Walk the HTML tree looking for class names or id that are in our parsed | 26 // Walk the HTML tree looking for class names or id that are in our parsed |
26 // stylesheet selectors and making those CSS classes and ids unique to that | 27 // stylesheet selectors and making those CSS classes and ids unique to that |
27 // component. | 28 // component. |
28 if (opts.verbose) print(" CSS fixup ${fileInfo.path.filename}"); | 29 if (opts.verbose) print(" CSS fixup ${fileInfo.path.filename}"); |
29 for (var component in fileInfo.declaredComponents) { | 30 for (var component in fileInfo.declaredComponents) { |
30 if (component.styleSheet != null) { | 31 // TODO(terry): Consider allowing more than one style sheet per component. |
| 32 // For components only 1 stylesheet allowed. |
| 33 if (!component.styleSheets.isEmpty && component.styleSheets.length == 1) { |
| 34 var styleSheet = component.styleSheets[0]; |
31 // If polyfill is on prefix component name to all CSS classes and ids | 35 // If polyfill is on prefix component name to all CSS classes and ids |
32 // referenced in the scoped style. | 36 // referenced in the scoped style. |
33 var prefix = opts.processCss ? component.tagName : null; | 37 var prefix = opts.processCss ? component.tagName : null; |
34 // List of referenced #id and .class in CSS. | 38 // List of referenced #id and .class in CSS. |
35 var knownCss = new IdClassVisitor()..visitTree(component.styleSheet); | 39 var knownCss = new IdClassVisitor()..visitTree(styleSheet); |
36 // Prefix all id and class refs in CSS selectors and HTML attributes. | 40 // Prefix all id and class refs in CSS selectors and HTML attributes. |
37 new _ScopedStyleRenamer(knownCss, prefix, opts.debugCss).visit(component); | 41 new _ScopedStyleRenamer(knownCss, prefix, opts.debugCss).visit(component); |
38 } | 42 } |
39 } | 43 } |
40 } | 44 } |
41 | 45 |
42 /** Build list of every CSS class name and id selector in a stylesheet. */ | 46 /** Build list of every CSS class name and id selector in a stylesheet. */ |
43 class IdClassVisitor extends Visitor { | 47 class IdClassVisitor extends Visitor { |
44 final Set<String> classes = new Set(); | 48 final Set<String> classes = new Set(); |
45 final Set<String> ids = new Set(); | 49 final Set<String> ids = new Set(); |
(...skipping 22 matching lines...) Expand all Loading... |
68 } | 72 } |
69 return selectors; | 73 return selectors; |
70 } | 74 } |
71 | 75 |
72 /** | 76 /** |
73 * Return a map of simple CSS selectors (class and id selectors) as a Dart map | 77 * Return a map of simple CSS selectors (class and id selectors) as a Dart map |
74 * definition. | 78 * definition. |
75 */ | 79 */ |
76 String createCssSelectorsDefinition(ComponentInfo info, bool cssPolyfill) { | 80 String createCssSelectorsDefinition(ComponentInfo info, bool cssPolyfill) { |
77 var cssVisited = new IdClassVisitor(); | 81 var cssVisited = new IdClassVisitor(); |
78 if (info.styleSheet != null) cssVisited..visitTree(info.styleSheet); | 82 |
| 83 // For components only 1 stylesheet allowed. |
| 84 if (!info.styleSheets.isEmpty && info.styleSheets.length == 1) { |
| 85 var styleSheet = info.styleSheets[0]; |
| 86 cssVisited..visitTree(styleSheet); |
| 87 } |
| 88 |
79 var css = json.stringify(createCssSimpleSelectors(cssVisited, info, | 89 var css = json.stringify(createCssSimpleSelectors(cssVisited, info, |
80 scopedStyles: cssPolyfill)); | 90 scopedStyles: cssPolyfill)); |
81 | |
82 return 'static Map<String, String> _css = $css;'; | 91 return 'static Map<String, String> _css = $css;'; |
83 } | 92 } |
84 | 93 |
85 // TODO(terry): Do we need to handle other selectors than IDs/classes? | 94 // TODO(terry): Do we need to handle other selectors than IDs/classes? |
86 // TODO(terry): Would be nice if we didn't need to mangle names; requires users | 95 // TODO(terry): Would be nice if we didn't need to mangle names; requires users |
87 // to be careful in their code and makes it more than a "polyfill". | 96 // to be careful in their code and makes it more than a "polyfill". |
88 // Maybe mechanism that generates CSS class name for scoping. | 97 // Maybe mechanism that generates CSS class name for scoping. |
89 /** | 98 /** |
90 * Fix a component's HTML to implement scoped stylesheets. | 99 * Fix a component's HTML to implement scoped stylesheets. |
91 * | 100 * |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 if (id != null && ids.contains(id)) { | 168 if (id != null && ids.contains(id)) { |
160 var mangledName = "${prefix}_$id"; | 169 var mangledName = "${prefix}_$id"; |
161 if (_debugCss) { | 170 if (_debugCss) { |
162 print(" id = ${node.attributes['id'].toString()} => $mangledName"); | 171 print(" id = ${node.attributes['id'].toString()} => $mangledName"); |
163 } | 172 } |
164 node.attributes['id'] = mangledName; | 173 node.attributes['id'] = mangledName; |
165 } | 174 } |
166 } | 175 } |
167 } | 176 } |
168 } | 177 } |
| 178 |
| 179 /** Compute each CSS URI resource relative from the generated CSS file. */ |
| 180 class UriVisitor extends Visitor { |
| 181 final Path _relativePath; |
| 182 |
| 183 UriVisitor(PathInfo pathInfo, Path mainFile, Path cssFile, bool rewriteUrl) |
| 184 : _relativePath = cssFile.relativeTo( |
| 185 rewriteUrl ? pathInfo.outputDirPath(mainFile) : mainFile.directoryPath |
| 186 ).directoryPath; |
| 187 |
| 188 |
| 189 void visitUriTerm(UriTerm node) { |
| 190 // TODO(terry): Needs to use pathos. |
| 191 node.text = _relativePath.join(new Path(node.text)).toString(); |
| 192 } |
| 193 } |
OLD | NEW |