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