-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #425 from phillipj/feature/cli
Created command line tool
- Loading branch information
Showing
7 changed files
with
197 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
#!/usr/bin/env node | ||
|
||
var fs = require('fs'); | ||
|
||
var Mustache = require('..'); | ||
var pkg = require('../package'); | ||
|
||
var viewArg = process.argv[2]; | ||
var templateArg = process.argv[3]; | ||
|
||
if (process.argv.indexOf('--version') > -1) { | ||
return console.log(pkg.version); | ||
} | ||
|
||
if (!templateArg || !viewArg) { | ||
console.error('Syntax: mustache <view> <template>'); | ||
process.exit(1); | ||
} | ||
|
||
run(readView, readTemplate, render, toStdout); | ||
|
||
/** | ||
* Runs a list of functions as a waterfall. | ||
* Functions are runned one after the other in order, providing each | ||
* function the returned values of all the previously invoked functions. | ||
* Each function is expected to exit the process if an error occurs. | ||
*/ | ||
function run(/*args*/) { | ||
var values = []; | ||
var fns = Array.prototype.slice.call(arguments); | ||
|
||
function invokeNextFn(val) { | ||
values.unshift(val); | ||
if (fns.length == 0) return; | ||
invoke(fns.shift()); | ||
} | ||
|
||
function invoke(fn) { | ||
fn.apply(null, [invokeNextFn].concat(values)); | ||
} | ||
|
||
invoke(fns.shift()); | ||
} | ||
|
||
function readView(cb) { | ||
var view = isStdin(viewArg) ? process.openStdin() : fs.createReadStream(viewArg); | ||
|
||
streamToStr(view, function(str) { | ||
cb(JSON.parse(str)); | ||
}); | ||
} | ||
|
||
function readTemplate(cb) { | ||
var template = fs.createReadStream(templateArg); | ||
streamToStr(template, cb); | ||
} | ||
|
||
function render(cb, templateStr, jsonView) { | ||
cb(Mustache.render(templateStr, jsonView)); | ||
} | ||
|
||
function toStdout(cb, str) { | ||
cb(process.stdout.write(str)); | ||
} | ||
|
||
function streamToStr(stream, cb) { | ||
var data = ''; | ||
|
||
stream.on('data', function(chunk) { | ||
data += chunk; | ||
}).once('end', function() { | ||
cb(data.toString()); | ||
}).on('error', function(err) { | ||
if (wasNotFound(err)) { | ||
console.error('Could not find file:', err.path); | ||
} else { | ||
console.error('Error while reading file:', err.message); | ||
} | ||
process.exit(1); | ||
}); | ||
} | ||
|
||
function isStdin(viewArg) { | ||
return viewArg === '-'; | ||
} | ||
|
||
function wasNotFound(err) { | ||
return err.code && err.code === 'ENOENT'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"name": "LeBron" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Howdy {{name}}, CLI rox |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Howdy LeBron, CLI rox |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
require('./helper'); | ||
|
||
var fs = require('fs'); | ||
var path = require('path'); | ||
var _files = path.join(__dirname, '_files'); | ||
var cliTxt = path.resolve(_files, 'cli.txt'); | ||
var moduleVersion = require('../package').version; | ||
|
||
var exec = require('child_process').exec; | ||
|
||
describe('Mustache CLI', function () { | ||
|
||
var expectedOutput; | ||
|
||
before(function(done) { | ||
fs.readFile(cliTxt, function onFsEnd(err, data) { | ||
if (err) return done(err); | ||
|
||
expectedOutput = data.toString(); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('writes syntax hints into stderr when runned with wrong number of arguments', function(done) { | ||
exec('bin/mustache', function(err, stdout, stderr) { | ||
assert.notEqual(stderr.indexOf('Syntax'), -1); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('writes module version into stdout when runned with --version', function(done){ | ||
exec('bin/mustache --version', function(err, stdout, stderr) { | ||
assert.notEqual(stdout.indexOf(moduleVersion), -1); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('writes rendered template into stdout when successfull', function(done) { | ||
exec('bin/mustache test/_files/cli.json test/_files/cli.mustache', function(err, stdout, stderr) { | ||
assert.equal(err, null); | ||
assert.equal(stderr, ''); | ||
assert.equal(stdout, expectedOutput); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('reads view data from stdin when first argument equals "-"', function(done){ | ||
exec('cat test/_files/cli.json | bin/mustache - test/_files/cli.mustache', function(err, stdout, stderr) { | ||
assert.equal(err, null); | ||
assert.equal(stderr, ''); | ||
assert.equal(stdout, expectedOutput); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('writes it couldnt find template into stderr when second argument doesnt resolve to a file', function(done) { | ||
exec('bin/mustache test/_files/cli.json test/_files/non-existing-template.mustache', function(err, stdout, stderr) { | ||
assert.notEqual(stderr.indexOf('Could not find file: test/_files/non-existing-template.mustache'), -1); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('writes it couldnt find view into stderr when first argument doesnt resolve to a file', function(done) { | ||
exec('bin/mustache test/_files/non-existing-view.json test/_files/cli.mustache', function(err, stdout, stderr) { | ||
assert.notEqual(stderr.indexOf('Could not find file: test/_files/non-existing-view.json'), -1); | ||
done(); | ||
}); | ||
}); | ||
|
||
}); |