diff --git a/Brocfile-dart.js b/Brocfile-dart.js
new file mode 100644
index 0000000000..3bc9d4d33a
--- /dev/null
+++ b/Brocfile-dart.js
@@ -0,0 +1,43 @@
+// Brocfile to transpile sources from TypeScript to Dart using ts2dart.
+var Funnel = require('broccoli-funnel');
+var stew = require('broccoli-stew');
+var ts2dart = require('./dist/broccoli/broccoli-ts2dart');
+var path = require('path');
+
+// Transpile everything in 'modules'...
+var modulesTree = new Funnel('modules', {
+ include: ['**/*.js', '**/*.ts', '**/*.dart'], // .dart file available means don't translate.
+ exclude: ['rtts_assert/**/*'], // ... except for the rtts_asserts (don't apply to Dart).
+ destDir: '/', // Remove the 'modules' prefix.
+});
+
+// Transpile to dart.
+var dartTree = ts2dart.transpile(modulesTree);
+
+// Move around files to match Dart's layout expectations.
+dartTree = stew.rename(dartTree, function(relativePath) {
+ // If a file matches the `pattern`, insert the given `insertion` as the second path part.
+ var replacements = [
+ {pattern: /^benchmarks\/test\//, insertion: ''},
+ {pattern: /^benchmarks\//, insertion: 'web'},
+ {pattern: /^benchmarks_external\/test\//, insertion: ''},
+ {pattern: /^benchmarks_external\//, insertion: 'web'},
+ {pattern: /^example.?\//, insertion: 'web/'},
+ {pattern: /^example.?\/test\//, insertion: ''},
+ {pattern: /^[^\/]*\/test\//, insertion: ''},
+ {pattern: /^./, insertion: 'lib'}, // catch all.
+ ];
+
+ for (var i = 0; i < replacements.length; i++) {
+ var repl = replacements[i];
+ if (relativePath.match(repl.pattern)) {
+ var parts = relativePath.split('/');
+ parts.splice(1, 0, repl.insertion);
+ return path.join.apply(path, parts);
+ }
+ }
+ throw new Error('Failed to match any path', relativePath);
+});
+
+// Move the tree under the 'dart' folder.
+module.exports = stew.mv(dartTree, 'dart');
diff --git a/gulpfile.js b/gulpfile.js
index 0a2e9a33c6..e0463d0e19 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -29,7 +29,6 @@ var runServerDartTests = require('./tools/build/run_server_dart_tests');
var sourcemaps = require('gulp-sourcemaps');
var transformCJSTests = require('./tools/build/transformCJSTests');
var tsc = require('gulp-typescript');
-var ts2dart = require('gulp-ts2dart');
var util = require('./tools/build/util');
var bundler = require('./tools/build/bundle');
var replace = require('gulp-replace');
@@ -373,11 +372,8 @@ gulp.task('build/transformCJSTests', function() {
.pipe(gulp.dest(CONFIG.dest.js.cjs + '/angular2/test/'));
});
-gulp.task('build/transpile.dart', function() {
- return gulp.src(CONFIG.transpile.src.dart)
- .pipe(ts2dart.transpile())
- .pipe(util.insertSrcFolder(gulpPlugins, CONFIG.srcFolderInsertion.dart))
- .pipe(gulp.dest(CONFIG.dest.dart));
+gulp.task('build/transpile.dart', ['build.broccoli.tools'], function() {
+ return broccoliBuild(require('./Brocfile-dart.js'), 'dart');
});
// ------------
@@ -720,7 +716,8 @@ gulp.task('test.transpiler.unittest', function() {
// Builds all Dart packages, but does not compile them
gulp.task('build/packages.dart', function(done) {
runSequence(
- ['build/transpile.dart', 'build/html.dart', 'build/copy.dart', 'build/multicopy.dart'],
+ 'build/transpile.dart', // Creates the folder structure needed by subsequent tasks.
+ ['build/html.dart', 'build/copy.dart', 'build/multicopy.dart'],
'build/format.dart',
'build/pubspec.dart',
done
diff --git a/modules/angular2/globals.dart b/modules/angular2/globals.dart
new file mode 100644
index 0000000000..6f7bcd7000
--- /dev/null
+++ b/modules/angular2/globals.dart
@@ -0,0 +1,2 @@
+// Globals are provided by lang.dart in Dart.
+// This file exists to prevent global.ts from being transpiled.
diff --git a/package.json b/package.json
index b1803424c2..1c55a6eb74 100644
--- a/package.json
+++ b/package.json
@@ -72,7 +72,6 @@
"gulp-sourcemaps": "1.3.*",
"gulp-template": "^3.0.0",
"gulp-traceur": "0.17.*",
- "gulp-ts2dart": "^1.0.6",
"gulp-typescript": "ivogabe/gulp-typescript#3422fbff06532ccc57368f3b4c8801de8f72ef27",
"gulp-webserver": "^0.8.7",
"js-yaml": "^3.2.7",
@@ -97,7 +96,7 @@
"ternary-stream": "^1.2.3",
"through2": "^0.6.1",
"typescript": "alexeagle/TypeScript#93dbbe2a2d0b42cefd02ac949e4bc8ab6b5b5823",
- "ts2dart": "^0.2.0",
+ "ts2dart": "^0.3.0",
"vinyl": "^0.4.6",
"walk-sync": "^0.1.3",
"xtend": "^4.0.0",
diff --git a/tools/broccoli/broccoli-ts2dart.ts b/tools/broccoli/broccoli-ts2dart.ts
new file mode 100644
index 0000000000..70fed135d2
--- /dev/null
+++ b/tools/broccoli/broccoli-ts2dart.ts
@@ -0,0 +1,56 @@
+///
+///
+///
+
+import Writer = require('broccoli-writer');
+import fs = require('fs');
+import fse = require('fs-extra');
+import path = require('path');
+import ts2dart = require('ts2dart');
+
+type Set = {
+ [s:string]: boolean
+};
+
+class TypeScriptToDartTranspiler extends Writer {
+ constructor(private inputTree, private includePattern = /\.(js|ts)$/) { super(); }
+
+ write(readTree, destDir): Promise {
+ return readTree(this.inputTree).then(dir => this.transpile(dir, destDir));
+ }
+
+ private transpile(inputDir: string, destDir: string) {
+ var files = this.listRecursive(inputDir);
+ var toTranspile = [];
+ for (var f in files) {
+ // If it's not matching, don't translate.
+ if (!f.match(this.includePattern)) continue;
+ var dartVariant = f.replace(this.includePattern, '.dart');
+ // A .dart file of the same name takes precedence over transpiled code.
+ if (files.hasOwnProperty(dartVariant)) continue;
+ toTranspile.push(f);
+ }
+ var transpiler = new ts2dart.Transpiler(
+ {generateLibraryName: true, generateSourceMap: false, basePath: inputDir});
+ transpiler.transpile(toTranspile, destDir);
+ }
+
+ private listRecursive(root: string, res: Set = {}): Set {
+ var paths = fs.readdirSync(root);
+ paths.forEach((p) => {
+ p = path.join(root, p);
+ var stat = fs.statSync(p);
+ if (stat.isDirectory()) {
+ this.listRecursive(p, res);
+ } else {
+ // Collect *all* files so we can check .dart files that already exist and exclude them.
+ res[p] = true;
+ }
+ });
+ return res;
+ }
+}
+
+export function transpile(inputTree) {
+ return new TypeScriptToDartTranspiler(inputTree);
+}
diff --git a/tools/broccoli/broccoli-writer.d.ts b/tools/broccoli/broccoli-writer.d.ts
index ee2555c5d5..1505e4745d 100644
--- a/tools/broccoli/broccoli-writer.d.ts
+++ b/tools/broccoli/broccoli-writer.d.ts
@@ -2,7 +2,7 @@
declare class Writer {
- write(readTree: (tree) => Promise, destDir: string);
+ write(readTree: (tree) => Promise, destDir: string): Promise;
}
export = Writer;
diff --git a/tools/broccoli/ts2dart.d.ts b/tools/broccoli/ts2dart.d.ts
new file mode 100644
index 0000000000..5b93f4cc60
--- /dev/null
+++ b/tools/broccoli/ts2dart.d.ts
@@ -0,0 +1,14 @@
+// TODO(martinprobst): This is a hand-written declarations file. Replace with an automatically
+// generated one when TypeScript has a strategy to distribute TS source via npm.
+
+export interface TranspilerOptions {
+ failFast?: boolean;
+ generateLibraryName?: boolean;
+ generateSourceMap?: boolean;
+ basePath?: string;
+}
+
+export class Transpiler{
+ constructor(options: TranspilerOptions);
+ transpile(fileNames: string[], outdir?: string);
+}