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

Side by Side Diff: lib/src/html_css_fixup.dart

Issue 19497002: Reducing the amount of code we generate in the compiler: We still continue (Closed) Base URL: git@github.com:dart-lang/web-ui.git@master
Patch Set: Created 7 years, 5 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
OLDNEW
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:csslib/parser.dart' as css; 9 import 'package:csslib/parser.dart' as css;
10 import 'package:csslib/visitor.dart'; 10 import 'package:csslib/visitor.dart';
11 import 'package:html5lib/dom.dart'; 11 import 'package:html5lib/dom.dart';
12 import 'package:html5lib/dom_parsing.dart'; 12 import 'package:html5lib/dom_parsing.dart';
13 13
14 import 'compiler.dart'; 14 import 'compiler.dart';
15 import 'emitters.dart'; 15 import 'emitters.dart';
16 import 'info.dart'; 16 import 'info.dart';
17 import 'messages.dart'; 17 import 'messages.dart';
18 import 'options.dart'; 18 import 'options.dart';
19 import 'paths.dart'; 19 import 'paths.dart';
20 import 'utils.dart'; 20 import 'utils.dart';
21 21
22 /** 22 /** Enum for type of polyfills supported. */
23 * Helper function returns [true] if CSS polyfill is on and component has a 23 class CssPolyfillKind {
24 * scoped style tag. 24 final index;
25 */ 25 const CssPolyfillKind(this.index);
26 bool useCssPolyfill(CompilerOptions opts, ComponentInfo component) => 26
27 opts.processCss && component.scoped; 27 /** Emit CSS selectors as seen (no polyfill). */
28 static const NO_POLYFILL = const CssPolyfillKind(0);
29
30 /** Emit CSS selectors scoped to the "is" attribute of the component. */
31 static const SCOPED_POLYFILL = const CssPolyfillKind(1);
32
33 /** Emit CSS selectors mangled. */
34 static const MANGLED_POLYFILL = const CssPolyfillKind(2);
35
36 static CssPolyfillKind of(CompilerOptions options, ComponentInfo component) {
37 if (!options.processCss || !component.scoped) return NO_POLYFILL;
38 if (options.mangleCss) return MANGLED_POLYFILL;
39 if (!component.hasAuthorStyles && !hasCssReset) return MANGLED_POLYFILL;
40 return SCOPED_POLYFILL;
41 }
42 }
43
28 44
29 /** 45 /**
30 * If processCss is enabled, prefix any component's HTML attributes for id or 46 * If processCss is enabled, prefix any component's HTML attributes for id or
31 * class to reference the mangled CSS class name or id. 47 * class to reference the mangled CSS class name or id.
32 */ 48 */
33 void fixupHtmlCss(FileInfo fileInfo, CompilerOptions options, 49 void fixupHtmlCss(FileInfo fileInfo, CompilerOptions options) {
34 CssPolyfillKind polyfillKind(ComponentInfo component)) {
35 // Walk the HTML tree looking for class names or id that are in our parsed 50 // Walk the HTML tree looking for class names or id that are in our parsed
36 // stylesheet selectors and making those CSS classes and ids unique to that 51 // stylesheet selectors and making those CSS classes and ids unique to that
37 // component. 52 // component.
38 if (options.verbose) { 53 if (options.verbose) {
39 print(" CSS fixup ${path.basename(fileInfo.inputUrl.resolvedPath)}"); 54 print(" CSS fixup ${path.basename(fileInfo.inputUrl.resolvedPath)}");
40 } 55 }
41 for (var component in fileInfo.declaredComponents) { 56 for (var component in fileInfo.declaredComponents) {
42 // Mangle class names and element ids in the HTML to match the stylesheet. 57 // Mangle class names and element ids in the HTML to match the stylesheet.
43 // TODO(terry): Allow more than one style sheet per component. 58 // TODO(terry): Allow more than one style sheet per component.
44 if (component.styleSheets.length == 1) { 59 if (component.styleSheets.length == 1) {
45 // For components only 1 stylesheet allowed. 60 // For components only 1 stylesheet allowed.
46 var styleSheet = component.styleSheets[0]; 61 var styleSheet = component.styleSheets[0];
47 var prefix = polyfillKind(component) == CssPolyfillKind.MANGLED_POLYFILL ? 62 var prefix = CssPolyfillKind.of(options, component) ==
48 component.tagName : null; 63 CssPolyfillKind.MANGLED_POLYFILL ? component.tagName : null;
49 64
50 // List of referenced #id and .class in CSS. 65 // List of referenced #id and .class in CSS.
51 var knownCss = new IdClassVisitor()..visitTree(styleSheet); 66 var knownCss = new IdClassVisitor()..visitTree(styleSheet);
52 // Prefix all id and class refs in CSS selectors and HTML attributes. 67 // Prefix all id and class refs in CSS selectors and HTML attributes.
53 new _ScopedStyleRenamer(knownCss, prefix, options.debugCss) 68 new _ScopedStyleRenamer(knownCss, prefix, options.debugCss)
54 .visit(component.elementNode); 69 .visit(component.element);
55 } 70 }
56 } 71 }
57 } 72 }
58 73
59 /** Build list of every CSS class name and id selector in a stylesheet. */ 74 /** Build list of every CSS class name and id selector in a stylesheet. */
60 class IdClassVisitor extends Visitor { 75 class IdClassVisitor extends Visitor {
61 final Set<String> classes = new Set(); 76 final Set<String> classes = new Set();
62 final Set<String> ids = new Set(); 77 final Set<String> ids = new Set();
63 78
64 void visitClassSelector(ClassSelector node) { 79 void visitClassSelector(ClassSelector node) {
65 classes.add(node.name); 80 classes.add(node.name);
66 } 81 }
67 82
68 void visitIdSelector(IdSelector node) { 83 void visitIdSelector(IdSelector node) {
69 ids.add(node.name); 84 ids.add(node.name);
70 } 85 }
71 } 86 }
72 87
73 /** Build the Dart map of managled class/id names and component tag name. */ 88 /** Build the Dart map of managled class/id names and component tag name. */
74 Map _createCssSimpleSelectors(IdClassVisitor visitedCss, ComponentInfo info, 89 Map _createCssSimpleSelectors(IdClassVisitor visitedCss, ComponentInfo info,
75 bool mangleNames) { 90 CssPolyfillKind kind) {
91 bool mangleNames = kind == CssPolyfillKind.MANGLED_POLYFILL;
76 Map selectors = {}; 92 Map selectors = {};
77 if (visitedCss != null) { 93 if (visitedCss != null) {
78 for (var cssClass in visitedCss.classes) { 94 for (var cssClass in visitedCss.classes) {
79 selectors['.$cssClass'] = 95 selectors['.$cssClass'] =
80 mangleNames ? '${info.tagName}_$cssClass' : cssClass; 96 mangleNames ? '${info.tagName}_$cssClass' : cssClass;
81 } 97 }
82 for (var id in visitedCss.ids) { 98 for (var id in visitedCss.ids) {
83 selectors['#$id'] = mangleNames ? '${info.tagName}_$id' : id; 99 selectors['#$id'] = mangleNames ? '${info.tagName}_$id' : id;
84 } 100 }
85 } 101 }
86 102
87 // Add tag name selector x-comp == [is="x-comp"]. 103 // Add tag name selector x-comp == [is="x-comp"].
88 var componentName = info.tagName; 104 var componentName = info.tagName;
89 selectors['$componentName'] = '[is="$componentName"]'; 105 selectors['$componentName'] = '[is="$componentName"]';
90 106
91 return selectors; 107 return selectors;
92 } 108 }
93 109
94 /** 110 /**
95 * Return a map of simple CSS selectors (class and id selectors) as a Dart map 111 * Return a map of simple CSS selectors (class and id selectors) as a Dart map
96 * definition. 112 * definition.
97 */ 113 */
98 String createCssSelectorsExpression(ComponentInfo info, bool mangled) { 114 String createCssSelectorsExpression(ComponentInfo info, CssPolyfillKind kind) {
99 var cssVisited = new IdClassVisitor(); 115 var cssVisited = new IdClassVisitor();
100 116
101 // For components only 1 stylesheet allowed. 117 // For components only 1 stylesheet allowed.
102 if (!info.styleSheets.isEmpty && info.styleSheets.length == 1) { 118 if (!info.styleSheets.isEmpty && info.styleSheets.length == 1) {
103 var styleSheet = info.styleSheets[0]; 119 var styleSheet = info.styleSheets[0];
104 cssVisited..visitTree(styleSheet); 120 cssVisited..visitTree(styleSheet);
105 } 121 }
106 122
107 return json.stringify(_createCssSimpleSelectors(cssVisited, info, mangled)); 123 return json.stringify(_createCssSimpleSelectors(cssVisited, info, kind));
108 } 124 }
109 125
110 // TODO(terry): Need to handle other selectors than IDs/classes like tag name 126 // TODO(terry): Need to handle other selectors than IDs/classes like tag name
111 // e.g., DIV { color: red; } 127 // e.g., DIV { color: red; }
112 // TODO(terry): Would be nice if we didn't need to mangle names; requires users 128 // TODO(terry): Would be nice if we didn't need to mangle names; requires users
113 // to be careful in their code and makes it more than a "polyfill". 129 // to be careful in their code and makes it more than a "polyfill".
114 // Maybe mechanism that generates CSS class name for scoping. This 130 // Maybe mechanism that generates CSS class name for scoping. This
115 // would solve tag name selectors (see above TODO). 131 // would solve tag name selectors (see above TODO).
116 /** 132 /**
117 * Fix a component's HTML to implement scoped stylesheets. 133 * Fix a component's HTML to implement scoped stylesheets.
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 /** List of @imports found. */ 554 /** List of @imports found. */
539 List<UrlInfo> imports = []; 555 List<UrlInfo> imports = [];
540 556
541 CssStyleTag(this._packageRoot, this._info, this._inputUrl, this._messages, 557 CssStyleTag(this._packageRoot, this._info, this._inputUrl, this._messages,
542 this._options); 558 this._options);
543 559
544 void visitElement(Element node) { 560 void visitElement(Element node) {
545 // Don't process any style tags inside of element if we're processing a 561 // Don't process any style tags inside of element if we're processing a
546 // FileInfo. The style tags inside of a component defintion will be 562 // FileInfo. The style tags inside of a component defintion will be
547 // processed when _info is a ComponentInfo. 563 // processed when _info is a ComponentInfo.
548 if (node.tagName == 'element' && _info is FileInfo) return; 564 if (node.tagName == 'polymer-element' && _info is FileInfo) return;
549 if (node.tagName == 'style') { 565 if (node.tagName == 'style') {
550 // Parse the contents of the scoped style tag. 566 // Parse the contents of the scoped style tag.
551 var styleSheet = parseCss(node.nodes.single.value, _messages, _options); 567 var styleSheet = parseCss(node.nodes.single.value, _messages, _options);
552 if (styleSheet != null) { 568 if (styleSheet != null) {
553 _info.styleSheets.add(styleSheet); 569 _info.styleSheets.add(styleSheet);
554 570
555 // TODO(terry): Check on scoped attribute there's a rumor that styles 571 // TODO(terry): Check on scoped attribute there's a rumor that styles
556 // might always be scoped in a component. 572 // might always be scoped in a component.
557 // TODO(terry): May need to handle multiple style tags some with scoped 573 // TODO(terry): May need to handle multiple style tags some with scoped
558 // and some without for now first style tag determines how 574 // and some without for now first style tag determines how
559 // CSS is emitted. 575 // CSS is emitted.
560 if (node.attributes.containsKey('scoped') && _info is ComponentInfo) { 576 if (node.attributes.containsKey('scoped') && _info is ComponentInfo) {
561 (_info as ComponentInfo).scoped = true; 577 (_info as ComponentInfo).scoped = true;
562 } 578 }
563 579
564 // Find all imports return list of @imports in this style tag. 580 // Find all imports return list of @imports in this style tag.
565 var urlInfos = findImportsInStyleSheet(styleSheet, _packageRoot, 581 var urlInfos = findImportsInStyleSheet(styleSheet, _packageRoot,
566 _inputUrl, _messages); 582 _inputUrl, _messages);
567 imports.addAll(urlInfos); 583 imports.addAll(urlInfos);
568 } 584 }
569 } 585 }
570 super.visitElement(node); 586 super.visitElement(node);
571 } 587 }
572 } 588 }
OLDNEW
« lib/polymer_element.dart ('K') | « lib/src/emitters.dart ('k') | lib/src/info.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698