UNPKG

3.18 kBPlain TextView Raw
1#!/usr/bin/env node
2
3var fs = require('fs'),
4 path = require('path');
5
6var Mustache = require('..');
7var pkg = require('../package');
8var partials = {};
9
10var partialsPaths = [];
11var partialArgIndex = -1;
12
13while ((partialArgIndex = process.argv.indexOf('-p')) > -1) {
14 partialsPaths.push(process.argv.splice(partialArgIndex, 2)[1]);
15}
16
17var viewArg = process.argv[2];
18var templateArg = process.argv[3];
19var outputArg = process.argv[4];
20
21if (hasVersionArg()) {
22 return console.log(pkg.version);
23}
24
25if (!templateArg || !viewArg) {
26 console.error('Syntax: mustache <view> <template> [output]');
27 process.exit(1);
28}
29
30run(readPartials, readView, readTemplate, render, toStdout);
31
32/**
33 * Runs a list of functions as a waterfall.
34 * Functions are runned one after the other in order, providing each
35 * function the returned values of all the previously invoked functions.
36 * Each function is expected to exit the process if an error occurs.
37 */
38function run (/*args*/) {
39 var values = [];
40 var fns = Array.prototype.slice.call(arguments);
41
42 function invokeNextFn (val) {
43 values.unshift(val);
44 if (fns.length === 0) return;
45 invoke(fns.shift());
46 }
47
48 function invoke (fn) {
49 fn.apply(null, [invokeNextFn].concat(values));
50 }
51
52 invoke(fns.shift());
53}
54
55function readView (cb) {
56 var view = isStdin(viewArg) ? process.openStdin() : fs.createReadStream(viewArg);
57
58 streamToStr(view, function onDone (str) {
59 cb(parseView(str));
60 });
61}
62
63function parseView (str) {
64 try {
65 return JSON.parse(str);
66 } catch (ex) {
67 console.error(
68 'Shooot, could not parse view as JSON.\n' +
69 'Tips: functions are not valid JSON and keys / values must be surround with double quotes.\n\n' +
70 ex.stack);
71
72 process.exit(1);
73 }
74}
75
76function readPartials (cb) {
77 if (!partialsPaths.length) return cb();
78 var partialPath = partialsPaths.pop();
79 var partial = fs.createReadStream(partialPath);
80 streamToStr(partial, function onDone (str) {
81 partials[getPartialName(partialPath)] = str;
82 readPartials(cb);
83 });
84}
85
86function readTemplate (cb) {
87 var template = fs.createReadStream(templateArg);
88 streamToStr(template, cb);
89}
90
91function render (cb, templateStr, jsonView) {
92 cb(Mustache.render(templateStr, jsonView, partials));
93}
94
95function toStdout (cb, str) {
96 if (outputArg) {
97 cb(fs.writeFileSync(outputArg, str));
98 } else {
99 cb(process.stdout.write(str));
100 }
101}
102
103function streamToStr (stream, cb) {
104 var data = '';
105
106 stream.on('data', function onData (chunk) {
107 data += chunk;
108 }).once('end', function onEnd () {
109 cb(data.toString());
110 }).on('error', function onError (err) {
111 if (wasNotFound(err)) {
112 console.error('Could not find file:', err.path);
113 } else {
114 console.error('Error while reading file:', err.message);
115 }
116 process.exit(1);
117 });
118}
119
120function isStdin (view) {
121 return view === '-';
122}
123
124function wasNotFound (err) {
125 return err.code && err.code === 'ENOENT';
126}
127
128function hasVersionArg () {
129 return ['--version', '-v'].some(function matchInArgs (opt) {
130 return process.argv.indexOf(opt) > -1;
131 });
132}
133
134function getPartialName (filename) {
135 return path.basename(filename, '.mustache');
136}