diff --git a/README.md b/README.md index 63b775a..2233ab9 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,12 @@ $ npm run build The command line tool is basically a wrapper around `Mustache.render` so you get all the features. +If your templates use partials you should pass paths to partials using `-p` flag: + +```bash +$ mustache -p path/to/partial1.mustache -p path/to/partial2.mustache dataView.json myTemplate.mustache +``` + ## Who uses mustache.js? An updated list of mustache.js users is kept [on the Github wiki](http://wiki.github.com/janl/mustache.js/beard-competition). Add yourself or your company if you use mustache.js! diff --git a/bin/mustache b/bin/mustache index a88c9b4..730e79a 100755 --- a/bin/mustache +++ b/bin/mustache @@ -1,9 +1,18 @@ #!/usr/bin/env node -var fs = require('fs'); +var fs = require('fs'), + path = require('path'); var Mustache = require('..'); var pkg = require('../package'); +var partials = {}; + +var partialsPaths = []; +var partialArgIndex = -1; + +while((partialArgIndex = process.argv.indexOf("-p")) > -1){ + partialsPaths.push(process.argv.splice(partialArgIndex, 2)[1]); +} var viewArg = process.argv[2]; var templateArg = process.argv[3]; @@ -17,7 +26,7 @@ if (!templateArg || !viewArg) { process.exit(1); } -run(readView, readTemplate, render, toStdout); +run(readPartials, readView, readTemplate, render, toStdout); /** * Runs a list of functions as a waterfall. @@ -63,13 +72,23 @@ function parseView(str) { } } +function readPartials(cb) { + if(!partialsPaths.length) return cb(); + var partialPath = partialsPaths.pop(); + var partial = fs.createReadStream(partialPath); + streamToStr(partial, function(str) { + partials[getPartialName(partialPath)] = str; + readPartials(cb); + }); +} + function readTemplate(cb) { var template = fs.createReadStream(templateArg); streamToStr(template, cb); } function render(cb, templateStr, jsonView) { - cb(Mustache.render(templateStr, jsonView)); + cb(Mustache.render(templateStr, jsonView, partials)); } function toStdout(cb, str) { @@ -105,4 +124,8 @@ function hasVersionArg() { return ['--version', '-v'].some(function(opt) { return process.argv.indexOf(opt) > -1; }); -} \ No newline at end of file +} + +function getPartialName(filename) { + return path.basename(filename, '.mustache') +} diff --git a/test/_files/cli_with_partials.json b/test/_files/cli_with_partials.json new file mode 100644 index 0000000..c6af1c8 --- /dev/null +++ b/test/_files/cli_with_partials.json @@ -0,0 +1,14 @@ +{ "users": [ + { + "name": "LeBron" + }, + { + "name": "LeBron 2" + } + ], + "comments": [ + { + "title": "A Comedy of Errors" + } + ] +} \ No newline at end of file diff --git a/test/_files/cli_with_partials.mustache b/test/_files/cli_with_partials.mustache new file mode 100644 index 0000000..9c168d8 --- /dev/null +++ b/test/_files/cli_with_partials.mustache @@ -0,0 +1,7 @@ +{{#users}} +{{>cli}} +{{/users}} + +{{#comments}} +{{>comments}} +{{/comments}} \ No newline at end of file diff --git a/test/_files/cli_with_partials.txt b/test/_files/cli_with_partials.txt new file mode 100644 index 0000000..f582397 --- /dev/null +++ b/test/_files/cli_with_partials.txt @@ -0,0 +1,2 @@ +Howdy LeBron, CLI roxHowdy LeBron 2, CLI rox +

A Comedy of Errors

diff --git a/test/cli-test.js b/test/cli-test.js index 52cd7de..dd3ec30 100644 --- a/test/cli-test.js +++ b/test/cli-test.js @@ -4,6 +4,7 @@ var fs = require('fs'); var path = require('path'); var _files = path.join(__dirname, '_files'); var cliTxt = path.resolve(_files, 'cli.txt'); +var cliPartialsTxt = path.resolve(_files, 'cli_with_partials.txt'); var moduleVersion = require('../package').version; var exec = require('child_process').exec; @@ -12,15 +13,6 @@ 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); @@ -49,36 +41,76 @@ describe('Mustache CLI', function () { }); }); - 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(); + describe("without partials", function(){ + before(function(done) { + fs.readFile(cliTxt, function onFsEnd(err, data) { + if (err) return done(err); + + expectedOutput = data.toString(); + 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 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('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('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 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(); + 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(); + }); }); }); + + describe("with partials", function(){ + before(function(done) { + fs.readFile(cliPartialsTxt, function onFsEnd(err, data) { + if (err) return done(err); + + expectedOutput = data.toString(); + done(); + }); + }); + + it('writes rendered template with partials into stdout', function(done) { + exec('bin/mustache test/_files/cli_with_partials.json test/_files/cli_with_partials.mustache -p test/_files/cli.mustache -p test/_files/comments.mustache', function(err, stdout, stderr) { + assert.equal(err, null); + assert.equal(stderr, ''); + assert.equal(stdout, expectedOutput); + done(); + }); + }); + + it('writes rendered template with partials when partials args before required args', function(done) { + exec('bin/mustache -p test/_files/cli.mustache -p test/_files/comments.mustache test/_files/cli_with_partials.json test/_files/cli_with_partials.mustache', function(err, stdout, stderr) { + assert.equal(err, null); + assert.equal(stderr, ''); + assert.equal(stdout, expectedOutput); + done(); + }); + }); + }) });