Add source map output support to the CLI

This commit is contained in:
kpdecker
2014-11-08 17:03:14 -06:00
parent 3ee0682247
commit 0dbeeb4503
3 changed files with 76 additions and 21 deletions
+4
View File
@@ -7,6 +7,10 @@ var optimist = require('optimist')
'description': 'Output File',
'alias': 'output'
},
'map': {
'type': 'string',
'description': 'Source Map File'
},
'a': {
'type': 'boolean',
'description': 'Exports amd style (require.js)',
+57 -20
View File
@@ -2,6 +2,9 @@
var fs = require('fs'),
Handlebars = require('./index'),
basename = require('path').basename,
SourceMap = require('source-map'),
SourceMapConsumer = SourceMap.SourceMapConsumer,
SourceNode = SourceMap.SourceNode,
uglify = require('uglify-js');
module.exports.cli = function(opts) {
@@ -45,20 +48,23 @@ module.exports.cli = function(opts) {
var extension = opts.extension.replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function(arg) { return '\\' + arg; });
extension = new RegExp('\\.' + extension + '$');
var output = [];
var output = new SourceNode();
if (!opts.simple) {
if (opts.amd) {
output.push('define([\'' + opts.handlebarPath + 'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];');
output.add('define([\'' + opts.handlebarPath + 'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];');
} else if (opts.commonjs) {
output.push('var Handlebars = require("' + opts.commonjs + '");');
output.add('var Handlebars = require("' + opts.commonjs + '");');
} else {
output.push('(function() {\n');
output.add('(function() {\n');
}
output.push(' var template = Handlebars.template, templates = ');
output.push(opts.namespace);
output.push(' = ');
output.push(opts.namespace);
output.push(' || {};\n');
output.add(' var template = Handlebars.template, templates = ');
if (opts.namespace) {
output.add(opts.namespace);
output.add(' = ');
output.add(opts.namespace);
output.add(' || ');
}
output.add('{};\n');
}
function processTemplate(template, root) {
var path = template,
@@ -83,6 +89,9 @@ module.exports.cli = function(opts) {
knownHelpersOnly: opts.o
};
if (opts.map) {
options.srcName = path;
}
if (opts.data) {
options.data = true;
}
@@ -95,18 +104,26 @@ module.exports.cli = function(opts) {
}
template = template.replace(extension, '');
var precompiled = Handlebars.precompile(data, options);
// If we are generating a source map, we have to reconstruct the SourceNode object
if (opts.map) {
var consumer = new SourceMapConsumer(precompiled.map);
precompiled = SourceNode.fromStringWithSourceMap(precompiled.code, consumer);
}
if (opts.simple) {
output.push(Handlebars.precompile(data, options) + '\n');
output.add([precompiled, '\n']);
} else if (opts.partial) {
if(opts.amd && (opts.templates.length == 1 && !fs.statSync(opts.templates[0]).isDirectory())) {
output.push('return ');
output.add('return ');
}
output.push('Handlebars.partials[\'' + template + '\'] = template(' + Handlebars.precompile(data, options) + ');\n');
output.add(['Handlebars.partials[\'', template, '\'] = template(', precompiled, ');\n']);
} else {
if(opts.amd && (opts.templates.length == 1 && !fs.statSync(opts.templates[0]).isDirectory())) {
output.push('return ');
output.add('return ');
}
output.push('templates[\'' + template + '\'] = template(' + Handlebars.precompile(data, options) + ');\n');
output.add(['templates[\'', template, '\'] = template(', precompiled, ');\n']);
}
}
}
@@ -120,22 +137,42 @@ module.exports.cli = function(opts) {
if (opts.amd) {
if(opts.templates.length > 1 || (opts.templates.length == 1 && fs.statSync(opts.templates[0]).isDirectory())) {
if(opts.partial){
output.push('return Handlebars.partials;\n');
output.add('return Handlebars.partials;\n');
} else {
output.push('return templates;\n');
output.add('return templates;\n');
}
}
output.push('});');
output.add('});');
} else if (!opts.commonjs) {
output.push('})();');
output.add('})();');
}
}
output = output.join('');
if (opts.map) {
output.add('\n//# sourceMappingURL=' + opts.map + '\n');
}
output = output.toStringWithSourceMap();
output.map = output.map + '';
if (opts.min) {
output = uglify.minify(output, {fromString: true}).code;
output = uglify.minify(output.code, {
fromString: true,
outSourceMap: opts.map,
inSourceMap: JSON.parse(output.map)
});
if (opts.map) {
output.code += '\n//# sourceMappingURL=' + opts.map + '\n';
}
}
if (opts.map) {
fs.writeFileSync(opts.map, output.map, 'utf8');
}
output = output.code;
if (opts.output) {
fs.writeFileSync(opts.output, output, 'utf8');
} else {
+15 -1
View File
@@ -98,7 +98,8 @@ describe('precompiler', function() {
});
it('should output multiple amd', function() {
Handlebars.precompile = function() { return 'amd'; };
Precompiler.cli({templates: [__dirname + '/artifacts'], amd: true, extension: 'handlebars'});
Precompiler.cli({templates: [__dirname + '/artifacts'], amd: true, extension: 'handlebars', namespace: 'foo'});
equal(/templates = foo = foo \|\|/.test(log), true);
equal(/return templates/.test(log), true);
equal(/template\(amd\)/.test(log), true);
});
@@ -156,4 +157,17 @@ describe('precompiler', function() {
Precompiler.cli({templates: [__dirname + '/artifacts/empty.handlebars'], min: true, extension: 'handlebars'});
equal(log, 'min');
});
it('should output map', function() {
fs.writeFileSync = function(_file, _content) {
console.error(arguments);
file = _file;
content = _content;
};
Precompiler.cli({templates: [__dirname + '/artifacts/empty.handlebars'], map: 'foo.js.map', extension: 'handlebars'});
equal(file, 'foo.js.map');
equal(/sourceMappingURL=/.test(log), true);
});
});