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();
+ });
+ });
+ })
});