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

Side by Side Diff: lib/build/import_inliner.dart

Issue 1014423002: add option to pass in bindings delimiters (Closed) Base URL: git@github.com:dart-lang/web-components.git@master
Patch Set: format Created 5 years, 9 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
« no previous file with comments | « CHANGELOG.md ('k') | pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 library web_components.build.import_inliner; 4 library web_components.build.import_inliner;
5 5
6 import 'dart:async'; 6 import 'dart:async';
7 import 'dart:collection' show LinkedHashMap; 7 import 'dart:collection' show LinkedHashMap;
8 import 'package:barback/barback.dart'; 8 import 'package:barback/barback.dart';
9 import 'package:code_transformers/assets.dart'; 9 import 'package:code_transformers/assets.dart';
10 import 'package:code_transformers/messages/build_logger.dart'; 10 import 'package:code_transformers/messages/build_logger.dart';
11 import 'package:html5lib/dom.dart'; 11 import 'package:html5lib/dom.dart';
12 import 'package:html5lib/dom_parsing.dart' show TreeVisitor; 12 import 'package:html5lib/dom_parsing.dart' show TreeVisitor;
13 import 'package:path/path.dart' as path; 13 import 'package:path/path.dart' as path;
14 import 'package:source_span/source_span.dart'; 14 import 'package:source_span/source_span.dart';
15 import 'common.dart'; 15 import 'common.dart';
16 import 'import_crawler.dart'; 16 import 'import_crawler.dart';
17 import 'messages.dart'; 17 import 'messages.dart';
18 18
19 /// Transformer which inlines all html imports found from the entry points. This 19 /// Transformer which inlines all html imports found from the entry points. This
20 /// deletes all dart scripts found during the inlining, so the 20 /// deletes all dart scripts found during the inlining, so the
21 /// [ScriptCompactorTransformer] should be ran first if there are any dart files 21 /// [ScriptCompactorTransformer] should be ran first if there are any dart files
22 /// in html imports. 22 /// in html imports.
23 class ImportInlinerTransformer extends Transformer { 23 class ImportInlinerTransformer extends Transformer {
24 final List<String> entryPoints; 24 final List<String> entryPoints;
25 final List<String> bindingStartDelimiters;
25 26
26 ImportInlinerTransformer([this.entryPoints]); 27 ImportInlinerTransformer(
28 [this.entryPoints, this.bindingStartDelimiters = const []]);
27 29
28 bool isPrimary(AssetId id) { 30 bool isPrimary(AssetId id) {
29 if (entryPoints != null) return entryPoints.contains(id.path); 31 if (entryPoints != null) return entryPoints.contains(id.path);
30 // If no entry point is supplied, then any html file under web/ or test/ is 32 // If no entry point is supplied, then any html file under web/ or test/ is
31 // an entry point. 33 // an entry point.
32 return (id.path.startsWith('web/') || id.path.startsWith('test/')) && 34 return (id.path.startsWith('web/') || id.path.startsWith('test/')) &&
33 id.path.endsWith('.html'); 35 id.path.endsWith('.html');
34 } 36 }
35 37
36 apply(Transform transform) { 38 apply(Transform transform) {
37 var logger = new BuildLogger(transform, convertErrorsToWarnings: true); 39 var logger = new BuildLogger(transform, convertErrorsToWarnings: true);
38 return new ImportInliner(transform, transform.primaryInput.id, logger) 40 return new ImportInliner(transform, transform.primaryInput.id, logger,
39 .run(); 41 bindingStartDelimiters: bindingStartDelimiters).run();
40 } 42 }
41 } 43 }
42 44
43 /// Helper class which actually does all the inlining of html imports for a 45 /// Helper class which actually does all the inlining of html imports for a
44 /// single entry point. 46 /// single entry point.
45 class ImportInliner { 47 class ImportInliner {
46 // Can be an AggregateTransform or Transform 48 // Can be an AggregateTransform or Transform
47 final transform; 49 final transform;
48 // The primary input to start from. 50 // The primary input to start from.
49 final AssetId primaryInput; 51 final AssetId primaryInput;
50 // The logger to use. 52 // The logger to use.
51 final BuildLogger logger; 53 final BuildLogger logger;
54 // The start delimiters for template bindings, such as '{{' or '[['.
55 final List<String> bindingStartDelimiters;
52 56
53 ImportInliner(this.transform, this.primaryInput, this.logger); 57 ImportInliner(this.transform, this.primaryInput, this.logger,
58 {this.bindingStartDelimiters: const []});
54 59
55 Future run() { 60 Future run() {
56 var crawler = new ImportCrawler(transform, primaryInput, logger); 61 var crawler = new ImportCrawler(transform, primaryInput, logger);
57 return crawler.crawlImports().then((imports) { 62 return crawler.crawlImports().then((imports) {
58 var primaryDocument = imports[primaryInput].document; 63 var primaryDocument = imports[primaryInput].document;
59 64
60 // Normalize urls in the entry point. 65 // Normalize urls in the entry point.
61 var changed = new _UrlNormalizer(primaryInput, primaryInput, logger) 66 var changed = new _UrlNormalizer(
67 primaryInput, primaryInput, logger, bindingStartDelimiters)
62 .visit(primaryDocument); 68 .visit(primaryDocument);
63 69
64 // Inline things if needed, always have at least one (the entry point). 70 // Inline things if needed, always have at least one (the entry point).
65 if (imports.length > 1) { 71 if (imports.length > 1) {
66 _inlineImports(primaryDocument, imports); 72 _inlineImports(primaryDocument, imports);
67 } else if (!changed && 73 } else if (!changed &&
68 primaryDocument.querySelectorAll('link[rel="import"]').length == 0) { 74 primaryDocument.querySelectorAll('link[rel="import"]').length == 0) {
69 // If there were no url changes and no imports, then we are done. 75 // If there were no url changes and no imports, then we are done.
70 return; 76 return;
71 } 77 }
(...skipping 25 matching lines...) Expand all
97 103
98 // Add all the other imports! 104 // Add all the other imports!
99 imports.forEach((AssetId asset, ImportData data) { 105 imports.forEach((AssetId asset, ImportData data) {
100 if (asset == primaryInput) return; 106 if (asset == primaryInput) return;
101 var document = data.document; 107 var document = data.document;
102 // Remove all dart script tags. 108 // Remove all dart script tags.
103 document 109 document
104 .querySelectorAll('script[type="$dartType"]') 110 .querySelectorAll('script[type="$dartType"]')
105 .forEach((script) => script.remove()); 111 .forEach((script) => script.remove());
106 // Normalize urls in attributes and inline css. 112 // Normalize urls in attributes and inline css.
107 new _UrlNormalizer(data.fromId, asset, logger).visit(document); 113 new _UrlNormalizer(data.fromId, asset, logger, bindingStartDelimiters)
114 .visit(document);
108 // Replace the import with its contents by appending the nodes 115 // Replace the import with its contents by appending the nodes
109 // immediately before the import one at a time, and then removing the 116 // immediately before the import one at a time, and then removing the
110 // import from the document. 117 // import from the document.
111 var element = data.element; 118 var element = data.element;
112 var parent = element.parent; 119 var parent = element.parent;
113 document.head.nodes 120 document.head.nodes
114 .toList(growable: false) 121 .toList(growable: false)
115 .forEach((child) => parent.insertBefore(child, element)); 122 .forEach((child) => parent.insertBefore(child, element));
116 document.body.nodes 123 document.body.nodes
117 .toList(growable: false) 124 .toList(growable: false)
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 /// Counter used to ensure that every library name we inject is unique. 173 /// Counter used to ensure that every library name we inject is unique.
167 int _count = 0; 174 int _count = 0;
168 175
169 /// Path to the top level folder relative to the transform primaryInput. 176 /// Path to the top level folder relative to the transform primaryInput.
170 /// This should just be some arbitrary # of ../'s. 177 /// This should just be some arbitrary # of ../'s.
171 final String topLevelPath; 178 final String topLevelPath;
172 179
173 /// Whether or not the normalizer has changed something in the tree. 180 /// Whether or not the normalizer has changed something in the tree.
174 bool changed = false; 181 bool changed = false;
175 182
183 // The start delimiters for template bindings, such as '{{' or '[['. If these
184 // are found before the first `/` in a url, then the url will not be
185 // normalized.
186 final List<String> bindingStartDelimiters;
187
176 final BuildLogger logger; 188 final BuildLogger logger;
177 189
178 _UrlNormalizer(AssetId primaryInput, this.sourceId, this.logger) 190 _UrlNormalizer(AssetId primaryInput, this.sourceId, this.logger,
191 this.bindingStartDelimiters)
179 : primaryInput = primaryInput, 192 : primaryInput = primaryInput,
180 topLevelPath = '../' * (path.url.split(primaryInput.path).length - 2); 193 topLevelPath = '../' * (path.url.split(primaryInput.path).length - 2);
181 194
182 bool visit(Node node) { 195 bool visit(Node node) {
183 super.visit(node); 196 super.visit(node);
184 return changed; 197 return changed;
185 } 198 }
186 199
187 visitElement(Element node) { 200 visitElement(Element node) {
188 // TODO(jakemac): Support custom elements that extend html elements which 201 // TODO(jakemac): Support custom elements that extend html elements which
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 var suffix = href.substring(href.indexOf('packages/') + 9); 255 var suffix = href.substring(href.indexOf('packages/') + 9);
243 return '${topLevelPath}packages/$suffix'; 256 return '${topLevelPath}packages/$suffix';
244 } else if (href.contains('assets/')) { 257 } else if (href.contains('assets/')) {
245 var suffix = href.substring(href.indexOf('assets/') + 7); 258 var suffix = href.substring(href.indexOf('assets/') + 7);
246 return '${topLevelPath}packages/$suffix'; 259 return '${topLevelPath}packages/$suffix';
247 } 260 }
248 261
249 hrefToParse = '${href.substring(0, firstFolder + 1)}'; 262 hrefToParse = '${href.substring(0, firstFolder + 1)}';
250 } 263 }
251 264
265 // If we found a binding before the first `/`, then just return the original
266 // href, we can't determine anything about it.
267 if (bindingStartDelimiters.any((d) => hrefToParse.contains(d))) return href;
268
252 Uri uri; 269 Uri uri;
253 // Various template systems introduce invalid characters to uris which would 270 // Various template systems introduce invalid characters to uris which would
254 // be typically replaced at runtime. Parse errors are assumed to be caused 271 // be typically replaced at runtime. Parse errors are assumed to be caused
255 // by this, and we just return the original href in that case. 272 // by this, and we just return the original href in that case.
256 try { 273 try {
257 uri = Uri.parse(hrefToParse); 274 uri = Uri.parse(hrefToParse);
258 } catch (e) { 275 } catch (e) {
259 return href; 276 return href;
260 } 277 }
261 if (uri.isAbsolute) return href; 278 if (uri.isAbsolute) return href;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 '_href', // in a, area, link, base, command 354 '_href', // in a, area, link, base, command
338 'icon', 355 'icon',
339 '_icon', // in command 356 '_icon', // in command
340 'manifest', 357 'manifest',
341 '_manifest', // in html 358 '_manifest', // in html
342 'poster', 359 'poster',
343 '_poster', // in video 360 '_poster', // in video
344 'src', 361 'src',
345 '_src', // in audio, embed, iframe, img, input, script, source, track,video 362 '_src', // in audio, embed, iframe, img, input, script, source, track,video
346 ]; 363 ];
OLDNEW
« no previous file with comments | « CHANGELOG.md ('k') | pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698