| OLD | NEW |
| 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 library web_components.build.import_crawler; | 4 library web_components.build.import_crawler; |
| 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:code_transformers/assets.dart'; | 8 import 'package:code_transformers/assets.dart'; |
| 9 import 'package:code_transformers/messages/build_logger.dart'; | 9 import 'package:code_transformers/messages/build_logger.dart'; |
| 10 import 'package:barback/barback.dart'; | 10 import 'package:barback/barback.dart'; |
| 11 import 'package:html5lib/dom.dart' show Document, Element; | 11 import 'package:html5lib/dom.dart' show Document, Element; |
| 12 import 'common.dart'; | 12 import 'common.dart'; |
| 13 import 'messages.dart'; | 13 import 'messages.dart'; |
| 14 | 14 |
| 15 /// Information about an html import found in a document. | 15 /// Information about an html import found in a document. |
| 16 class ImportData { | 16 class ImportData { |
| 17 /// The [AssetId] where the html import appeared. |
| 18 final AssetId fromId; |
| 19 |
| 17 /// The [Document] where the html import appeared. | 20 /// The [Document] where the html import appeared. |
| 18 final Document document; | 21 final Document document; |
| 19 | 22 |
| 20 /// The html import element itself. | 23 /// The html import element itself. |
| 21 final Element element; | 24 final Element element; |
| 22 | 25 |
| 23 ImportData(this.document, this.element); | 26 ImportData(this.document, this.element, {this.fromId}); |
| 24 } | 27 } |
| 25 | 28 |
| 26 /// A crawler for html imports. | 29 /// A crawler for html imports. |
| 27 class ImportCrawler { | 30 class ImportCrawler { |
| 28 // Can be either an AggregateTransform or Transform. | 31 // Can be either an AggregateTransform or Transform. |
| 29 final _transform; | 32 final _transform; |
| 30 final BuildLogger _logger; | 33 final BuildLogger _logger; |
| 31 final AssetId _primaryInputId; | 34 final AssetId _primaryInputId; |
| 32 | 35 |
| 33 // Optional parsed document for the primary id if available. | 36 // Optional parsed document for the primary id if available. |
| 34 final Document _primaryDocument; | 37 final Document _primaryDocument; |
| 35 | 38 |
| 36 ImportCrawler(this._transform, this._primaryInputId, this._logger, | 39 ImportCrawler(this._transform, this._primaryInputId, this._logger, |
| 37 {Document primaryDocument}) | 40 {Document primaryDocument}) |
| 38 : _primaryDocument = primaryDocument; | 41 : _primaryDocument = primaryDocument; |
| 39 | 42 |
| 40 /// Returns a post-ordered map of [AssetId]'s to [ImportData]. The [AssetId]'s | 43 /// Returns a post-ordered map of [AssetId]'s to [ImportData]. The [AssetId]'s |
| 41 /// represent an asset which was discovered via an html import, and the | 44 /// represent an asset which was discovered via an html import, and the |
| 42 /// [ImportData] represents the [Document] where it was discovered and the | 45 /// [ImportData] represents the [Document] where it was discovered and the |
| 43 /// html import [Element] itself. | 46 /// html import [Element] itself. |
| 44 Future<LinkedHashMap<AssetId, ImportData>> crawlImports() { | 47 Future<LinkedHashMap<AssetId, ImportData>> crawlImports() { |
| 45 var documents = new LinkedHashMap<AssetId, ImportData>(); | 48 var documents = new LinkedHashMap<AssetId, ImportData>(); |
| 46 var seen = new Set<AssetId>(); | 49 var seen = new Set<AssetId>(); |
| 47 | 50 |
| 48 Future doCrawl(AssetId assetId, [Element import, Document document]) { | 51 Future doCrawl(AssetId assetId, |
| 52 {Element import, Document document, AssetId from}) { |
| 49 if (seen.contains(assetId)) return null; | 53 if (seen.contains(assetId)) return null; |
| 50 seen.add(assetId); | 54 seen.add(assetId); |
| 51 | 55 |
| 52 Future crawlImports(Document document) { | 56 Future crawlImports(Document document) { |
| 53 var imports = document.querySelectorAll('link[rel="import"]'); | 57 var imports = document.querySelectorAll('link[rel="import"]'); |
| 54 var done = | 58 var done = Future.forEach(imports, |
| 55 Future.forEach(imports, (i) => doCrawl(_importId(assetId, i), i)); | 59 (i) => doCrawl(_importId(assetId, i), import: i, from: assetId)); |
| 56 | 60 |
| 57 // Add this document after its dependencies. | 61 // Add this document after its dependencies. |
| 58 return done.then((_) { | 62 return done.then((_) { |
| 59 documents[assetId] = new ImportData(document, import); | 63 documents[assetId] = new ImportData(document, import, fromId: from); |
| 60 }); | 64 }); |
| 61 } | 65 } |
| 62 | 66 |
| 63 if (document != null) { | 67 if (document != null) { |
| 64 return crawlImports(document); | 68 return crawlImports(document); |
| 65 } else { | 69 } else { |
| 66 return _transform.readInputAsString(assetId).then((html) { | 70 return _transform.readInputAsString(assetId).then((html) { |
| 67 return crawlImports(parseHtml(html, assetId.path)); | 71 return crawlImports(parseHtml(html, assetId.path)); |
| 68 }).catchError((error) { | 72 }).catchError((error) { |
| 69 var span; | 73 var span; |
| 70 if (import != null) span = import.sourceSpan; | 74 if (import != null) span = import.sourceSpan; |
| 71 _logger.error(inlineImportFail.create({'error': error}), span: span); | 75 _logger.error(inlineImportFail.create({'error': error}), span: span); |
| 72 }); | 76 }); |
| 73 } | 77 } |
| 74 } | 78 } |
| 75 | 79 |
| 76 return | 80 return doCrawl(_primaryInputId, document: _primaryDocument) |
| 77 doCrawl(_primaryInputId, null, _primaryDocument).then((_) => documents); | 81 .then((_) => documents); |
| 78 } | 82 } |
| 79 | 83 |
| 80 AssetId _importId(AssetId source, Element import) { | 84 AssetId _importId(AssetId source, Element import) { |
| 81 var url = import.attributes['href']; | 85 var url = import.attributes['href']; |
| 82 return uriToAssetId(source, url, _transform.logger, import.sourceSpan); | 86 return uriToAssetId(source, url, _transform.logger, import.sourceSpan); |
| 83 } | 87 } |
| 84 } | 88 } |
| OLD | NEW |