Skip to content
This repository has been archived by the owner on May 28, 2020. It is now read-only.

lzilioli/template-export

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

64 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

template-export

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:

  1. initialization
  2. 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
  3. return the result of (2)
  4. 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.

Usage

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');

Options

options.sourceFiles

-- see the Configuring the Task section above for an explanation of this argument

options.noExpand

If you pass this flag, sourceFiles will be used as passed in, without being expanded.

options.translator

options.translator.init
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 )
options.translator.translate
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

options.model

options.model.init
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 )
options.model.getModel
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

Extending the Default Translator

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 );
        }
    };
};

Changelog

  • v0.2.6 -- sourceFiles.templates and sourceFiles.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

About

Export and hydrate your files in style.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages