Index: web_components/lib/build/script_compactor.dart |
diff --git a/web_components/lib/build/script_compactor.dart b/web_components/lib/build/script_compactor.dart |
deleted file mode 100644 |
index 12655b3e5870b6ec9fcc26b78fec78a129195ce1..0000000000000000000000000000000000000000 |
--- a/web_components/lib/build/script_compactor.dart |
+++ /dev/null |
@@ -1,261 +0,0 @@ |
-// 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.script_compactor; |
- |
-import 'dart:async'; |
-import 'package:analyzer/analyzer.dart'; |
-import 'package:barback/barback.dart'; |
-import 'package:code_transformers/assets.dart'; |
-import 'package:code_transformers/messages/build_logger.dart'; |
-import 'package:html/dom.dart' as dom; |
-import 'package:html/parser.dart' as parser; |
-import 'package:path/path.dart' as path; |
-import 'package:source_maps/refactor.dart' show TextEditTransaction; |
-import 'package:source_span/source_span.dart'; |
-import 'common.dart'; |
-import 'import_crawler.dart'; |
-import 'messages.dart'; |
- |
-/// Transformer which combines all dart scripts found in html imports into one |
-/// new bootstrap file, and replaces the old entry point script with that file. |
-/// |
-/// Note: Does not delete the original script files (it can't because the |
-/// imports may live in other packages). The [ImportInlinerTransformer] will not |
-/// copy scripts when inlining imports into your entry point to compensate for |
-/// this. |
-class ScriptCompactorTransformer extends Transformer { |
- final List<String> entryPoints; |
- |
- ScriptCompactorTransformer([this.entryPoints]); |
- |
- bool isPrimary(AssetId id) { |
- if (entryPoints != null) return entryPoints.contains(id.path); |
- // If no entry point is supplied, then any html file under web/ or test/ is |
- // an entry point. |
- return (id.path.startsWith('web/') || id.path.startsWith('test/')) && |
- id.path.endsWith('.html'); |
- } |
- |
- apply(Transform transform) { |
- var logger = new BuildLogger(transform); |
- return new ScriptCompactor(transform, transform.primaryInput.id, logger) |
- .run() |
- .then((Asset bootstrap) { |
- if (bootstrap == null) return null; |
- return transform.primaryInput.readAsString().then((html) { |
- var doc = parser.parse(html); |
- var mainScriptTag = doc.querySelector('script[type="$dartType"]'); |
- mainScriptTag.attributes['src'] = |
- _importPath(bootstrap.id, transform.primaryInput.id); |
- mainScriptTag.text = ''; |
- |
- transform.addOutput( |
- new Asset.fromString(transform.primaryInput.id, doc.outerHtml)); |
- }); |
- }); |
- } |
-} |
- |
-/// Helper class which does all the script compacting for a single entry point. |
-class ScriptCompactor { |
- /// Can be an AggregateTransform or Transform |
- final transform; |
- |
- /// The primary input to start from. |
- final AssetId primaryInput; |
- |
- /// The logger to use. |
- final BuildLogger logger; |
- |
- /// How many inline scripts were extracted. |
- int inlineScriptCounter = 0; |
- |
- /// Id representing the dart script which lives in the primaryInput. |
- AssetId mainScript; |
- |
- /// Ids of all the scripts found in html imports. |
- final Set<AssetId> importScripts = new Set<AssetId>(); |
- |
- ScriptCompactor(this.transform, this.primaryInput, this.logger); |
- |
- Future<Asset> run() { |
- var crawler = new ImportCrawler(transform, primaryInput, logger); |
- return crawler.crawlImports().then((imports) { |
- Future extractScripts(id) => |
- _extractInlineScripts(id, imports[id].document); |
- |
- return Future.forEach(imports.keys, extractScripts).then((_) { |
- if (mainScript == null) { |
- logger.error( |
- exactlyOneScriptPerEntryPoint.create({'url': primaryInput.path})); |
- return null; |
- } |
- |
- var primaryDocument = imports[primaryInput].document; |
- assert(primaryDocument != null); |
- |
- // Create the new bootstrap file and return its AssetId. |
- return _buildBootstrapFile(mainScript, importScripts); |
- }); |
- }); |
- } |
- |
- /// Builds the bootstrap file and returns the path to it relative to |
- /// [primaryInput]. |
- Asset _buildBootstrapFile(AssetId mainScript, Set<AssetId> importScripts) { |
- var bootstrapId = new AssetId(primaryInput.package, |
- primaryInput.path.replaceFirst('.html', '.bootstrap.dart')); |
- |
- var buffer = new StringBuffer(); |
- buffer.writeln('library ${_libraryNameFor(bootstrapId)};'); |
- buffer.writeln(); |
- var i = 0; |
- for (var script in importScripts) { |
- var path = _importPath(script, primaryInput); |
- buffer.writeln("import '$path' as i$i;"); |
- i++; |
- } |
- var mainScriptPath = _importPath(mainScript, primaryInput); |
- buffer.writeln("import '$mainScriptPath' as i$i;"); |
- buffer.writeln(); |
- buffer.writeln('main() => i$i.main();'); |
- |
- var bootstrap = new Asset.fromString(bootstrapId, '$buffer'); |
- transform.addOutput(bootstrap); |
- return bootstrap; |
- } |
- |
- /// Split inline scripts into their own files. We need to do this for dart2js |
- /// to be able to compile them. |
- /// |
- /// This also validates that there weren't any duplicate scripts. |
- Future _extractInlineScripts(AssetId asset, dom.Document doc) { |
- var scripts = doc.querySelectorAll('script[type="$dartType"]'); |
- return Future.forEach(scripts, (script) { |
- var type = script.attributes['type']; |
- var src = script.attributes['src']; |
- |
- if (src != null) { |
- return _addScript( |
- asset, uriToAssetId(asset, src, logger, script.sourceSpan), |
- span: script.sourceSpan); |
- } |
- |
- final count = inlineScriptCounter++; |
- var code = script.text; |
- // TODO(sigmund): ensure this path is unique (dartbug.com/12618). |
- var newId = primaryInput.addExtension('.$count.dart'); |
- if (!_hasLibraryDirective(code)) { |
- var libName = _libraryNameFor(primaryInput, count); |
- code = "library $libName;\n$code"; |
- } |
- |
- // Normalize dart import paths. |
- code = _normalizeDartImports(code, asset, primaryInput); |
- |
- // Write out the file and record it. |
- transform.addOutput(new Asset.fromString(newId, code)); |
- |
- return _addScript(asset, newId, validate: false).then((_) { |
- // If in the entry point, replace the inline script with one pointing to |
- // the new source file. |
- if (primaryInput == asset) { |
- script.text = ''; |
- script.attributes['src'] = path.url.relative(newId.path, |
- from: path.url.dirname(primaryInput.path)); |
- } |
- }); |
- }); |
- } |
- |
- // Normalize dart import paths when moving code from one asset to another. |
- String _normalizeDartImports(String code, AssetId from, AssetId to) { |
- var unit = parseDirectives(code, suppressErrors: true); |
- var file = new SourceFile(code, url: spanUrlFor(from, to, logger)); |
- var output = new TextEditTransaction(code, file); |
- var foundLibraryDirective = false; |
- for (Directive directive in unit.directives) { |
- if (directive is UriBasedDirective) { |
- var uri = directive.uri.stringValue; |
- var span = getSpan(file, directive.uri); |
- |
- var id = uriToAssetId(from, uri, logger, span, errorOnAbsolute: false); |
- if (id == null) continue; |
- |
- var primaryId = primaryInput; |
- var newUri = assetUrlFor(id, primaryId, logger); |
- if (newUri != uri) { |
- output.edit(span.start.offset, span.end.offset, "'$newUri'"); |
- } |
- } else if (directive is LibraryDirective) { |
- foundLibraryDirective = true; |
- } |
- } |
- |
- if (!output.hasEdits) return code; |
- |
- // TODO(sigmund): emit source maps when barback supports it (see |
- // dartbug.com/12340) |
- return (output.commit()..build(file.url.toString())).text; |
- } |
- |
- Future _addScript(AssetId from, AssetId scriptId, |
- {bool validate: true, SourceSpan span}) { |
- var validateFuture; |
- if (validate && !importScripts.contains(scriptId)) { |
- validateFuture = transform.hasInput(scriptId); |
- } else { |
- validateFuture = new Future.value(true); |
- } |
- return validateFuture.then((exists) { |
- if (!exists) { |
- logger.warning(scriptFileNotFound.create({'url': scriptId}), |
- span: span); |
- } |
- |
- if (from == primaryInput) { |
- if (mainScript != null) { |
- logger |
- .error(exactlyOneScriptPerEntryPoint.create({'url': from.path})); |
- } |
- mainScript = scriptId; |
- } else { |
- importScripts.add(scriptId); |
- } |
- }); |
- } |
-} |
- |
-/// Generate a library name for an asset. |
-String _libraryNameFor(AssetId id, [int suffix]) { |
- var name = '${path.withoutExtension(id.path)}_' |
- '${path.extension(id.path).substring(1)}'; |
- if (name.startsWith('lib/')) name = name.substring(4); |
- name = name.split('/').map((part) { |
- part = part.replaceAll(_invalidLibCharsRegex, '_'); |
- if (part.startsWith(_numRegex)) part = '_${part}'; |
- return part; |
- }).join("."); |
- var suffixString = suffix != null ? '_$suffix' : ''; |
- return '${id.package}.${name}$suffixString'; |
-} |
- |
-/// Parse [code] and determine whether it has a library directive. |
-bool _hasLibraryDirective(String code) => |
- parseDirectives(code, suppressErrors: true).directives |
- .any((d) => d is LibraryDirective); |
- |
-/// Returns the dart import path to reach [id] relative to [primaryInput]. |
-String _importPath(AssetId id, AssetId primaryInput) { |
- var parts = path.url.split(id.path); |
- if (parts[0] == 'lib') { |
- parts[0] = id.package; |
- return 'package:${path.url.joinAll(parts)}'; |
- } |
- return path.url.relative(id.path, from: path.url.dirname(primaryInput.path)); |
-} |
- |
-// Constant and final variables |
-final _invalidLibCharsRegex = new RegExp('[^a-z0-9_]'); |
-final _numRegex = new RegExp('[0-9]'); |