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..f8ffaa273b8be8d577b04b39598f04cebee59c7f |
--- /dev/null |
+++ b/lib/build/html_import_annotation_inliner.dart |
@@ -0,0 +1,124 @@ |
+// 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:analyzer/analyzer.dart'; |
+import 'package:barback/barback.dart'; |
+import 'package:html5lib/dom.dart' as dom; |
+import 'package:html5lib/parser.dart'; |
+import 'package:initialize/plugin_transformer.dart'; |
+import 'package:source_maps/refactor.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. |
+/// Notes: Does not inline the import, it just puts the <link rel="import"> tag. |
+/// This also has a few limitations, it only supports string literals (to avoid |
+/// using the analyzer to resolve references) and doesn't support const |
+/// references to HtmlImport annotations (for the same reason). |
+class HtmlImportAnnotationInliner extends InitializePluginTransformer { |
+ final String _bootstrapFile; |
+ final String _htmlEntryPoint; |
+ TransformLogger _logger; |
+ final Set<String> importPaths = new Set(); |
+ |
+ HtmlImportAnnotationInliner(String bootstrapFile, this._htmlEntryPoint) |
+ : super(bootstrapFile), |
+ _bootstrapFile = bootstrapFile; |
+ |
+ 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) { |
+ var superValue = super.classifyPrimary(id); |
+ if (superValue != null) return superValue; |
+ // Group it with the bootstrap file. |
+ if (_htmlEntryPoint == id.path) return _bootstrapFile; |
+ return null; |
+ } |
+ |
+ apply(AggregateTransform transform) { |
+ _logger = transform.logger; |
+ return super.apply(transform).then((_) { |
+ var htmlEntryPoint = |
+ allAssets.firstWhere((asset) => asset.id.path == _htmlEntryPoint); |
+ return 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,}; |
Siggi Cherem (dart-lang)
2015/02/12 16:49:44
nit: remove trailing comma `,`?
jakemac
2015/02/12 17:04:09
oh I probably had these on separate lines in which
|
+ doc.head.append(import); |
+ } |
+ transform |
+ .addOutput(new Asset.fromString(htmlEntryPoint.id, doc.outerHtml)); |
+ }); |
+ }); |
+ } |
+ |
+ // Executed for each initializer constructor in the bootstrap file. We filter |
+ // out the HtmlImport ones and inline them. |
+ initEntry( |
+ InstanceCreationExpression expression, TextEditTransaction transaction) { |
+ // Filter out extraneous values. |
+ if (expression is! InstanceCreationExpression) return; |
+ var args = expression.argumentList.arguments; |
+ // Only support InstanceCreationExpressions. Const references to HtmlImport |
+ // annotations can't be cheaply discovered. |
+ if (args[0] is! InstanceCreationExpression) return; |
+ if (!'${args[0].constructorName.type.name}'.contains('.HtmlImport')) return; |
+ |
+ // Grab the raw path supplied to the HtmlImport. Only string literals are |
+ // supported for the transformer. |
Siggi Cherem (dart-lang)
2015/02/12 16:49:44
FYI - I opened https://github.com/dart-lang/initia
jakemac
2015/02/12 17:04:09
I replied there, but basically in the new plugin a
|
+ var originalPath = args[0].argumentList.arguments[0]; |
+ if (originalPath is SimpleStringLiteral) { |
+ originalPath = originalPath.value; |
+ } else { |
+ _logger.warning('Found HtmlImport constructor which was supplied an ' |
+ 'expression. Only raw strings are currently supported for the ' |
+ 'transformer, so $originalPath will be injected dynamically'); |
+ return; |
+ } |
+ |
+ // Now grab the package from the LibraryIdentifier, we know its either a |
+ // string or null literal. |
+ var package = args[1].argumentList.arguments[1]; |
+ if (package is SimpleStringLiteral) { |
+ package = package.value; |
+ } else if (package is NullLiteral) { |
+ package = null; |
+ } else { |
+ _logger.error('Invalid LibraryIdentifier declaration. The 2nd argument ' |
+ 'be a literal string or null. `${args[1]}`'); |
+ } |
+ |
+ // And finally get the original dart file path, this is always a string |
+ // literal. |
+ var dartPath = args[1].argumentList.arguments[2]; |
+ if (dartPath is SimpleStringLiteral) { |
+ dartPath = dartPath.value; |
+ } else { |
+ _logger.error('Invalid LibraryIdentifier declaration. The 3rd argument ' |
+ 'be a literal string. `${args[1]}`'); |
+ } |
+ |
+ // Add the normalized path to our list and remove the expression from the |
+ // bootstrap file. |
+ importPaths.add(normalizeHtmlImportPath(originalPath, package, dartPath)); |
+ removeInitializer(expression, transaction); |
+ } |
+} |