add htmlEntryPoint option to transformer
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3b7f27..a5c9a3b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 0.1.1
+
+Added `htmlEntryPoint` option to the transformer. This will search that file for
+any script tag whose src is `entryPoint` and rewrite it to point at the
+bootstrapped file `newEntryPoint`.
+
## 0.1.0+1
Quick fix for the transformer on windows.
diff --git a/README.md b/README.md
index 082fda5..f5e91cf 100644
--- a/README.md
+++ b/README.md
@@ -53,9 +53,11 @@
but for deployment there is a transformer which can replace that with a static list
of initializers to be ran.
-This transformer does not modify your existing files, but instead creates a new
-entrypoint which bootstraps your existing app. Below is an example pubspec with the
-transformer:
+This will create a new entry point which bootstraps your existing app. If you
+supply an `htmlEntryPoint` then any script tags whose src is the same as
+`entryPoint` will be rewritten to the bootstrapped file `newEntryPoint`.
+
+Below is an example pubspec with the transformer:
name: my_app
dependencies:
@@ -64,10 +66,7 @@
- initialize:
entryPoint: web/index.dart
newEntryPoint: web/index.bootstrap.dart
-
-**Note**: Until https://github.com/dart-lang/initialize/issues/10 is resolved, it
-is necessary to rewrite any script tags pointing to your entry point to the new
-bootstrapped entry point manually.
+ htmlEntryPoint: web/index.html
## Creating your own initializer
diff --git a/lib/transformer.dart b/lib/transformer.dart
index 081a8c6..5cd7860 100644
--- a/lib/transformer.dart
+++ b/lib/transformer.dart
@@ -9,6 +9,8 @@
import 'package:analyzer/src/generated/element.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/resolver.dart';
+import 'package:html5lib/dom.dart' as dom;
+import 'package:html5lib/parser.dart' show parse;
import 'package:path/path.dart' as path;
/// Removes the mirror-based initialization logic and replaces it with static
@@ -17,8 +19,10 @@
final Resolvers _resolvers;
final String _entryPoint;
final String _newEntryPoint;
+ final String _htmlEntryPoint;
- InitializeTransformer(this._entryPoint, this._newEntryPoint)
+ InitializeTransformer(
+ this._entryPoint, this._newEntryPoint, this._htmlEntryPoint)
: _resolvers = new Resolvers.fromMock({
// The list of types below is derived from:
// * types that are used internally by the resolver (see
@@ -65,12 +69,23 @@
if (newEntryPoint == null) {
newEntryPoint = entryPoint.replaceFirst('.dart', '.bootstrap.dart');
}
- return new InitializeTransformer(entryPoint, newEntryPoint);
+ var htmlEntryPoint = settings.configuration['htmlEntryPoint'];
+ return new InitializeTransformer(entryPoint, newEntryPoint, htmlEntryPoint);
}
- bool isPrimary(AssetId id) => _entryPoint == id.path;
+ bool isPrimary(AssetId id) =>
+ _entryPoint == id.path || _htmlEntryPoint == id.path;
Future apply(Transform transform) {
+ if (transform.primaryInput.id.path == _entryPoint) {
+ return _buildBootstrapFile(transform);
+ } else if (transform.primaryInput.id.path == _htmlEntryPoint) {
+ return _replaceEntryWithBootstrap(transform);
+ }
+ return null;
+ }
+
+ Future _buildBootstrapFile(Transform transform) {
var newEntryPointId =
new AssetId(transform.primaryInput.id.package, _newEntryPoint);
return transform.hasInput(newEntryPointId).then((exists) {
@@ -85,6 +100,47 @@
}
});
}
+
+ Future _replaceEntryWithBootstrap(Transform transform) {
+ // For now at least, _htmlEntryPoint, _entryPoint, and _newEntryPoint need
+ // to be in the same folder.
+ // TODO(jakemac): support package urls with _entryPoint or _newEntryPoint
+ // in `lib`, and _htmlEntryPoint in another directory.
+ var _expectedDir = path.split(_htmlEntryPoint)[0];
+ if (_expectedDir != path.split(_entryPoint)[0] ||
+ _expectedDir != path.split(_newEntryPoint)[0]) {
+ transform.logger.error(
+ 'htmlEntryPoint, entryPoint, and newEntryPoint(if supplied) all must '
+ 'be in the same top level directory.');
+ }
+
+ return transform.primaryInput.readAsString().then((String html) {
+ var found = false;
+ var doc = parse(html);
+ var scripts = doc.querySelectorAll('script[type="application/dart"]');
+ for (dom.Element script in scripts) {
+ if (!_isEntryPointScript(script)) continue;
+ script.attributes['src'] = _relativeDartEntryPath(_newEntryPoint);
+ found = true;
+ }
+ if (!found) {
+ transform.logger.error(
+ 'Unable to find script for $_entryPoint in $_htmlEntryPoint.');
+ }
+ return transform.addOutput(
+ new Asset.fromString(transform.primaryInput.id, doc.outerHtml));
+ });
+ }
+
+ // Checks if the src of this script tag is pointing at `_entryPoint`.
+ bool _isEntryPointScript(dom.Element script) =>
+ path.normalize(script.attributes['src']) ==
+ _relativeDartEntryPath(_entryPoint);
+
+ // The relative path from `_htmlEntryPoint` to `dartEntry`. You must ensure
+ // that neither of these is null before calling this function.
+ String _relativeDartEntryPath(String dartEntry) =>
+ path.relative(dartEntry, from: path.dirname(_htmlEntryPoint));
}
class _BootstrapFileBuilder {
diff --git a/pubspec.yaml b/pubspec.yaml
index fe32be2..d17e0b0 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,11 +1,13 @@
name: initialize
-version: 0.1.0+1
+version: 0.1.1
author: Polymer.dart Authors <web@dartlang.org>
description: Generic building blocks for doing static initialization.
homepage: https://github.com/dart-lang/initialize
dependencies:
barback: '>=0.14.2 <0.16.0'
code_transformers: '>=0.2.3 <0.3.0'
+ html5lib: '>=0.12.0 <0.13.0'
+ path: '>=1.3.0 <2.0.0'
dev_dependencies:
unittest: '>=0.10.0 <0.12.0'
environment:
diff --git a/test/transformer_test.dart b/test/transformer_test.dart
index b27069a..bda6877 100644
--- a/test/transformer_test.dart
+++ b/test/transformer_test.dart
@@ -10,10 +10,15 @@
main() {
useCompactVMConfiguration();
- var transformer =
- new InitializeTransformer('web/index.dart', 'web/index.bootstrap.dart');
+ var transformer = new InitializeTransformer(
+ 'web/index.dart', 'web/index.bootstrap.dart', 'web/index.html');
testPhases('transformer', [[transformer]], {
+ 'a|web/index.html': '''
+ <html><head></head><body>
+ <script type="application/dart" src="index.dart"></script>
+ </body></html>
+ '''.replaceAll(' ', ''),
'a|web/index.dart': '''
library web_foo;
@@ -67,8 +72,13 @@
const _InitMethod();
}
const _InitMethod initMethod = const _InitMethod();
- '''
+ ''',
}, {
+ 'a|web/index.html': '''
+ <html><head></head><body>
+ <script type="application/dart" src="index.bootstrap.dart"></script>
+
+ </body></html>'''.replaceAll(' ', ''),
'a|web/index.bootstrap.dart': '''
import 'package:initialize/src/static_loader.dart';
import 'index.dart' as i0;
@@ -91,6 +101,6 @@
i0.main();
}
- '''.replaceAll(' ', '')
+ '''.replaceAll(' ', ''),
});
}