Permalink
Browse files

Initial commit.

  • Loading branch information...
0 parents commit 53670b7124adedb6dfe5ef543a93ad8c041c21b2 @evocateur evocateur committed Jul 3, 2012
@@ -0,0 +1,2 @@
+node_modules
+test/output
@@ -0,0 +1,67 @@
+
+module.exports = {
+ options: {
+ 'v': {
+ type: 'boolean',
+ description: 'Verbose logging',
+ alias: 'verbose'
+ },
+ 'd': {
+ type: 'string',
+ description: 'Output base directory',
+ alias: 'outputDir'
+ },
+ 'f': {
+ type: 'string',
+ description: 'Output File',
+ alias: 'outputFile'
+ },
+ 'p': {
+ type: 'string',
+ description: 'Module prefix',
+ alias: 'modulePrefix',
+ default: 'z-template'
+ },
+ 'k': {
+ type: 'string',
+ description: 'Known helpers',
+ alias: 'known'
+ },
+ 'o': {
+ type: 'boolean',
+ description: 'Known helpers only',
+ alias: 'knownOnly'
+ },
+ 'b': {
+ type: 'boolean',
+ description: 'Beautify output',
+ alias: 'beautify'
+ },
+ 'm': {
+ type: 'boolean',
+ description: 'Minimize output',
+ alias: 'min'
+ },
+ 's': {
+ type: 'boolean',
+ description: 'Output template function only',
+ alias: 'simple'
+ },
+ 'r': {
+ type: 'string',
+ description: 'Template root, stripped from template names.',
+ alias: 'root'
+ }
+ },
+ defaults: {
+ verbose: false,
+ outputDir: '',
+ outputFile: '',
+ known: '',
+ knownOnly: false,
+ beautify: false,
+ min: false,
+ simple: false,
+ root: ''
+ }
+};
@@ -0,0 +1,32 @@
+#!/usr/bin/env node
+
+var fs = require('fs'),
+ optimist = require('optimist')
+ .usage('Precompile handlebars templates.\nUsage: $0 template...')
+ .options(require('./argv').options)
+ .check(function (argv) {
+ if (!argv._.length) {
+ throw 'Must define at least one template or directory.';
+ }
+
+ argv._.forEach(function (template) {
+ try {
+ fs.statSync(template);
+ } catch (err) {
+ throw 'Unable to open template file "' + template + '"';
+ }
+ });
+ })
+ .check(function (argv) {
+ if (argv.beautify && argv.min) {
+ throw 'Unable to beautify minified output';
+ }
+ if (argv.simple && argv.min) {
+ throw 'Unable to minimize simple output';
+ }
+ if (argv.simple && (argv._.length !== 1 || fs.statSync(argv._[0]).isDirectory())) {
+ throw 'Unable to output multiple templates in simple mode';
+ }
+ });
+
+new (require('./mustachio'))(optimist.argv);
@@ -0,0 +1,211 @@
+/**
+ * Mustachio - Not just for Salvador, anymore!
+ */
+
+var fs = require('fs'),
+ path = require('path'),
+ mkdirp = require('mkdirp'),
+ uglify = require('uglify-js'),
+
+ Handlebars = require('yui/handlebars').Handlebars,
+
+ defaults = require('./argv').defaults;
+
+function Mustachio(argv) {
+ this.argv = merge(defaults, argv);
+
+ this.known = {};
+ this.output = [];
+ this.prefix = (this.argv.modulePrefix + '-').replace('--', '-');
+ this.pregex = new RegExp('"(' + this.prefix + '[\\w\\-]+)"');
+
+ if (this.argv.verbose) {
+ this.log = function () {
+ console.log.apply(null, arguments);
+ };
+ }
+
+ if (this.argv.min) {
+ this.render = function (ary) {
+ return uglify(ary.join('')) + ';\n';
+ };
+ }
+ else if (this.argv.beautify) {
+ this.render = function (ary) {
+ var code = ary.join(''),
+ ast = uglify.parser.parse(code);
+ // ast = uglify.uglify.ast_mangle(ast);
+ // ast = uglify.uglify.ast_squeeze(ast);
+ return uglify.uglify.gen_code(ast, {
+ beautify: true
+ }) + '\n';
+ };
+ }
+
+ // Convert the known list into a hash
+ if (this.argv.known && !Array.isArray(this.argv.known)) {
+ this.argv.known = [this.argv.known];
+ }
+ if (this.argv.known) {
+ var i = 0, len = this.argv.known.length;
+ for (; i < len; i++) {
+ this.known[this.argv.known[i]] = true;
+ }
+ }
+
+ if (argv._ && argv._.length) {
+ this.invoke(argv._);
+ }
+}
+
+Mustachio.prototype = {
+
+ log: function () {},
+
+ render: function (ary) {
+ return ary.join('');
+ },
+
+ invoke: function (templates) {
+ this.log("\nProcessing templates: " + templates + "\n#####################\n");
+
+ var self = this,
+ root = this.argv.root;
+
+ templates.forEach(function (template) {
+ self.processTemplate(template, root);
+ });
+
+ this.renderOutput();
+ },
+
+ processTemplate: function (template, root) {
+ var precompiled,
+ self = this,
+ extn = /\.(handlebars|mustache)$/,
+ tmpl = template,
+ stat = fs.statSync(tmpl);
+
+ if (stat.isDirectory()) {
+ fs.readdirSync(template).forEach(function (file) {
+ var path = template + '/' + file;
+
+ if (extn.test(path) || fs.statSync(path).isDirectory()) {
+ self.processTemplate(path, root || template);
+ }
+ });
+ }
+ else {
+ precompiled = Handlebars.precompile(fs.readFileSync(tmpl, 'utf8'), {
+ knownHelpers: this.known,
+ knownHelpersOnly: this.argv.o
+ });
+
+ if (this.argv.simple) {
+ this.output.push(precompiled + '\n');
+ }
+ else {
+ // Clean the template name
+ if (!root) {
+ template = path.basename(template);
+ } else if (template.indexOf(root) === 0) {
+ template = template.substring(root.length + 1);
+ }
+ template = template.replace(extn, '');
+ this.log(' raw template name: "' + template + '"');
+
+ this.output.push(this.wrapModule(template, precompiled));
+ }
+ }
+ },
+
+ wrapModule: function (templateName, precompiledFn) {
+ // replace slashes in templateName with dashes
+ templateName = templateName.replace(/\//g, '-');
+ this.log('module template name: "' + templateName + '"\n');
+
+ return [
+ 'YUI.add("' + this.prefix + templateName + '", function (Y) {\n',
+ ' Y.namespace("Z.Template")["' + templateName + '"] = Y.Handlebars.template(' + precompiledFn + ');\n',
+ '}, "@VERSION@", { "requires": ["handlebars-base"] });\n'
+ ];
+ },
+
+ renderOutput: function () {
+ var self = this,
+ output = self.output,
+ pregex = self.pregex,
+ render = self.render;
+
+ if (output.length) {
+ if (self.argv.outputDir) {
+ self.log("\nWriting module files: " + self.argv.outputDir + "\n#####################\n");
+
+ output.forEach(function (moduleData) {
+ // read out the generated module name from the module data
+ var moduleName = moduleData[0].match(pregex)[1],
+ modulePath = path.resolve(self.argv.outputDir + '/' + moduleName),
+ moduleFile = modulePath + '/' + moduleName + '.js';
+
+ self.log(' "' + moduleName + '"');
+ self.log(moduleData[0]);
+
+ mkdirp(modulePath, function (dirErr, made) {
+ if (dirErr) {
+ console.error(dirErr);
+ throw dirErr;
+ }
+
+ fs.writeFile(moduleFile, render(moduleData), 'utf8', function (fileErr) {
+ if (fileErr) {
+ console.error(fileErr);
+ throw fileErr;
+ }
+
+ console.log('Wrote ' + moduleFile);
+ });
+ });
+ });
+ } else if (self.argv.outputFile) {
+ fs.writeFileSync(self.argv.outputFile, render(output), 'utf8');
+ } else {
+ console.log(render(output));
+ }
+ }
+ }
+
+};
+
+module.exports = Mustachio;
+
+// mix & merge lifted from yui-base, simplified
+function mix(receiver, supplier, overwrite) {
+ var key;
+
+ if (!receiver || !supplier) {
+ return receiver || {};
+ }
+
+ for (key in supplier) {
+ if (supplier.hasOwnProperty(key)) {
+ if (overwrite || !receiver.hasOwnProperty(key)) {
+ receiver[key] = supplier[key];
+ }
+ }
+ }
+
+ return receiver;
+}
+
+function merge() {
+ var args = arguments,
+ i = 0,
+ len = args.length,
+ result = {};
+
+ for (; i < len; i += 1) {
+ mix(result, args[i], true);
+ }
+
+ return result;
+}
Oops, something went wrong.

0 comments on commit 53670b7

Please sign in to comment.