Chromium Code Reviews| Index: pkg/polymer/lib/src/build/import_inliner.dart | 
| diff --git a/pkg/polymer/lib/src/build/import_inliner.dart b/pkg/polymer/lib/src/build/import_inliner.dart | 
| index d58afcaef53fea337ba48e4614a5639d9c1dc8c7..d80adc11b6e6af52551e9a37631c8bdbc4585bd1 100644 | 
| --- a/pkg/polymer/lib/src/build/import_inliner.dart | 
| +++ b/pkg/polymer/lib/src/build/import_inliner.dart | 
| @@ -24,9 +24,11 @@ class _HtmlInliner extends PolymerTransformer { | 
| final TransformLogger logger; | 
| final AssetId docId; | 
| final seen = new Set<AssetId>(); | 
| - final imported = new DocumentFragment(); | 
| final scriptIds = <AssetId>[]; | 
| + static const TYPE_DART = 'application/dart'; | 
| + static const TYPE_JS = 'text/javascript'; | 
| + | 
| _HtmlInliner(this.options, Transform transform) | 
| : transform = transform, | 
| logger = transform.logger, | 
| @@ -40,12 +42,11 @@ class _HtmlInliner extends PolymerTransformer { | 
| return readPrimaryAsHtml(transform).then((document) => | 
| _visitImports(document, docId).then((importsFound) { | 
| + var output = transform.primaryInput; | 
| if (importsFound) { | 
| - document.body.insertBefore(imported, document.body.firstChild); | 
| - transform.addOutput(new Asset.fromString(docId, document.outerHtml)); | 
| - } else { | 
| - transform.addOutput(transform.primaryInput); | 
| + output = new Asset.fromString(docId, document.outerHtml); | 
| } | 
| + transform.addOutput(output); | 
| // We produce a secondary asset with extra information for later phases. | 
| transform.addOutput(new Asset.fromString( | 
| @@ -65,6 +66,8 @@ class _HtmlInliner extends PolymerTransformer { | 
| Future<bool> _visitImports(Document document, AssetId sourceId) { | 
| bool changed = false; | 
| + _moveHeadToBody(document); | 
| + | 
| // Note: we need to preserve the import order in the generated output. | 
| return Future.forEach(document.querySelectorAll('link'), (Element tag) { | 
| var rel = tag.attributes['rel']; | 
| @@ -76,21 +79,53 @@ class _HtmlInliner extends PolymerTransformer { | 
| if (rel == 'import') { | 
| changed = true; | 
| - tag.remove(); | 
| - if (id == null || !seen.add(id)) return null; | 
| - return _inlineImport(id); | 
| + if (id == null || !seen.add(id)) { | 
| + tag.remove(); | 
| + return null; | 
| + } | 
| + return _inlineImport(id, tag); | 
| } else if (rel == 'stylesheet') { | 
| if (id == null) return null; | 
| changed = true; | 
| + | 
| return _inlineStylesheet(id, tag); | 
| } | 
| }).then((_) => changed); | 
| } | 
| + /** | 
| + * To preserve the order of scripts with respect to inlined | 
| + * link rel=import, we move both of those into the body before we do any | 
| + * inlining. | 
| + * | 
| + * Note: we do this for stylesheets as well to preserve ordering with | 
| + * respect to eachother, because stylesheets can be pulled in transitively | 
| + * from imports. | 
| + */ | 
| + // TODO(jmesserly): vulcanizer doesn't need this because they inline JS | 
| + // scripts, causing them to be naturally moved as part of the inlining. | 
| + // Should we do the same? Alternatively could we inline head into head and | 
| + // body into body and avoid this whole thing? | 
| + void _moveHeadToBody(Document doc) { | 
| + var insertionPoint = doc.body.firstChild; | 
| + for (var node in doc.head.nodes.toList(growable: false)) { | 
| + if (node is! Element) continue; | 
| + var tag = node.tagName; | 
| + var type = node.attributes['type']; | 
| + var rel = node.attributes['rel']; | 
| + if (tag == 'style' || tag == 'script' && | 
| + (type == null || type == TYPE_JS || type == TYPE_DART) || | 
| + tag == 'link' && (rel == 'stylesheet' || rel == 'import')) { | 
| + // Move the node into the body, where its contents will be placed. | 
| + doc.body.insertBefore(node, insertionPoint); | 
| + } | 
| + } | 
| + } | 
| + | 
| // Loads an asset identified by [id], visits its imports and collects its | 
| // html imports. Then inlines it into the main document. | 
| - Future _inlineImport(AssetId id) => | 
| + Future _inlineImport(AssetId id, Element link) => | 
| readAsHtml(id, transform).then((doc) => _visitImports(doc, id).then((_) { | 
| new _UrlNormalizer(transform, id).visit(doc); | 
| @@ -98,7 +133,9 @@ class _HtmlInliner extends PolymerTransformer { | 
| // TODO(jmesserly): figure out how this is working in vulcanizer. | 
| // Do they produce a <body> tag with a <head> and <body> inside? | 
| + var imported = new DocumentFragment(); | 
| imported.nodes..addAll(doc.head.nodes)..addAll(doc.body.nodes); | 
| + link.replaceWith(imported); | 
| 
 
Siggi Cherem (dart-lang)
2014/02/20 03:50:55
not sure I follow, why not remove the link node?
 
Jennifer Messerly
2014/02/20 03:59:08
replaceWith should remove it & replace it with the
 
Siggi Cherem (dart-lang)
2014/02/20 04:37:19
Sorry, I saw the added lines, and for some reason
 
 | 
| })); | 
| Future _inlineStylesheet(AssetId id, Element link) { | 
| @@ -118,7 +155,7 @@ class _HtmlInliner extends PolymerTransformer { | 
| void _extractScripts(Document document) { | 
| bool first = true; | 
| for (var script in document.querySelectorAll('script')) { | 
| - if (script.attributes['type'] == 'application/dart') { | 
| + if (script.attributes['type'] == TYPE_DART) { | 
| script.remove(); | 
| // only one Dart script per document is supported in Dartium. |