Skip to content

Commit

Permalink
Add hulk support for node exports format
Browse files Browse the repository at this point in the history
Allow export of templates in node format, also supporting browserify/webpack processing

If we are creating a aggregated out put the export will expose a template map
like it is already doing to the global variable, but in this case we use
`module.export` and `global.` for browser interoperability.

If we are crearing one file per template it adds the template directly in the `module.exports`.
  • Loading branch information
rtfpessoa committed Apr 16, 2016
1 parent 7e340e9 commit eaf10f4
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 40 deletions.
101 changes: 66 additions & 35 deletions bin/hulk
Expand Up @@ -27,22 +27,22 @@ var hogan = require('../lib/hogan.js')
// locals
var specials = ['/', '.', '*', '+', '?', '|','(', ')', '[', ']', '{', '}', '\\']
, specialsRegExp = new RegExp('(\\' + specials.join('|\\') + ')', 'g')
, options = {
'namespace': String,
'outputdir': path,
'variable': String,
'wrapper': String,
'version': true,
'help': true
}
, shortHand = {
'n': ['--namespace'],
'o': ['--outputdir'],
'v': ['--variable'],
'w': ['--wrapper'],
'h': ['--help'],
'v': ['--version']
}
, options = {
'namespace': String,
'outputdir': path,
'variable': String,
'wrapper': String,
'version': true,
'help': true
}
, shortHand = {
'n': ['--namespace'],
'o': ['--outputdir'],
'v': ['--variable'],
'w': ['--wrapper'],
'h': ['--help'],
'v': ['--version']
}
, templates;


