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 |