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)