Expand All @@ -65,14 +65,14 @@ function cyan(text) {
// check for dirs and correct ext (<3 for windows)
function extractFiles(args) {
var usage = '\n' +
cyan('USAGE:') + ' hulk [--wrapper wrapper] [--outputdir outputdir] [--namespace namespace] [--variable variable] FILES\n\n' +
cyan('OPTIONS:') + ' [-w, --wrapper] :: wraps the template (i.e. amd)\n' +
' [-o, --outputdir] :: outputs the templates as individual files to a directory\n\n' +
' [-n, --namespace] :: prepend string to template names\n\n' +
' [-v, --variable] :: variable name for non-amd wrapper\n\n' +
cyan('EXAMPLE:') + ' hulk --wrapper amd ./templates/*.mustache\n\n' +
cyan('NOTE:') + ' hulk supports the "*" wildcard and allows you to target specific extensions too\n',
files = [];
cyan('USAGE:') + ' hulk [--wrapper wrapper] [--outputdir outputdir] [--namespace namespace] [--variable variable] FILES\n\n' +
cyan('OPTIONS:') + ' [-w, --wrapper] :: wraps the template (i.e. amd)\n' +
' [-o, --outputdir] :: outputs the templates as individual files to a directory\n\n' +
' [-n, --namespace] :: prepend string to template names\n\n' +
' [-v, --variable] :: variable name for non-amd wrapper\n\n' +
cyan('EXAMPLE:') + ' hulk --wrapper amd ./templates/*.mustache\n\n' +
cyan('NOTE:') + ' hulk supports the "*" wildcard and allows you to target specific extensions too\n',
files = [];

if (options.version) {
console.log(require('../package.json').version);
Expand Down Expand Up @@ -122,15 +122,50 @@ function wrap(file, name, openedFile) {
switch(options.wrapper) {
case "amd":
return 'define('+ (!options.outputdir ? '"' + path.join(path.dirname(file), name) + '", ' : '') + '[ "hogan.js" ], function(Hogan){ return new Hogan.Template(' + hogan.compile(openedFile, { asString: 1 }) + ');});';
case "node":
var globalObj = 'global.' + (options.variable || 'templates') + '["' + name + '"]';
var globalStmt = globalObj + ' = new Hogan.Template(' + hogan.compile(openedFile, { asString: 1 }) + ');';
var nodeOutput = globalStmt;

// if we have a template per file the export will expose the template directly
if (options.outputdir) {
nodeOutput = nodeOutput + '\n' + 'module.exports = ' + globalObj + ';';
}

return nodeOutput;
default:
return (options.variable || 'templates')
+ '["' + name + '"] = new Hogan.Template('
+ hogan.compile(openedFile, { asString: 1 })
return (options.variable || 'templates')
+ '["' + name + '"] = new Hogan.Template('
+ hogan.compile(openedFile, { asString: 1 })
+ ');';
}
}


function prepareOutput(content) {
var variableName = options.variable || 'templates';
switch (options.wrapper) {
case "amd":
return content;
case "node":
var nodeExport = '';

// if we have aggregated templates the export will expose the template map
if (!options.outputdir) {
nodeExport = 'module.exports = global.' + variableName + ';\n';
}

return '(function() {\n' +
'if (!!!global.' + variableName + ') global.' + variableName + ' = {};\n' +
content + '\n' +
nodeExport +
'})();';
default:
return 'if (!!!' + variableName + ') var ' + variableName + ' = {};\n' + content;
}
}


// write the directory
if (options.outputdir) {
mkderp.sync(options.outputdir);
Expand All @@ -139,7 +174,7 @@ if (options.outputdir) {

// Prepend namespace to template name
function namespace(name) {
return (options.namespace || '') + name;
return (options.namespace || '') + name;
}


Expand All @@ -152,9 +187,8 @@ templates = extractFiles(options.argv.remain)
openedFile = removeByteOrderMark(openedFile.trim());
openedFile = wrap(file, name, openedFile);
if (!options.outputdir) return openedFile;
var vn = options.variable || 'templates';
fs.writeFileSync(path.join(options.outputdir, name + '.js')
, 'if (!!!' + vn + ') var ' + vn + ' = {};\n' + openedFile);
, prepareOutput(openedFile));
})
.filter(function (t) {
return t;
Expand All @@ -163,8 +197,5 @@ templates = extractFiles(options.argv.remain)

// output templates
if (!templates.length || options.outputdir) process.exit(0);
if (!options.wrapper) {
var vn = options.variable || 'templates';
console.log('if (!!!' + vn + ') var ' + vn + ' = {};');
}
console.log(templates.join('\n'));

console.log(prepareOutput(templates.join('\n')));
47 changes: 42 additions & 5 deletions test/hulk.js
Expand Up @@ -27,12 +27,49 @@ exec('node bin/hulk --wrapper amd test/templates/*', function (error, stdout, st
eval(stdout);
});

// wrapper options: --outputdir
exec('node bin/hulk --outputdir dist/foo test/templates/*', function (error, stdout, stderr) {
// wrapper options: --wrapper node
exec('node bin/hulk --wrapper node test/templates/*', function (error, stdout, stderr) {
if (error) throw error;
assert(fs.existsSync('dist/foo'), 'dist/foo directory created');
assert(fs.existsSync('dist/foo/list.js'), 'dist/foo/list.js file created');
rimraf.sync('dist');
eval(stdout);
function test(templates) {
template = templates['list'];
assert(template, 'template named list is defined');
assert(typeof template == 'object', 'defined a templates.list object');
assert(typeof template.r == 'function', 'defined a templates.list.r function');
}
test(module.exports);
test(global.templates);
});

// wrapper options: --outputdir foo/dist
exec('node bin/hulk --outputdir foo/dist test/templates/*', function (error, stdout, stderr) {
if (error) throw error;
assert(fs.existsSync('foo/dist'), 'foo/dist directory created');
assert(fs.existsSync('foo/dist/list.js'), 'foo/dist/list.js file created');
rimraf.sync('foo');
});

// wrapper options: --outputdir bar/dist --wrapper node
exec('node bin/hulk --outputdir bar/dist --wrapper node test/templates/list.mustache', function (error, stdout, stderr) {
if (error) throw error;
assert(fs.existsSync('bar/dist'), 'bar/dist directory created');
assert(fs.existsSync('bar/dist/list.js'), 'bar/dist/list.js file created');

var template;
templateContents = fs.readFileSync('bar/dist/list.js', 'utf-8');
eval(templateContents);

template = module.exports;
assert(template, 'template named list is defined');
assert(typeof template == 'object', 'defined a templates.list object');
assert(typeof template.r == 'function', 'defined a templates.list.r function');

template = global.templates['list'];
assert(template, 'template named list is defined');
assert(typeof template == 'object', 'defined a templates.list object');
assert(typeof template.r == 'function', 'defined a templates.list.r function');

rimraf.sync('bar');
});

// templates wildcard
Expand Down

0 comments on commit eaf10f4

Please sign in to comment.