- Notifications
You must be signed in to change notification settings - Fork77
lazd/gulp-handlebars
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Handlebars plugin for gulp
Installgulp-handlebars
as a development dependency:
npm install --save-dev gulp-handlebars
Are you seeing this error when using pre-compliled templates?
Error: Template was precompiled with an older version of Handlebars
If you're getting a version mismatch error when using pre-compliled templates,install the handlebars version of your choice and pass it asoptions.handlebars
, then include the appropriate runtime in your client-side application.
Here's how you install your own version of handlebars:
npm install --save handlebars@^4.0.0
And here's how you use that verison of handlebars ingulp-handlebars
:
handlebars({handlebars:require('handlebars')})
The runtime is located in:
node_modules/handlebars/dist/handlebars.js
gulp-declare
andgulp-wrap
can be used to safely declare template namespaces and make templates available for use in the browser.
First, install development dependencies:
npm install --save-dev gulp-handlebars gulp-wrap gulp-declare gulp-concat
Given the following directory structure:
├── gulpfile.js # Your gulpfile└── source/ # Your application's source files └── templates/ # A folder containing templates named with dot notation └── home.header.hbs # A template that will be available as MyApp.templates.home.header
To compile all templates insource/templates/
tobuild/js/templates.js
under theMyApp.templates
namespace:
varhandlebars=require('gulp-handlebars');varwrap=require('gulp-wrap');vardeclare=require('gulp-declare');varconcat=require('gulp-concat');gulp.task('templates',function(){gulp.src('source/templates/*.hbs').pipe(handlebars()).pipe(wrap('Handlebars.template(<%= contents %>)')).pipe(declare({namespace:'MyApp.templates',noRedeclare:true,// Avoid duplicate declarations})).pipe(concat('templates.js')).pipe(gulp.dest('build/js/'));});
The template's filename is combined with the namespace, so the resultingbuild/js/templates.js
would look like:
this["MyApp"]=this["MyApp"]||{};this["MyApp"]["templates"]=this["MyApp"]["templates"]||{};this["MyApp"]["templates"]["home"]=this["MyApp"]["templates"]["home"]||{};this["MyApp"]["templates"]["home"]["header"]=Handlebars.template(function(){/* compiled template function */});
See thenamespaceByDirectory example if you'd like to compile templates with a mapping that looks like this:
File path | Namespace path |
---|---|
source/templates/App.hbs | MyApp.templates.App |
source/templates/App/header.hbs | MyApp.templates.App.header |
source/templates/App/footer.hbs | MyApp.templates.App.footer |
source/templates/Other.item.hbs | MyApp.templates.Other.item |
See thegulp-define-module
documentation for details on how to define templates as AMD, Node, CommonJS, and hybrid modules.
See theamd example for a full example of compiling templates to AMD modules.
gulp-handlebars
makes the following available for use ingulp-define-module
'swrapper
template option:
<%= handlebars %>
- The Handlebars template, wrapped in a call toHandlebars.template()
<%= contents %>
- The bare Handlebars template (not wrapped).
gulp-handlebars
also sets a defaultoptions.require
of{ Handlebars: 'handlebars' }
forgulp-define-module
so Handlebars will be present in when defining AMD, Node, CommonJS, or hybrid modules. You can change this by passing a differentoptions.require
when you invokegulp-define-module
.
The following example will precompile and register partials for all.hbs
files insource/partials/
, then store the result asbuild/js/partials.js
;
varpath=require('path');vargulp=require('gulp');varwrap=require('gulp-wrap');varconcat=require('gulp-concat');varhandlebars=require('gulp-handlebars');gulp.task('partials',function(){// Assume all partials are in a folder such as source/partials/**/*.hbsgulp.src(['source/partials/**/*.hbs']).pipe(handlebars()).pipe(wrap('Handlebars.registerPartial(<%= processPartialName(file.relative) %>, Handlebars.template(<%= contents %>));',{},{imports:{processPartialName:function(fileName){// Strip the extension and the underscore// Escape the output with JSON.stringifyreturnJSON.stringify(path.basename(fileName,'.js'));}}})).pipe(concat('partials.js')).pipe(gulp.dest('build/js/'));});
See thepartials example for a full example that compiles partials and templates down to a single file.
You can use different versions of Handlebars by specifying the version in yourpackage.json
and passing it asoptions.handlebars
:
{"devDependencies": {"handlebars":"^1.3.0" }}
gulp.task('templates',function(){gulp.src('source/templates/*.hbs').pipe(handlebars({handlebars:require('handlebars')})).pipe(wrap('Handlebars.template(<%= contents %>)')).pipe(declare({namespace:'MyApp.templates',noRedeclare:true,// Avoid duplicate declarations})).pipe(concat('templates.js')).pipe(gulp.dest('build/js/'));});
The runtime you include on the client side MUST match the version you compile templates with. You cannot use the the 2.x runtime with 1.x templates. Thehandlebars1 example copies the runtime fromnode_modules/handlebars/dist/handlebars.runtime.js
and uses that on the client side. Follow a similar pattern in your application to keep the runtime up to date with the compiler.
This example will make templates available for loading viaNode's require:
varhandlebars=require('gulp-handlebars');vardefineModule=require('gulp-define-module');gulp.task('templates',function(){gulp.src(['templates/*.hbs']).pipe(handlebars()).pipe(defineModule('node')).pipe(gulp.dest('build/templates/'));});
Templates can then be used within Node as such:
varappTemplate=require('./build/templates/App.Header.js');varhtml=appTemplate(data);
See thesingleModule example if you'd like to have a single module that contains all of your templates that can be used like so:
vartemplates=require('./templates');varoutput=templates.App.header();
The example below removes any partial and replaces it with the textfoo
.
handlebars({processAST:function(ast){ast.statements.forEach(function(statement,i){if(statement.type==='partial'){ast.statements[i]={type:'content',string:'foo'};}});}})
See theember-htmlbars example for details
handlebars({handlebars:emberHandlebars,compiler:emberTemplateCompilerFunction})
Type:Object
Compiler options to pass toHandlebars.precompile()
.
Type:Function
A function which will be passed the parsed Handlebars Abstract Syntax Tree. You can modify the AST in place or return a new AST to change the source of the precompiled template.
Type:Object
Handlebars library to use for precompilation. By default, the latest stable version of Handlebars is used.
Type:Function
Custom compiler function. By default, the precompile method of the provided Handlebars module is used (seeoptions.handlebars).