chore(build): add typescript to the cjs build.
Refactor the file extension logic in traceur plugin to simplify
This commit is contained in:
parent
b5002fb46b
commit
f0477e164a
@ -2,12 +2,14 @@ var Funnel = require('broccoli-funnel');
|
|||||||
var mergeTrees = require('broccoli-merge-trees');
|
var mergeTrees = require('broccoli-merge-trees');
|
||||||
var stew = require('broccoli-stew');
|
var stew = require('broccoli-stew');
|
||||||
var TraceurCompiler = require('./tools/broccoli/traceur');
|
var TraceurCompiler = require('./tools/broccoli/traceur');
|
||||||
|
var TypescriptCompiler = require('./tools/broccoli/typescript');
|
||||||
var renderLodashTemplate = require('broccoli-lodash');
|
var renderLodashTemplate = require('broccoli-lodash');
|
||||||
|
|
||||||
var modulesTree = new Funnel('modules', {include: ['**/**'], exclude: ['angular2/src/core/zone/vm_turn_zone.es6']});
|
var modulesTree = new Funnel(
|
||||||
|
'modules', {include: ['**/**'], exclude: ['angular2/src/core/zone/vm_turn_zone.es6']});
|
||||||
|
|
||||||
// Use Traceur to transpile original sources to ES6
|
// Use Traceur to transpile original sources to ES5
|
||||||
var cjsTree = new TraceurCompiler(modulesTree, '.js', {
|
var traceurOpts = {
|
||||||
sourceMaps: true,
|
sourceMaps: true,
|
||||||
annotations: true, // parse annotations
|
annotations: true, // parse annotations
|
||||||
types: true, // parse types
|
types: true, // parse types
|
||||||
@ -17,18 +19,13 @@ var cjsTree = new TraceurCompiler(modulesTree, '.js', {
|
|||||||
// Don't use type assertions since this is partly transpiled by typescript
|
// Don't use type assertions since this is partly transpiled by typescript
|
||||||
typeAssertions: false,
|
typeAssertions: false,
|
||||||
modules: 'commonjs'
|
modules: 'commonjs'
|
||||||
}, true);
|
};
|
||||||
|
var cjsTree = new TraceurCompiler(modulesTree, '.js', '.map', traceurOpts);
|
||||||
|
|
||||||
// Munge the filenames since we use an '.es6' extension
|
// Add the LICENSE file in each module
|
||||||
cjsTree = stew.rename(cjsTree, function(relativePath) {
|
|
||||||
return relativePath.replace(/\.(js|es6)\.map$/, '.map').replace(/\.es6$/, '.js');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Now we add a few more files to the es6 tree that Traceur should not see
|
|
||||||
['angular2', 'benchmarks', 'benchmarks_external', 'benchpress', 'examples', 'rtts_assert'].forEach(
|
['angular2', 'benchmarks', 'benchmarks_external', 'benchpress', 'examples', 'rtts_assert'].forEach(
|
||||||
function(destDir) {
|
function(destDir) {
|
||||||
var extras = new Funnel('.', {files: ['LICENSE'], destDir: destDir});
|
cjsTree = mergeTrees([cjsTree, new Funnel('.', {files: ['LICENSE'], destDir: destDir})]);
|
||||||
cjsTree = mergeTrees([cjsTree, extras]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
extras = new Funnel(modulesTree, {include: ['**/*.md', '**/*.png'], exclude: ['**/*.dart.md']});
|
extras = new Funnel(modulesTree, {include: ['**/*.md', '**/*.png'], exclude: ['**/*.dart.md']});
|
||||||
@ -53,12 +50,25 @@ var COMMON_PACKAGE_JSON = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add a .template extension since renderLodashTemplate strips one extension
|
// Add a .template extension since renderLodashTemplate strips one extension
|
||||||
var packageJsons = stew.rename(new Funnel(modulesTree, {include: ['**/package.json']}), '.json', '.json.template');
|
var packageJsons =
|
||||||
packageJsons = renderLodashTemplate(packageJsons, {
|
stew.rename(new Funnel(modulesTree, {include: ['**/package.json']}), '.json', '.json.template');
|
||||||
files: ["**/**"],
|
packageJsons = renderLodashTemplate(
|
||||||
context: { 'packageJson': COMMON_PACKAGE_JSON }
|
packageJsons, {files: ["**/**"], context: {'packageJson': COMMON_PACKAGE_JSON}});
|
||||||
|
|
||||||
|
var typescriptTree = new TypescriptCompiler(modulesTree, {
|
||||||
|
target: 'ES5',
|
||||||
|
sourceMap: true,
|
||||||
|
mapRoot: '', /* force sourcemaps to use relative path */
|
||||||
|
module: /*system.js*/'commonjs',
|
||||||
|
allowNonTsExtensions: false,
|
||||||
|
typescript: require('typescript'),
|
||||||
|
//declarationFiles: true,
|
||||||
|
noEmitOnError: true,
|
||||||
|
outDir: 'angular2'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// For now, we just overwrite the Traceur-compiled files with their Typescript equivalent
|
||||||
|
cjsTree = mergeTrees([cjsTree, typescriptTree], { overwrite: true });
|
||||||
cjsTree = mergeTrees([cjsTree, extras, packageJsons]);
|
cjsTree = mergeTrees([cjsTree, extras, packageJsons]);
|
||||||
|
|
||||||
module.exports = stew.mv(cjsTree, 'js/cjs');
|
module.exports = stew.mv(cjsTree, 'js/cjs');
|
||||||
|
@ -10,7 +10,7 @@ var path = require('path');
|
|||||||
var modulesTree = new Funnel('modules', {include: ['**/**'], exclude: ['**/*.cjs'], destDir: '/'});
|
var modulesTree = new Funnel('modules', {include: ['**/**'], exclude: ['**/*.cjs'], destDir: '/'});
|
||||||
|
|
||||||
// Use Traceur to transpile original sources to ES6
|
// Use Traceur to transpile original sources to ES6
|
||||||
var es6DevTree = new TraceurCompiler(modulesTree, '.es6', {
|
var es6DevTree = new TraceurCompiler(modulesTree, '.es6', '.map', {
|
||||||
sourceMaps: true,
|
sourceMaps: true,
|
||||||
annotations: true, // parse annotations
|
annotations: true, // parse annotations
|
||||||
types: true, // parse types
|
types: true, // parse types
|
||||||
@ -21,14 +21,9 @@ var es6DevTree = new TraceurCompiler(modulesTree, '.es6', {
|
|||||||
typeAssertions: true,
|
typeAssertions: true,
|
||||||
outputLanguage: 'es6'
|
outputLanguage: 'es6'
|
||||||
});
|
});
|
||||||
// Munge the filenames since we use an '.es6' extension
|
|
||||||
es6DevTree = stew.rename(es6DevTree, function(relativePath) {
|
|
||||||
return relativePath.replace(/\.(js|es6)\.map$/, '.map').replace(/\.js$/, '.es6');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Call Traceur again to lower the ES6 build tree to ES5
|
// Call Traceur again to lower the ES6 build tree to ES5
|
||||||
var es5DevTree = new TraceurCompiler(es6DevTree, '.js', {modules: 'instantiate', sourceMaps: true});
|
var es5DevTree = new TraceurCompiler(es6DevTree, '.js', '.js.map', {modules: 'instantiate', sourceMaps: true});
|
||||||
es5DevTree = stew.rename(es5DevTree, '.es6.map', '.js.map');
|
|
||||||
|
|
||||||
// Now we add a few more files to the es6 tree that Traceur should not see
|
// Now we add a few more files to the es6 tree that Traceur should not see
|
||||||
['angular2', 'benchmarks', 'benchmarks_external', 'benchpress', 'examples', 'rtts_assert'].forEach(
|
['angular2', 'benchmarks', 'benchmarks_external', 'benchpress', 'examples', 'rtts_assert'].forEach(
|
||||||
|
@ -10,7 +10,7 @@ var path = require('path');
|
|||||||
var modulesTree = new Funnel('modules', {include: ['**/**'], destDir: '/'});
|
var modulesTree = new Funnel('modules', {include: ['**/**'], destDir: '/'});
|
||||||
|
|
||||||
// Use Traceur to transpile original sources to ES6
|
// Use Traceur to transpile original sources to ES6
|
||||||
var es6ProdTree = new TraceurCompiler(modulesTree, '.es6', {
|
var es6ProdTree = new TraceurCompiler(modulesTree, '.es6', '.map', {
|
||||||
sourceMaps: true,
|
sourceMaps: true,
|
||||||
annotations: true, // parse annotations
|
annotations: true, // parse annotations
|
||||||
types: true, // parse types
|
types: true, // parse types
|
||||||
@ -21,14 +21,9 @@ var es6ProdTree = new TraceurCompiler(modulesTree, '.es6', {
|
|||||||
typeAssertions: false,
|
typeAssertions: false,
|
||||||
outputLanguage: 'es6'
|
outputLanguage: 'es6'
|
||||||
});
|
});
|
||||||
// Munge the filenames since we use an '.es6' extension
|
|
||||||
es6ProdTree = stew.rename(es6ProdTree, function(relativePath) {
|
|
||||||
return relativePath.replace(/\.(js|es6)\.map$/, '.map').replace(/\.js$/, '.es6');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Call Traceur again to lower the ES6 build tree to ES5
|
// Call Traceur again to lower the ES6 build tree to ES5
|
||||||
var es5ProdTree = new TraceurCompiler(es6ProdTree, '.js', {modules: 'instantiate', sourceMaps: true});
|
var es5ProdTree = new TraceurCompiler(es6ProdTree, '.js', '.js.map', {modules: 'instantiate', sourceMaps: true});
|
||||||
es5ProdTree = stew.rename(es5ProdTree, '.es6.map', '.js.map');
|
|
||||||
|
|
||||||
// Now we add a few more files to the es6 tree that Traceur should not see
|
// Now we add a few more files to the es6 tree that Traceur should not see
|
||||||
['angular2', 'benchmarks', 'benchmarks_external', 'benchpress', 'examples', 'rtts_assert'].forEach(
|
['angular2', 'benchmarks', 'benchmarks_external', 'benchpress', 'examples', 'rtts_assert'].forEach(
|
||||||
|
@ -761,10 +761,6 @@ gulp.task('broccoli.js.cjs', function() {
|
|||||||
gulp.task('build.js.cjs', function(done) {
|
gulp.task('build.js.cjs', function(done) {
|
||||||
runSequence(
|
runSequence(
|
||||||
'broccoli.js.cjs',
|
'broccoli.js.cjs',
|
||||||
//['build/transpile.js.cjs', 'build/copy.js.cjs', 'build/multicopy.js.cjs'],
|
|
||||||
// Overwrite the .js.cjs transpilation with typescript outputs
|
|
||||||
// We still need traceur outputs everywhere else, for now.
|
|
||||||
'build/transpile.ts.cjs',
|
|
||||||
['build/linknodemodules.js.cjs'],
|
['build/linknodemodules.js.cjs'],
|
||||||
'build/transformCJSTests',
|
'build/transformCJSTests',
|
||||||
done
|
done
|
||||||
|
@ -13,14 +13,12 @@ var Writer = require('broccoli-writer');
|
|||||||
var xtend = require('xtend');
|
var xtend = require('xtend');
|
||||||
var TraceurFilter = (function (_super) {
|
var TraceurFilter = (function (_super) {
|
||||||
__extends(TraceurFilter, _super);
|
__extends(TraceurFilter, _super);
|
||||||
function TraceurFilter(inputTree, destExtension, options, hackSourceMapExtension) {
|
function TraceurFilter(inputTree, destExtension, destSourceMapExtension, options) {
|
||||||
if (destExtension === void 0) { destExtension = '.js'; }
|
|
||||||
if (options === void 0) { options = {}; }
|
if (options === void 0) { options = {}; }
|
||||||
if (hackSourceMapExtension === void 0) { hackSourceMapExtension = false; }
|
|
||||||
this.inputTree = inputTree;
|
this.inputTree = inputTree;
|
||||||
this.destExtension = destExtension;
|
this.destExtension = destExtension;
|
||||||
|
this.destSourceMapExtension = destSourceMapExtension;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.hackSourceMapExtension = hackSourceMapExtension;
|
|
||||||
}
|
}
|
||||||
TraceurFilter.prototype.write = function (readTree, destDir) {
|
TraceurFilter.prototype.write = function (readTree, destDir) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
@ -39,16 +37,13 @@ var TraceurFilter = (function (_super) {
|
|||||||
var result = traceur.compile(options, filepath, sourcecode);
|
var result = traceur.compile(options, filepath, sourcecode);
|
||||||
// TODO: we should fix the sourceMappingURL written by Traceur instead of overriding
|
// TODO: we should fix the sourceMappingURL written by Traceur instead of overriding
|
||||||
// (but we might switch to typescript first)
|
// (but we might switch to typescript first)
|
||||||
var url = path.basename(filepath).replace(/\.es6$/, '') + (_this.destExtension === '.js' ? '.js.map' : '.map');
|
var mapFilepath = filepath.replace(/\.\w+$/, '') + _this.destSourceMapExtension;
|
||||||
if (_this.hackSourceMapExtension) {
|
result.js = result.js + ("\n//# sourceMappingURL=./" + path.basename(mapFilepath));
|
||||||
url = path.basename(filepath).replace(/\.\w+$/, '') + '.map';
|
|
||||||
}
|
|
||||||
result.js = result.js + ("\n//# sourceMappingURL=./" + url);
|
|
||||||
var destFilepath = filepath.replace(/\.\w+$/, _this.destExtension);
|
var destFilepath = filepath.replace(/\.\w+$/, _this.destExtension);
|
||||||
var destFile = path.join(destDir, destFilepath);
|
var destFile = path.join(destDir, destFilepath);
|
||||||
fse.mkdirsSync(path.dirname(destFile));
|
fse.mkdirsSync(path.dirname(destFile));
|
||||||
var destMap = path.join(destDir, destFilepath + '.map');
|
|
||||||
fs.writeFileSync(destFile, result.js, fsOpts);
|
fs.writeFileSync(destFile, result.js, fsOpts);
|
||||||
|
var destMap = path.join(destDir, mapFilepath);
|
||||||
result.sourceMap.file = destFilepath;
|
result.sourceMap.file = destFilepath;
|
||||||
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
|
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
|
||||||
});
|
});
|
||||||
|
@ -7,9 +7,11 @@ var Writer = require('broccoli-writer');
|
|||||||
var xtend = require('xtend');
|
var xtend = require('xtend');
|
||||||
|
|
||||||
class TraceurFilter extends Writer {
|
class TraceurFilter extends Writer {
|
||||||
constructor(private inputTree, private destExtension: string = '.js',
|
|
||||||
private options = {}, private hackSourceMapExtension: boolean = false) {}
|
|
||||||
static RUNTIME_PATH = traceur.RUNTIME_PATH;
|
static RUNTIME_PATH = traceur.RUNTIME_PATH;
|
||||||
|
|
||||||
|
constructor(private inputTree, private destExtension: string,
|
||||||
|
private destSourceMapExtension: string, private options = {}) {}
|
||||||
|
|
||||||
write(readTree, destDir) {
|
write(readTree, destDir) {
|
||||||
return readTree(this.inputTree)
|
return readTree(this.inputTree)
|
||||||
.then(srcDir => {
|
.then(srcDir => {
|
||||||
@ -29,21 +31,15 @@ class TraceurFilter extends Writer {
|
|||||||
|
|
||||||
// TODO: we should fix the sourceMappingURL written by Traceur instead of overriding
|
// TODO: we should fix the sourceMappingURL written by Traceur instead of overriding
|
||||||
// (but we might switch to typescript first)
|
// (but we might switch to typescript first)
|
||||||
var url = path.basename(filepath).replace(/\.es6$/, '') +
|
var mapFilepath = filepath.replace(/\.\w+$/, '') + this.destSourceMapExtension;
|
||||||
(this.destExtension === '.js' ? '.js.map' : '.map');
|
result.js = result.js + `\n//# sourceMappingURL=./${path.basename(mapFilepath)}`;
|
||||||
if (this.hackSourceMapExtension) {
|
|
||||||
url = path.basename(filepath).replace(/\.\w+$/, '') + '.map';
|
|
||||||
}
|
|
||||||
result.js = result.js + `\n//# sourceMappingURL=./${url}`;
|
|
||||||
|
|
||||||
var destFilepath = filepath.replace(/\.\w+$/, this.destExtension);
|
var destFilepath = filepath.replace(/\.\w+$/, this.destExtension);
|
||||||
var destFile = path.join(destDir, destFilepath);
|
var destFile = path.join(destDir, destFilepath);
|
||||||
fse.mkdirsSync(path.dirname(destFile));
|
fse.mkdirsSync(path.dirname(destFile));
|
||||||
var destMap = path.join(destDir, destFilepath + '.map');
|
|
||||||
|
|
||||||
|
|
||||||
fs.writeFileSync(destFile, result.js, fsOpts);
|
fs.writeFileSync(destFile, result.js, fsOpts);
|
||||||
|
|
||||||
|
var destMap = path.join(destDir, mapFilepath);
|
||||||
result.sourceMap.file = destFilepath;
|
result.sourceMap.file = destFilepath;
|
||||||
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
|
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
|
||||||
});
|
});
|
||||||
|
61
tools/broccoli/typescript/index.js
Normal file
61
tools/broccoli/typescript/index.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
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 path = require('path');
|
||||||
|
var ts = require('typescript');
|
||||||
|
var walkSync = require('walk-sync');
|
||||||
|
var Writer = require('broccoli-writer');
|
||||||
|
var xtend = require('xtend');
|
||||||
|
var TSCompiler = (function (_super) {
|
||||||
|
__extends(TSCompiler, _super);
|
||||||
|
function TSCompiler(inputTree, options) {
|
||||||
|
if (options === void 0) { options = {}; }
|
||||||
|
_super.call(this, inputTree, options);
|
||||||
|
this.inputTree = inputTree;
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
TSCompiler.prototype.write = function (readTree, destDir) {
|
||||||
|
var options = xtend({
|
||||||
|
outDir: destDir
|
||||||
|
}, this.options);
|
||||||
|
if (this.options.outDir) {
|
||||||
|
options.outDir = path.resolve(destDir, options.outDir);
|
||||||
|
}
|
||||||
|
if (options.out) {
|
||||||
|
options.out = path.resolve(destDir, options.out);
|
||||||
|
}
|
||||||
|
options.target = ts.ScriptTarget[options.target];
|
||||||
|
return readTree(this.inputTree).then(function (srcDir) {
|
||||||
|
var files = walkSync(srcDir).filter(function (filepath) {
|
||||||
|
return path.extname(filepath).toLowerCase() === '.ts';
|
||||||
|
}).map(function (filepath) {
|
||||||
|
return path.resolve(srcDir, filepath);
|
||||||
|
});
|
||||||
|
if (files.length > 0) {
|
||||||
|
var program = ts.createProgram(files, options);
|
||||||
|
var emitResult = program.emit();
|
||||||
|
var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
|
||||||
|
var errMsg = '';
|
||||||
|
allDiagnostics.forEach(function (diagnostic) {
|
||||||
|
var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||||
|
if (!diagnostic.file) {
|
||||||
|
errMsg += "\n" + message;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var _a = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start), line = _a.line, character = _a.character;
|
||||||
|
errMsg += "\n" + diagnostic.file.fileName + " (" + (line + 1) + "," + (character + 1) + "): " + message;
|
||||||
|
});
|
||||||
|
if (emitResult.emitSkipped) {
|
||||||
|
throw new Error(errMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return TSCompiler;
|
||||||
|
})(Writer);
|
||||||
|
module.exports = TSCompiler;
|
||||||
|
//# sourceMappingURL=index.js.map
|
51
tools/broccoli/typescript/index.ts
Normal file
51
tools/broccoli/typescript/index.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var ts = require('typescript');
|
||||||
|
var walkSync = require('walk-sync');
|
||||||
|
var Writer = require('broccoli-writer');
|
||||||
|
var xtend = require('xtend');
|
||||||
|
|
||||||
|
class TSCompiler extends Writer {
|
||||||
|
constructor(private inputTree, private options = {}) { super(inputTree, options); }
|
||||||
|
|
||||||
|
write(readTree, destDir) {
|
||||||
|
var options: ts.CompilerOptions = xtend({outDir: destDir}, this.options);
|
||||||
|
if (this.options.outDir) {
|
||||||
|
options.outDir = path.resolve(destDir, options.outDir);
|
||||||
|
}
|
||||||
|
if (options.out) {
|
||||||
|
options.out = path.resolve(destDir, options.out);
|
||||||
|
}
|
||||||
|
options.target = ts.ScriptTarget[options.target];
|
||||||
|
return readTree(this.inputTree)
|
||||||
|
.then(srcDir => {
|
||||||
|
var files = walkSync(srcDir)
|
||||||
|
.filter(filepath => path.extname(filepath).toLowerCase() === '.ts')
|
||||||
|
.map(filepath => path.resolve(srcDir, filepath));
|
||||||
|
|
||||||
|
if (files.length > 0) {
|
||||||
|
var program = ts.createProgram(files, options);
|
||||||
|
var emitResult = program.emit();
|
||||||
|
|
||||||
|
var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
|
||||||
|
|
||||||
|
var errMsg = '';
|
||||||
|
allDiagnostics.forEach(diagnostic => {
|
||||||
|
var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||||
|
if (!diagnostic.file) {
|
||||||
|
errMsg += `\n${message}`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var {line, character} =
|
||||||
|
diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
||||||
|
errMsg += `\n${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (emitResult.emitSkipped) {
|
||||||
|
throw new Error(errMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.exports = TSCompiler;
|
Loading…
x
Reference in New Issue
Block a user