summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/handlebars11
-rw-r--r--lib/precompiler.js76
-rw-r--r--package.json1
-rw-r--r--spec/precompiler.js46
4 files changed, 130 insertions, 4 deletions
diff --git a/bin/handlebars b/bin/handlebars
index bfe6680..7645adf 100755
--- a/bin/handlebars
+++ b/bin/handlebars
@@ -54,6 +54,16 @@ var optimist = require('optimist')
'description': 'Output template function only.',
'alias': 'simple'
},
+ 'N': {
+ 'type': 'string',
+ 'description': 'Name of passed string templates. Optional if running in a simple mode. Required when operating on multiple templates.',
+ 'alias': 'name'
+ },
+ 'i': {
+ 'type': 'string',
+ 'description': 'Generates a template from the passed CLI argument.\n"-" is treated as a special value and causes stdin to be read for the template value.',
+ 'alias': 'string'
+ },
'r': {
'type': 'string',
'description': 'Template root. Base value that will be stripped from template names.',
@@ -92,6 +102,7 @@ var optimist = require('optimist')
}
})
+ .wrap(120)
.check(function(argv) {
if (argv.version) {
return;
diff --git a/lib/precompiler.js b/lib/precompiler.js
index 12a5a1f..9f23ef6 100644
--- a/lib/precompiler.js
+++ b/lib/precompiler.js
@@ -7,12 +7,64 @@ import {SourceMapConsumer, SourceNode} from 'source-map';
import uglify from 'uglify-js';
module.exports.loadTemplates = function(opts, callback) {
+ loadStrings(opts, function(err, strings) {
+ if (err) {
+ callback(err);
+ } else {
+ loadFiles(opts, function(err, files) {
+ if (err) {
+ callback(err);
+ } else {
+ opts.templates = strings.concat(files);
+ callback(undefined, opts);
+ }
+ });
+ }
+ });
+};
+
+function loadStrings(opts, callback) {
+ let strings = arrayCast(opts.string),
+ names = arrayCast(opts.name);
+
+ if (names.length !== strings.length
+ && strings.length > 1) {
+ return callback(new Handlebars.Exception('Number of names did not match the number of string inputs'));
+ }
+
+ Async.map(strings, function(string, callback) {
+ if (string !== '-') {
+ callback(undefined, string);
+ } else {
+ // Load from stdin
+ let buffer = '';
+ process.stdin.setEncoding('utf8');
+
+ process.stdin.on('data', function(chunk) {
+ buffer += chunk;
+ });
+ process.stdin.on('end', function() {
+ callback(undefined, buffer);
+ });
+ }
+ },
+ function(err, strings) {
+ strings = strings.map((string, index) => ({
+ name: names[index],
+ path: names[index],
+ source: string
+ }));
+ callback(err, strings);
+ });
+}
+
+function loadFiles(opts, callback) {
// Build file extension pattern
let extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function(arg) { return '\\' + arg; });
extension = new RegExp('\\.' + extension + '$');
let ret = [],
- queue = opts.files.map((template) => ({template, root: opts.root}));
+ queue = (opts.files || []).map((template) => ({template, root: opts.root}));
Async.whilst(() => queue.length, function(callback) {
let {template: path, root} = queue.shift();
@@ -74,9 +126,7 @@ module.exports.loadTemplates = function(opts, callback) {
if (err) {
callback(err);
} else {
- opts.templates = ret;
-
- callback(undefined, opts);
+ callback(undefined, ret);
}
});
}
@@ -100,6 +150,12 @@ module.exports.cli = function(opts) {
throw new Handlebars.Exception('Unable to output multiple templates in simple mode');
}
+ // Force simple mode if we have only one template and it's unnamed.
+ if (!opts.amd && !opts.commonjs && opts.templates.length === 1
+ && !opts.templates[0].name) {
+ opts.simple = true;
+ }
+
// Convert the known list into a hash
let known = {};
if (opts.known && !Array.isArray(opts.known)) {
@@ -156,6 +212,10 @@ module.exports.cli = function(opts) {
if (opts.simple) {
output.add([precompiled, '\n']);
} else {
+ if (!template.name) {
+ throw new Handlebars.Exception('Name missing for template');
+ }
+
if (opts.amd && !multiple) {
output.add('return ');
}
@@ -206,3 +266,11 @@ module.exports.cli = function(opts) {
console.log(output);
}
};
+
+function arrayCast(value) {
+ value = value != null ? value : [];
+ if (!Array.isArray(value)) {
+ value = [value];
+ }
+ return value;
+}
diff --git a/package.json b/package.json
index b1cafee..8548cd8 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
"jison": "~0.3.0",
"keen.io": "0.0.3",
"mocha": "~1.20.0",
+ "mock-stdin": "^0.3.0",
"mustache": "0.x",
"semver": "^4.0.0",
"underscore": "^1.5.1"
diff --git a/spec/precompiler.js b/spec/precompiler.js
index 25c57a8..e1ad5ad 100644
--- a/spec/precompiler.js
+++ b/spec/precompiler.js
@@ -71,6 +71,11 @@ describe('precompiler', function() {
Precompiler.cli({templates: [__dirname + '/artifacts/empty.handlebars', __dirname + '/artifacts/empty.handlebars'], simple: true});
}, Handlebars.Exception, 'Unable to output multiple templates in simple mode');
});
+ it('should throw when missing name', function() {
+ shouldThrow(function() {
+ Precompiler.cli({templates: [{source: ''}], amd: true});
+ }, Handlebars.Exception, 'Name missing for template');
+ });
it('should throw when combining simple and directories', function() {
shouldThrow(function() {
Precompiler.cli({hasDirectory: true, templates: [1], simple: true});
@@ -82,6 +87,11 @@ describe('precompiler', function() {
Precompiler.cli({templates: [emptyTemplate], simple: true});
equal(log, 'simple\n');
});
+ it('should default to simple templates', function() {
+ Handlebars.precompile = function() { return 'simple'; };
+ Precompiler.cli({templates: [{source: ''}]});
+ equal(log, 'simple\n');
+ });
it('should output amd templates', function() {
Handlebars.precompile = function() { return 'amd'; };
Precompiler.cli({templates: [emptyTemplate], amd: true});
@@ -197,6 +207,42 @@ describe('precompiler', function() {
});
});
+ it('should accept string inputs', function(done) {
+ var opts = {string: ''};
+ Precompiler.loadTemplates(opts, function(err, opts) {
+ equal(opts.templates[0].name, undefined);
+ equal(opts.templates[0].source, '');
+ done(err);
+ });
+ });
+ it('should accept string array inputs', function(done) {
+ var opts = {string: ['', 'bar'], name: ['beep', 'boop']};
+ Precompiler.loadTemplates(opts, function(err, opts) {
+ equal(opts.templates[0].name, 'beep');
+ equal(opts.templates[0].source, '');
+ equal(opts.templates[1].name, 'boop');
+ equal(opts.templates[1].source, 'bar');
+ done(err);
+ });
+ });
+ it('should accept stdin input', function(done) {
+ var stdin = require('mock-stdin').stdin();
+ Precompiler.loadTemplates({string: '-'}, function(err, opts) {
+ equal(opts.templates[0].source, 'foo');
+ done(err);
+ });
+ stdin.send('fo');
+ stdin.send('o');
+ stdin.end();
+ });
+ it('error on name missing', function(done) {
+ var opts = {string: ['', 'bar']};
+ Precompiler.loadTemplates(opts, function(err) {
+ equal(err.message, 'Number of names did not match the number of string inputs');
+ done();
+ });
+ });
+
it('should complete when no args are passed', function(done) {
Precompiler.loadTemplates({}, function(err, opts) {
equal(opts.templates.length, 0);