Index: lib/build/html_import_annotation_inliner.dart |
diff --git a/lib/build/html_import_annotation_inliner.dart b/lib/build/html_import_annotation_inliner.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ffb6668079f3db48793a8e2800b5c7ddc895b5d5 |
--- /dev/null |
+++ b/lib/build/html_import_annotation_inliner.dart |
@@ -0,0 +1,97 @@ |
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+library web_components.build.html_import_annotation_inliner; |
+ |
+import 'dart:async'; |
+import 'package:barback/barback.dart'; |
+import 'package:html5lib/dom.dart' as dom; |
+import 'package:html5lib/parser.dart'; |
+import '../src/normalize_path.dart'; |
+ |
+/// Given an html entry point with a single dart bootstrap file created by the |
+/// `initialize` transformer, this will open that dart file and remove all |
+/// `HtmlImport` initializers from it. Then it appends those imports to the head |
+/// of the html entry point. |
+/// Note: Does not inline the import, it just puts the <link rel="import"> tag. |
+class HtmlImportAnnotationInliner extends AggregateTransformer { |
+ final String _bootstrapFile; |
+ final String _htmlEntryPoint; |
+ TransformLogger _logger; |
+ |
+ HtmlImportAnnotationInliner(this._bootstrapFile, this._htmlEntryPoint); |
+ |
+ factory HtmlImportAnnotationInliner.asPlugin(BarbackSettings settings) { |
+ var bootstrapFile = settings.configuration['bootstrap_file']; |
+ if (bootstrapFile is! String || !bootstrapFile.endsWith('.dart')) { |
+ throw new ArgumentError( |
+ '`bootstrap_file` should be a string path to a dart file'); |
+ } |
+ var htmlEntryPoint = settings.configuration['html_entry_point']; |
+ if (htmlEntryPoint is! String || !htmlEntryPoint.endsWith('.html')) { |
+ throw new ArgumentError( |
+ '`html_entry_point` should be a string path to an html file'); |
+ } |
+ return new HtmlImportAnnotationInliner(bootstrapFile, htmlEntryPoint); |
+ } |
+ |
+ classifyPrimary(AssetId id) { |
+ if (_bootstrapFile == id.path || _htmlEntryPoint == id.path) return ' '; |
+ return null; |
+ } |
+ |
+ Future apply(AggregateTransform transform) { |
+ _logger = transform.logger; |
+ Asset dartEntryPoint; |
+ Asset htmlEntryPoint; |
+ return transform.primaryInputs.take(2).listen((Asset asset) { |
+ if (asset.id.path == _bootstrapFile) dartEntryPoint = asset; |
+ if (asset.id.path == _htmlEntryPoint) htmlEntryPoint = asset; |
+ }).asFuture().then((_) { |
+ // Will be populated with all import paths found in HtmlImport |
+ // constructors. |
+ var importPaths; |
+ return dartEntryPoint.readAsString().then((dartCode) { |
+ var matches = _htmlImportWithRawString.allMatches(dartCode); |
+ importPaths = new Set.from(matches.map((match) => |
+ normalizeHtmlImportPath( |
+ match.group(1), |
+ match.group(2) == 'null' ? null : match.group(2), |
+ match.group(3)))); |
+ |
+ var newDartCode = dartCode.replaceAll(_htmlImportWithRawString, ''); |
+ var leftoverMatches = _htmlImportGeneral.allMatches(newDartCode); |
+ for (var match in leftoverMatches) { |
+ _logger.warning('Found HtmlImport constructor which was supplied an ' |
+ 'expression. Only raw strings are currently supported for the ' |
+ 'transformer, so ${match.group(1)} will be injected dynamically'); |
+ } |
+ transform.addOutput( |
+ new Asset.fromString(dartEntryPoint.id, newDartCode)); |
+ }).then((_) => htmlEntryPoint.readAsString()).then((html) { |
+ var doc = parse(html); |
+ for (var importPath in importPaths) { |
+ var import = new dom.Element.tag('link')..attributes = { |
+ 'rel': 'import', |
+ 'href': importPath, |
+ }; |
+ doc.head.append(import); |
+ } |
+ transform.addOutput( |
+ new Asset.fromString(htmlEntryPoint.id, doc.outerHtml)); |
+ }); |
+ }); |
+ } |
+ |
+ // Matches HtmlImport constructors which are supplied a raw string. These are |
+ // the only ones currently supported for inlining. |
+ final RegExp _htmlImportWithRawString = new RegExp( |
Jennifer Messerly
2015/01/29 21:32:37
this is vaguely terrifying :)
although it gives m
jakemac
2015/02/02 20:55:57
Done, now using InitializerPluginTransformer which
|
+ r"\n\s*new InitEntry\(const i[\d]*\.HtmlImport\('([\w\d\/\.:]*\.html)'\)," |
+ r"\sconst\sLibraryIdentifier\(#[\w\.]*, '?([\w_]*)'?, '([\w\d\/\.]*)'\)\)" |
+ r","); |
+ |
+ // Matches HtmlImport initializers which are supplied any arguments. This |
+ // is used to detect if any were left over and not inlined. |
+ final RegExp _htmlImportGeneral = new RegExp( |
+ r"\n\s*new InitEntry\(const i[\d]*\.HtmlImport\(([\w\d\.]*)\),\s.*\),"); |
+} |