Want to use this with grunt? There's a grunt task that wraps this module.
A module, in MVC terms, a controller that acts as a near-transparent liason between a model and a view (referred to as a translator within this project). It enables the simple, yet highly custom exporting of templates (or other content) to a given destination.
The template-export module has five primary concerns:
- initialization
- given a path to a file:
- fetch a model from a user-defined module
- pass the contents of the file, along with the model, through a user-defined translation module
- return the result of (2)
- enforce a light-handed, yet reasonable separation between the model and the translator
The magic is in the fact that the model fetching and translation are both handled by user-defined modules that simply need to expose a pre-determined API. As long as the modules follow this API, they can do anything they need to under-the-hood in order to generate the proper output. Specifying an implementation for either of these modules is optional.
npm install --save template-export
var handlebars = require( 'handlebars' );
var fs = require( 'fs' );
var templateExport = require( 'template-export' );
var exporter = templateExport.exporter({
/* NOTE: The opts argument passed to model.getModel, model.init,
* translator.init, and translator.translate will contain all of
* the options passed in except for the following 3
* reserved keys (explained below):
* [ sourceFiles | translator | model ] */
sourceFiles: {
/* Arg for [lz-node-utils.file.expandSourceFiles](http://github.com/lzilioli-lz-node-utils)
* The resulting object will then be passed to model.init and
* translator.init. Those functions may do with the object what they
* please.
*
* This might be used to pass a list of markdown files
* to your model, and a set of templates to your
* translator for proper rendering. It's all up
* to you.
*/
templates: [ 'templates/**/*.tmpl' ],
posts: [ 'blog/posts/**/*.md' ]
},
/* Below are the default implementations for a model and a
* translator. If you don't provide either in the task options,
* the default implementation will be used. Additionally,
* if the model or translator that you provide omits one
* of the expected functions, the task will fall back on the
* implementations provided below for that function only. */
model: {
init: _.noop,
getModel: function() { return { }; }
},
translator: {
init: _.noop,
translate: _.identity
// _.identity is a fn that returns it's first arg
}
});
/* The call to exporter returns a function that takes a path to a template,
* and a options object. It will return the rendered version of the template
* according to the translator, using the model returned by your model's
* getModel function. */
/****** EXAMPLES ************************************/
// Get the rendered homepage, specified by src/templates/index.tmpl
var homepageExporter = templateExport({
sourceFiles: {
templates: [ 'templates/**/*.tmpl' ]
},
/* A default handlebars translator is provided. This
* translator will automatically register all of the
* templates specified in options.templates that pass
* the isPartial test with handlebars with the name
* returned by getPartialName.
*
* During translation, your template will be run through
* handlebars with the designated partials registered.
*
* See the below "Extending the Default Translator" section
* for an example on inheriting some of the default handlebars
* translator's functionality. */
translator: templateExport.translators.handlebars(
/* You must pass handlebars as your first argument
* (see v0.0.2 commit for v0.0.2 for an explanation) */
handlebars.create(),
/* The second argument is optional. It allows you to
* specify functions to determine if a template
* should be considered a partial (isPartial), and if so,
* what name to register with handlebars (getPartialName)
* If either is omitted, the default implementations
* (shown below) will be used. */
{
getPartialName: function( partialPath ) {
// The relative path of the partial from sourceDir, without the .tmpl extension
return partialPath.replace( '.tmpl', '' );
},
isPartial: function( filePath ) {
// Something is considered a partial if the filename begins with `_`
return path.basename( filePath )[ 0 ] === '_';
}
}
),
/* Use a static model */
model: {
getModel: function(){ fs.readFileSync( 'static-models/home.json' ) }
}
});
var homepageContents = homepageExporter('src/templates/index.tmpl');
-- see the Configuring the Task section above for an explanation of this argument
If you pass this flag, sourceFiles will be used as passed in, without being expanded.
function( sourceFiles, opts )
- return -- none
- sourceFiles -- see the Configuring the Task section above for an explanation of this argument
- opts -- all options passed to the task except ( translator, model, sourceFiles )
function( templateContents, model, opts, templatePath )
- return -- string
- templateContents -- the contents of the template being translated
- model
-- the model as returned by
options.model.getModel()
- opts -- all options passed to the task except ( translator, model, templates )
- templatePath -- the path to the source template containing templateContents
function( sourceFiles, opts )
- return -- none
- sourceFiles -- see the Configuring the Task section above for an explanation of this argument
- opts -- all options passed to the task except ( translator, model, templates )
function( opts, templatePath, templateContents )
- return -- Object
- opts -- all options passed to the task except ( translator, model, templates )
- templatePath -- the path to the source template containing templateContents
- templateContents -- the contents of the template being translated
- theTemplates
-- list of template files as passed to
options.templates
Say you want to register a set of helper functions with handlebars to make available during the export step. You can define the following translator, and pass it in the options to template-export.
var _ = require( 'underscore' );
var handlebars = require( 'handlebars' );
var defaultTranslators = require( 'template-export' ).translators;
module.exports = function( translatorToUse, helperOverrides ) {
var __parent = defaultTranslators.handlebars(handlebars, helperOverrides);
var helpers = {
siteUrl: function( siteDest ) {
return 'http://www.example.com/' + siteDest
}
};
return {
init: function() {
// register some additional helpers
handlebars.registerHelper( helpers );
__parent.init.apply( this, arguments );
},
translate: function() {
return __parent.translate.apply( this, arguments );
}
};
};
- v0.2.6
--
sourceFiles.templates
andsourceFiles.tmpl
checked in the handlebars translator before throwing an error - v0.2.5 -- Revert previous change. This is breaking, but 0.2.4 is no longer published.
- v0.2.4 -- allow model argument to export function to bypass the model
- v0.2.3 -- options.noExpand to allow for passing of already expanded file list
- v0.2.2 -- rely on util.expandSourceFiles for expansion of sourceFiles argument
- v0.2.1 -- fix to allow specification of sourceFiles without the string being an array
- v0.2.0 -- change the way in which sourceFiles is specified to make it easier to deal with fully qualified paths
- v0.1.2 -- translator-handlebars strips YAML front matter from template contents prior to passing to handlebars
- v0.1.3 -- use lz-node-utils package from npm
- v0.1.4 -- correctly require yaml dependency