Files
handlebars.js/lib/precompiler.js
T
kpdecker e3d3eda2e1 Add full support for es6
Converts the tool chain to use babel, eslint, and webpack vs. the previous proprietary solutions.

Additionally begins enforcing additional linting concerns as well as updates the code to reflect these rules.

Fixes #855
Fixes #993
2015-04-16 16:43:01 -05:00

181 lines
5.2 KiB
JavaScript

/*eslint-disable no-console */
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) {
if (opts.version) {
console.log(Handlebars.VERSION);
return;
}
if (!opts.templates.length) {
throw new Handlebars.Exception('Must define at least one template or directory.');
}
opts.templates.forEach(function(template) {
try {
fs.statSync(template);
} catch (err) {
throw new Handlebars.Exception('Unable to open template file "' + template + '"');
}
});
if (opts.simple && opts.min) {
throw new Handlebars.Exception('Unable to minimize simple output');
}
if (opts.simple && (opts.templates.length !== 1 || fs.statSync(opts.templates[0]).isDirectory())) {
throw new Handlebars.Exception('Unable to output multiple templates in simple mode');
}
// Convert the known list into a hash
var known = {};
if (opts.known && !Array.isArray(opts.known)) {
opts.known = [opts.known];
}
if (opts.known) {
for (var i = 0, len = opts.known.length; i < len; i++) {
known[opts.known[i]] = true;
}
}
// Build file extension pattern
var extension = opts.extension.replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function(arg) { return '\\' + arg; });
extension = new RegExp('\\.' + extension + '$');
var output = new SourceNode();
if (!opts.simple) {
if (opts.amd) {
output.add('define([\'' + opts.handlebarPath + 'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];');
} else if (opts.commonjs) {
output.add('var Handlebars = require("' + opts.commonjs + '");');
} else {
output.add('(function() {\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,
stat = fs.statSync(path);
if (stat.isDirectory()) {
fs.readdirSync(template).map(function(file) {
var childPath = template + '/' + file;
if (extension.test(childPath) || fs.statSync(childPath).isDirectory()) {
processTemplate(childPath, root || template);
}
});
} else {
var data = fs.readFileSync(path, 'utf8');
if (opts.bom && data.indexOf('\uFEFF') === 0) {
data = data.substring(1);
}
var options = {
knownHelpers: known,
knownHelpersOnly: opts.o
};
if (opts.map) {
options.srcName = path;
}
if (opts.data) {
options.data = true;
}
// Clean the template name
if (!root) {
template = basename(template);
} else if (template.indexOf(root) === 0) {
template = template.substring(root.length + 1);
}
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.add([precompiled, '\n']);
} else if (opts.partial) {
if (opts.amd && (opts.templates.length == 1 && !fs.statSync(opts.templates[0]).isDirectory())) {
output.add('return ');
}
output.add(['Handlebars.partials[\'', template, '\'] = template(', precompiled, ');\n']);
} else {
if (opts.amd && (opts.templates.length == 1 && !fs.statSync(opts.templates[0]).isDirectory())) {
output.add('return ');
}
output.add(['templates[\'', template, '\'] = template(', precompiled, ');\n']);
}
}
}
opts.templates.forEach(function(template) {
processTemplate(template, opts.root);
});
// Output the content
if (!opts.simple) {
if (opts.amd) {
if (opts.templates.length > 1 || (opts.templates.length == 1 && fs.statSync(opts.templates[0]).isDirectory())) {
if (opts.partial) {
output.add('return Handlebars.partials;\n');
} else {
output.add('return templates;\n');
}
}
output.add('});');
} else if (!opts.commonjs) {
output.add('})();');
}
}
if (opts.map) {
output.add('\n//# sourceMappingURL=' + opts.map + '\n');
}
output = output.toStringWithSourceMap();
output.map = output.map + '';
if (opts.min) {
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 {
console.log(output);
}
};