#!/usr/bin/env node var optimist = require('optimist') .usage('Precompile handlebar templates.\nUsage: $0 template...', { 'f': { 'type': 'string', 'description': 'Output File', 'alias': 'output' }, 'a': { 'type': 'boolean', 'description': 'Exports amd style (require.js)', 'alias': 'amd' }, 'c': { 'type': 'string', 'description': 'Exports CommonJS style, path to Handlebars module', 'alias': 'commonjs', 'default': null }, 'h': { 'type': 'string', 'description': 'Path to handlebar.js (only valid for amd-style)', 'alias': 'handlebarPath', 'default': '' }, 'k': { 'type': 'string', 'description': 'Known helpers', 'alias': 'known' }, 'o': { 'type': 'boolean', 'description': 'Known helpers only', 'alias': 'knownOnly' }, 'm': { 'type': 'boolean', 'description': 'Minimize output', 'alias': 'min' }, 'n': { 'type': 'string', 'description': 'Template namespace', 'alias': 'namespace', 'default': 'Handlebars.templates' }, 's': { 'type': 'boolean', 'description': 'Output template function only.', 'alias': 'simple' }, 'r': { 'type': 'string', 'description': 'Template root. Base value that will be stripped from template names.', 'alias': 'root' }, 'p' : { 'type': 'boolean', 'description': 'Compiling a partial template', 'alias': 'partial' }, 'd' : { 'type': 'boolean', 'description': 'Include data when compiling', 'alias': 'data' }, 'e': { 'type': 'string', 'description': 'Template extension.', 'alias': 'extension', 'default': 'handlebars' } }) .check(function(argv) { var template = [0]; 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.simple && argv.min) { throw 'Unable to minimze simple output'; } if (argv.simple && (argv._.length !== 1 || fs.statSync(argv._[0]).isDirectory())) { throw 'Unable to output multiple templates in simple mode'; } }); var fs = require('fs'), handlebars = require('../lib/handlebars'), basename = require('path').basename, uglify = require('uglify-js'); var argv = optimist.argv, template = argv._[0]; // Convert the known list into a hash var known = {}; if (argv.known && !Array.isArray(argv.known)) { argv.known = [argv.known]; } if (argv.known) { for (var i = 0, len = argv.known.length; i < len; i++) { known[argv.known[i]] = true; } } // Build file extension pattern var extension = argv.extension.replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function(arg) { return '\\' + arg; }); extension = new RegExp('\\.' + extension + '$'); var output = []; if (!argv.simple) { if (argv.amd) { output.push('define([\'' + argv.handlebarPath + 'handlebars\'], function(Handlebars) {\n'); } else if (argv.commonjs) { output.push('var Handlebars = require("' + argv.commonjs + '");'); } else { output.push('(function() {\n'); } output.push(' var template = Handlebars.template, templates = '); output.push(argv.namespace); output.push(' = '); output.push(argv.namespace); output.push(' || {};\n'); } function processTemplate(template, root) { var path = template, stat = fs.statSync(path); if (stat.isDirectory()) { fs.readdirSync(template).map(function(file) { var path = template + '/' + file; if (extension.test(path) || fs.statSync(path).isDirectory()) { processTemplate(path, root || template); } }); } else { var data = fs.readFileSync(path, 'utf8'); var options = { knownHelpers: known, knownHelpersOnly: argv.o }; if (argv.data) { options.data = true; } // Clean the template name if (!root) { template = basename(template); } else if (template.indexOf(root) === 0) { template = template.substring(root.length+1); } template = template.replace(extension, ''); if (argv.simple) { output.push(handlebars.precompile(data, options) + '\n'); } else if (argv.partial) { if(argv.amd && argv._.length == 1){ output.push('return '); } output.push('Handlebars.partials[\'' + template + '\'] = template(' + handlebars.precompile(data, options) + ');\n'); } else { if(argv.amd && argv._.length == 1){ output.push('return '); } output.push('templates[\'' + template + '\'] = template(' + handlebars.precompile(data, options) + ');\n'); } } } argv._.forEach(function(template) { processTemplate(template, argv.root); }); // Output the content if (!argv.simple) { if (argv.amd) { if(argv._.length > 1){ if(argv.partial){ output.push('return Handlebars.partials;\n'); } else { output.push('return templates;\n'); } } output.push('});'); } else if (!argv.commonjs) { output.push('})();'); } } output = output.join(''); if (argv.min) { var ast = uglify.parser.parse(output); ast = uglify.uglify.ast_mangle(ast); ast = uglify.uglify.ast_squeeze(ast); output = uglify.uglify.gen_code(ast); } if (argv.output) { fs.writeFileSync(argv.output, output, 'utf8'); } else { console.log(output); }