UNPKG

grunt-template-module

Version:

Precompile templates to a file with option to expose templates as a node/commonjs module.

175 lines (156 loc) 5.42 kB
'use strict'; /** * @fileOverview This is a grunt task to precompile JST files with the option to * expose the result into module.exports rather than a namespace. * This has been forked and modified from grunt-contrib-jst and * differs slightly. It retains all of the options of the * original, but adds a new one called <code>module</code>. This * is like the amdWrapper option, except it will create * exports[filename] = templateCode() instead so that if you use * browserify to package your code, or if you just want to call it * from the server. And this one uses lodash. So there. * * @module tasks\grunt-jst-module * @see http://gruntjs.com/ * @see https://github.com/gruntjs/grunt-contrib-jst * @copyright Copyright &copy; 2012 Terry Weiss, Tim Branyen, grunt-contrib contributers. All rights reserved. * @license MIT. */ /** * Figures out what the full namespace declaration looks like when rendered. * * @param {string} ns The namespace specification * @return {Object} And object with two components: <code>namespace</code> - the namespace specification and * <code>declaration</code>: the component declarations to make sure the namespace is valid at runtime. */ var getNamespaceDeclaration = function ( ns ) { var output = []; var curPath = 'this'; if ( ns !== 'this' ) { var nsParts = ns.split( '.' ); nsParts.forEach( function ( curPart ) { if ( curPart !== 'this' ) { curPath += '[' + JSON.stringify( curPart ) + ']'; output.push( curPath + ' = ' + curPath + ' || {};' ); } } ); } return { namespace : curPath, declaration : output.join( '\n' ) }; }; /** * The task itself * @param {Grunt} grunt The grunt object */ module.exports = function ( grunt ) { var path = require( "path" ); grunt.registerMultiTask( 'template-module', 'Compile underscore templates to JST file that can be exposed as a module', function () { var sys = require( "lodash" ); var beautifier = require( "node-beautify" ); var defaultOptions = { namespace : null, templateSettings : { client : true, compileDebug : true }, lintExpr : { // unused : false, asi : true, expr : true }, module : true, requireProvider : true, provider : "underscore", processName : function ( name ) { return name; }, useStrict : false, single : false, prettify : false, prettifyOptions : { indentSize : 2 } }; var options = sys.extend( {}, defaultOptions, this.options() ); var templateProvider = require( options.provider ); grunt.verbose.writeflags( options, 'Options' ); var nsInfo; // we want to turn module off in the event other setting would collide with it if ( options.amdWrapper || !sys.isEmpty( options.namespace ) ) { options.module = false; } if ( options.module ) { options.amdWrapper = false; nsInfo = { namespace : "exports", declaration : "" }; } else { options.module = false; options.requireProvider = false; options.namespace = options.namespace || "JST"; nsInfo = getNamespaceDeclaration( options.namespace ); } var output = []; var compiled, templateName; var oneSource = (this.files.length === 1); this.files.forEach( function ( f ) { sys.each( f.src, function ( srcFile ) { var fpath; if ( f.cwd ) { fpath = path.resolve( f.cwd, srcFile ); } else { fpath = srcFile; } var src = grunt.file.read( fpath ); try { if ( options.provider === "ejs" ) { options.templateSettings.filename = fpath; compiled = templateProvider.compile( src, options.templateSettings ); } else { compiled = templateProvider.template( src, false, options.templateSettings ).source; } if ( options.single === true && options.module === true && oneSource ) { output.push( "module.exports = " + compiled + ";" ); } else { templateName = options.processName( srcFile ); output.push( nsInfo.namespace + "[" + JSON.stringify( templateName ) + "] = " + compiled + ";" ); } } catch ( e ) { grunt.log.error( e ); grunt.fail.warn( "file failed to compile." ); } } ); if ( output.length > 0 ) { if ( !sys.isEmpty( nsInfo.declaration ) ) { output.unshift( nsInfo.declaration ); } if ( options.amdWrapper ) { var amdDefine = typeof options.amdWrapper === "string" ? options.amdWrapper : "define(function(){"; output.unshift( amdDefine ); output.push( " return " + nsInfo.namespace + ";\n});" ); } else if ( options.requireProvider ) { output.unshift( ["var _ = require('" + options.provider + "');"] ); } if ( options.lintExpr && !sys.isEmpty( options.lintExpr ) ) { var lintlines = sys.map( options.lintExpr, function ( v, k ) { return k + ", " + v; } ); output.push( "\n jshint " + lintlines.join( " " ) ); } if ( options.useStrict ) { output.unshift( '"use strict;"\n' ); } var contents = output.join( "\n" ); if ( options.prettify ) { contents = beautifier.beautifyJs( contents, options.prettifyOptions ); } grunt.file.write( f.dest, contents ); grunt.log.writeln( "File '" + f.dest + "' created." ); } } ); } ); };