Created command line tooltags/v1.1.0
| @@ -461,6 +461,36 @@ These may be built using [Rake](http://rake.rubyforge.org/) and one of the follo | |||
| $ rake yui3 | |||
| $ rake qooxdoo | |||
| ## Command line tool | |||
| mustache.js is shipped with a node based command line tool. It might be installed as a global tool on your computer to render a mustache template of some kind | |||
| ```bash | |||
| $ npm install -g mustache | |||
| $ mustache dataView.json myTemplate.mustache > output.html | |||
| # also supports stdin | |||
| $ cat dataView.json | mustache - myTemplate.mustache > output.html | |||
| ``` | |||
| or as a package.json `devDependency` in a build process maybe? | |||
| ```bash | |||
| $ npm install mustache --save-dev | |||
| ``` | |||
| ```json | |||
| { | |||
| "scripts": { | |||
| "build": "mustache dataView.json myTemplate.mustache > public/output.html" | |||
| } | |||
| } | |||
| ``` | |||
| ```bash | |||
| $ npm run build | |||
| ``` | |||
| The command line tool is basically a wrapper around `Mustache.render` so you get all the aformentioned features. | |||
| ## Testing | |||
| In order to run the tests you'll need to install [node](http://nodejs.org/). | |||
| @@ -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'; | |||
| } | |||
| @@ -14,6 +14,9 @@ | |||
| "ejs" | |||
| ], | |||
| "main": "./mustache.js", | |||
| "bin": { | |||
| "mustache": "./bin/mustache" | |||
| }, | |||
| "volo": { | |||
| "url": "https://raw.github.com/janl/mustache.js/{version}/mustache.js" | |||
| }, | |||
| @@ -0,0 +1,3 @@ | |||
| { | |||
| "name": "LeBron" | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| Howdy {{name}}, CLI rox | |||
| @@ -0,0 +1 @@ | |||
| Howdy LeBron, CLI rox | |||
| @@ -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(); | |||
| }); | |||
| }); | |||
| }); | |||