Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(712)

Unified Diff: lib/src/transform/script_compactor.dart

Issue 22825012: Introduce transformers for: (Closed) Base URL: git@github.com:dart-lang/web-ui.git@master
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/src/transform/script_compactor.dart
diff --git a/lib/src/transform/script_compactor.dart b/lib/src/transform/script_compactor.dart
new file mode 100644
index 0000000000000000000000000000000000000000..84d2032e61893d5dabc3aecf5b674e3a2f27da52
--- /dev/null
+++ b/lib/src/transform/script_compactor.dart
@@ -0,0 +1,122 @@
+// Copyright (c) 2013, 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.
+
+/** Transfomer that combines multiple dart script tags into a single one. */
+library polymer.src.transform.script_compactor;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:html5lib/parser.dart' show parseFragment;
+import 'package:path/path.dart' as path;
+
+import 'code_extractor.dart'; // import just for documentation.
terry 2013/08/20 17:03:24 If this import isn't used the editor will flag a w
Siggi Cherem (dart-lang) 2013/08/21 20:35:42 the good news is that they also recognize that the
+import 'common.dart';
+
+/**
+ * Combines Dart script tags into a single script tag, and creates a new Dart
+ * file that calls the main function of each of the original script tags.
+ *
+ * This transformer assumes that all script tags point to external files. To
+ * support script tags with inlined code, use this transformer after running
+ * [InlineCodeExtractor] on an earlier phase.
+ *
+ * Internally, this transformer will convert each script tag into an import
+ * statement to a library, and then uses `initPolymer` (see polymer.dart) to
+ * invoke the main method on each of these libraries and register any polymer
+ * elements annotated with `@CustomTag`.
+ */
+class ScriptCompactor extends Transformer {
+ Future<bool> isPrimary(Asset input) =>
+ new Future.value(input.id.extension == ".html");
+
+ Future apply(Transform transform) {
+ var id = transform.primaryId;
+ var logger = transform.logger;
+ return getPrimaryContent(transform).then((content) {
+ var document = parseHtml(content, id.path, logger);
+ var libraries = [];
+ bool changed = false;
+ for (var tag in document.queryAll('script')) {
+ if (tag.attributes['type'] != 'application/dart') continue;
+ tag.remove();
+ changed = true;
+ var src = tag.attributes['src'];
+ if (src == null) {
+ logger.warning('unexpected script without a src url', tag.sourceSpan);
Jennifer Messerly 2013/08/19 22:57:26 Hmm, why the warning here? Are we assuming the scr
Siggi Cherem (dart-lang) 2013/08/21 20:35:42 Good question. The transformers should always be r
+ continue;
+ }
+ var libraryId = resolve(id, src, logger, tag.sourceSpan);
+
+ // TODO(sigmund): should we detect/remove duplicates?
Jennifer Messerly 2013/08/19 22:57:26 i think so. don't want to generate erroneous code
Siggi Cherem (dart-lang) 2013/08/21 20:35:42 But then, wouldn't it be ok to import it twice? (w
Jennifer Messerly 2013/08/21 23:35:29 good point, importing twice would be fine assuming
+ if (libraryId == null) continue;
+ libraries.add(libraryId);
+ }
+
+ if (!changed) {
+ transform.addOutput(new Asset.fromString(id, content));
+ return;
+ }
+
+ var bootstrapId = id.addExtension('_bootstrap.dart');
+ var filename = path.basename(bootstrapId.path);
+ document.body.nodes.add(parseFragment(
+ '<script type="application/dart" src="$filename"></script>'));
+
+ var urls = libraries.map((id) => importUrlFor(id, bootstrapId, logger))
+ .where((url) => url != null).toList();
+ var buffer = new StringBuffer()..write(_header);
+ for (int i = 0; i < urls.length; i++) {
+ buffer.writeln("import '${urls[i]}' as i$i;");
+ }
+ buffer..write(_mainPrefix)
+ ..writeAll(urls.map((url) => " '$url',\n"))
+ ..write(_mainSuffix);
+
+ transform.addOutput(new Asset.fromString(bootstrapId, buffer.toString()));
+ transform.addOutput(new Asset.fromString(id, document.outerHtml));
+ });
+ }
+
+ /**
+ * Generate the import url for a file described by [id], referenced by a file
+ * with [sourceId].
+ */
+ String importUrlFor(AssetId id, AssetId sourceId, TransformLogger logger) {
+ // use package: urls if possible
+ if (id.path.startsWith('lib/')) {
+ return 'package:${id.package}/${id.path.substring(4)}';
+ }
+
+ // Use relative urls only if it's possible.
+ if (id.package != sourceId.package) {
+ logger.error("don't know how to import $id from $sourceId");
+ return null;
+ }
+
+ var upPath = path.joinAll(path.split(sourceId.path).map((_) => '..'));
+ return path.normalize(path.join(sourceId.path, upPath, id.path));
+ }
+}
+
+const _header = """
+library app_bootstrap;
+
+import 'package:polymer/polymer.dart';
+import 'dart:mirrors' show currentMirrorSystem;
+
+""";
+
+const _mainPrefix = """
+
+void main() {
+ initPolymer([
+""";
+
+const _mainSuffix = """
+ ],
+ currentMirrorSystem().findLibrary(const Symbol('app_bootstrap'))
Jennifer Messerly 2013/08/19 22:57:26 seems unfortunate to need to use mirrors for this.
Siggi Cherem (dart-lang) 2013/08/21 20:35:42 good question. I opened a bug to investigate.
Jennifer Messerly 2013/08/21 23:35:29 btw, I discovered another pattern using mirrors th
+ .first.uri.toString());
+}
+""";

Powered by Google App Engine
This is Rietveld 408576698