From d6003ee0abac936577137766bf7ba9f93905279e Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Mon, 6 Apr 2015 13:30:35 -0700 Subject: [PATCH] chore(build): Add traceur transpiler for broccoli. This exactly reproduces the output tree from one of the gulp tasks, which is now removed. Next step is to migrate another sibling task to broccoli. --- Brocfile.js | 38 ++++++++++++++++++++++ gulpfile.js | 57 +++++++++++++++++++++++++++------ package.json | 8 +++++ tools/broccoli/traceur/index.js | 50 +++++++++++++++++++++++++++++ tools/broccoli/traceur/index.ts | 44 +++++++++++++++++++++++++ tools/build/html.js | 1 + 6 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 Brocfile.js create mode 100644 tools/broccoli/traceur/index.js create mode 100644 tools/broccoli/traceur/index.ts diff --git a/Brocfile.js b/Brocfile.js new file mode 100644 index 0000000000..2790214dbf --- /dev/null +++ b/Brocfile.js @@ -0,0 +1,38 @@ +/** + * Build pipeline for Angular2. + * First time setup: + * $ npm install --global broccoli-cli + */ +var merge = require('merge'); +var TraceurCompiler = require('./tools/broccoli/traceur'); +var Funnel = require('broccoli-funnel'); +var stew = require('broccoli-stew'); + +var _COMPILER_CONFIG_JS_DEFAULT = { + sourceMaps: true, + annotations: true, // parse annotations + types: true, // parse types + script: false, // parse as a module + memberVariables: true, // parse class fields + modules: 'instantiate' +}; + +var modulesTree = new Funnel('modules', {include: ['**/**'], destDir: '/'}); + +var transpiledTree = new TraceurCompiler(modulesTree, merge(true, _COMPILER_CONFIG_JS_DEFAULT, { + typeAssertionModule: 'rtts_assert/rtts_assert', + typeAssertions: true, + outputLanguage: 'es6' +})); + +transpiledTree = stew.rename(transpiledTree, function(relativePath) { + return relativePath.replace(/\.(js|es6)\.map$/, '.map') + .replace(/\.js$/, '.es6'); +}); +transpiledTree = stew.mv(transpiledTree, 'js/dev/es6') + +//transpiledTree = stew.log(transpiledTree); + + +module.exports = transpiledTree; + diff --git a/gulpfile.js b/gulpfile.js index d40f700554..b760fbed3a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,3 +1,7 @@ +var broccoli = require('broccoli'); +var copyDereferenceSync = require('copy-dereference').sync; +var fse = require('fs-extra'); + var format = require('gulp-clang-format'); var gulp = require('gulp'); var gulpPlugins = require('gulp-load-plugins')(); @@ -278,6 +282,47 @@ var CONFIG = { }; CONFIG.test.js.cjs = CONFIG.test.js.cjs.map(function(s) {return CONFIG.dest.js.cjs + s}); +// ------------ +// integration point to run broccoli build + +var broccoliExecuted = false; + +gulp.task('broccoli', function() { + if (broccoliExecuted) { + throw new Error('The broccoli task can be called only once!'); + } + broccoliExecuted = true; + + var broccoliDist = path.join('dist', 'js', 'dev', 'es6'); + fse.removeSync(broccoliDist); + fse.mkdirsSync(path.join('dist', 'js', 'dev')); + + var tree = broccoli.loadBrocfile(); + var builder = new broccoli.Builder(tree); + return builder.build() + .then(function (hash) { + var dir = hash.directory; + try { + copyDereferenceSync(path.join(dir, 'js', 'dev', 'es6'), broccoliDist); + } catch (err) { + if (err.code === 'EEXIST') err.message += ' (we cannot build into an existing directory)'; + throw err; + } + }) + .finally(function () { + builder.cleanup(); + }) + .catch(function (err) { + // Should show file and line/col if present + if (err.file) { + console.error('File: ' + err.file); + } + console.error(err.stack); + console.error('\nBuild failed'); + process.exit(1); + }); +}); + // ------------ // clean @@ -317,15 +362,6 @@ gulp.task('build/transpile.ts.cjs', function() { ]); }); -gulp.task('build/transpile.js.dev.es6', transpile(gulp, gulpPlugins, { - src: CONFIG.transpile.src.js, - dest: CONFIG.dest.js.dev.es6, - outputExt: 'es6', - options: CONFIG.transpile.options.js.dev, - srcFolderInsertion: CONFIG.srcFolderInsertion.js -})); - - gulp.task('build/transpile.ts.dev.es5', function() { var tsResult = gulp.src(CONFIG.transpile.src.ts) .pipe(sourcemaps.init()) @@ -353,7 +389,7 @@ gulp.task('build/transpile.js.dev.es5', function() { gulp.task('build/transpile.js.dev', function(done) { runSequence( - 'build/transpile.js.dev.es6', + // broccoli runs the ES6 version of this task 'build/transpile.js.dev.es5', done ); @@ -806,6 +842,7 @@ gulp.task('build.dart', function(done) { gulp.task('build.js.dev', function(done) { runSequence( + 'broccoli', ['build/transpile.js.dev', 'build/html.js.dev', 'build/copy.js.dev', 'build/multicopy.js.dev.es6'], 'build/checkCircularDependencies', done diff --git a/package.json b/package.json index 655805cb7f..231dae7ece 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ }, "dependencies": { "es6-module-loader": "^0.9.2", + "fs-extra": "^0.18.0", "googleapis": "1.0.x", "gulp-insert": "^0.4.0", "gulp-modify": "0.0.4", @@ -41,7 +42,12 @@ "devDependencies": { "angular": "1.3.5", "bower": "^1.3.12", + "broccoli": "^0.15.3", + "broccoli-funnel": "^0.2.3", + "broccoli-stew": "^0.2.1", + "broccoli-writer": "^0.1.1", "canonical-path": "0.0.2", + "copy-dereference": "^1.0.0", "css": "mlaval/css#issue65", "del": "~1", "dgeni": "^0.4.1", @@ -87,6 +93,8 @@ "through2": "^0.6.1", "typescript": "alexeagle/TypeScript#93dbbe2a2d0b42cefd02ac949e4bc8ab6b5b5823", "vinyl": "^0.4.6", + "walk-sync": "^0.1.3", + "xtend": "^4.0.0", "yargs": "2.3.*" } } diff --git a/tools/broccoli/traceur/index.js b/tools/broccoli/traceur/index.js new file mode 100644 index 0000000000..6d915577d5 --- /dev/null +++ b/tools/broccoli/traceur/index.js @@ -0,0 +1,50 @@ +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +var fs = require('fs'); +var fse = require('fs-extra'); +var path = require('path'); +var traceur = require('../../transpiler'); +var walkSync = require('walk-sync'); +var Writer = require('broccoli-writer'); +var xtend = require('xtend'); +var TraceurFilter = (function (_super) { + __extends(TraceurFilter, _super); + function TraceurFilter(inputTree, options) { + if (options === void 0) { options = {}; } + this.inputTree = inputTree; + this.options = options; + } + TraceurFilter.prototype.write = function (readTree, destDir) { + var _this = this; + return readTree(this.inputTree).then(function (srcDir) { + walkSync(srcDir).filter(function (filepath) { + var extension = path.extname(filepath).toLowerCase(); + return extension === '.js' || extension === '.es6'; + }).map(function (filepath) { + var options = xtend({ + filename: filepath + }, _this.options); + var fsOpts = { + encoding: 'utf-8' + }; + var sourcecode = fs.readFileSync(path.join(srcDir, filepath), fsOpts); + var result = traceur.compile(options, filepath, sourcecode); + result.js = result.js + '\n//# sourceMappingURL=./' + path.basename(filepath).replace(/\.\w+$/, '.map'); + var destFilepath = filepath.replace(/\.\w+$/, '.es6'); + var destFile = path.join(destDir, destFilepath); + fse.mkdirsSync(path.dirname(destFile)); + var destMap = path.join(destDir, filepath + '.map'); + fs.writeFileSync(destFile, result.js, fsOpts); + result.sourceMap.file = destFilepath; + fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts); + }); + }); + }; + return TraceurFilter; +})(Writer); +module.exports = TraceurFilter; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/tools/broccoli/traceur/index.ts b/tools/broccoli/traceur/index.ts new file mode 100644 index 0000000000..4b09557b42 --- /dev/null +++ b/tools/broccoli/traceur/index.ts @@ -0,0 +1,44 @@ +var fs = require('fs'); +var fse = require('fs-extra'); +var path = require('path'); +var traceur = require('../../transpiler'); +var walkSync = require('walk-sync'); +var Writer = require('broccoli-writer'); +var xtend = require('xtend'); + +class TraceurFilter extends Writer { + constructor(private inputTree, private options = {}) {} + + write(readTree, destDir) { + return readTree(this.inputTree) + .then(srcDir => { + walkSync(srcDir) + .filter(filepath => { + var extension = path.extname(filepath).toLowerCase(); + return extension === '.js' || extension === '.es6'; + }) + .map(filepath => { + var options = xtend({filename: filepath}, this.options); + + var fsOpts = {encoding: 'utf-8'}; + var sourcecode = fs.readFileSync(path.join(srcDir, filepath), fsOpts); + + var result = traceur.compile(options, filepath, sourcecode); + + result.js = result.js + '\n//# sourceMappingURL=./' + path.basename(filepath).replace(/\.\w+$/, '.map'); + + var destFilepath = filepath.replace(/\.\w+$/, '.es6'); + var destFile = path.join(destDir, destFilepath); + fse.mkdirsSync(path.dirname(destFile)); + var destMap = path.join(destDir, filepath + '.map'); + + + fs.writeFileSync(destFile, result.js, fsOpts); + result.sourceMap.file = destFilepath; + fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts); + }); + }); + } +} + +module.exports = TraceurFilter; diff --git a/tools/build/html.js b/tools/build/html.js index c3371d4a1f..cbcae891db 100644 --- a/tools/build/html.js +++ b/tools/build/html.js @@ -5,6 +5,7 @@ var path = require('path'); var fs = require('fs'); var VinylFile = require('vinyl'); +// used for generating html files and bootstrapping benchmarks and examples module.exports = function(gulp, plugins, config) { return function() { return gulp.src(config.src)