Skip to content

Commit

Permalink
Merge pull request #17 from wbyoung/handlebars-abstract-module-defini…
Browse files Browse the repository at this point in the history
…tion

Use gulp-define-module for module definition
  • Loading branch information
lazd committed Mar 13, 2014
2 parents a9b92dc + 65ee6b9 commit 6f68760
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 213 deletions.
72 changes: 51 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,62 @@
## Usage

First, install `gulp-handlebars` as a development dependency:
First, install `gulp-handlebars` and [`gulp-define-module`][gulp-define-module] as development dependencies:

```shell
npm install --save-dev gulp-handlebars
npm install --save-dev gulp-handlebars gulp-define-module
```

Then, add it to your `gulpfile.js`:

```javascript
var handlebars = require('gulp-handlebars');
var defineModule = require('gulp-define-module');

gulp.task('templates', function(){
gulp.src(['client/templates/*.hbs'])
.pipe(handlebars({
outputType: 'node'
}))
.pipe(handlebars())
.pipe(defineModule('node'))
.pipe(gulp.dest('build/templates/'));
});
```

gulp-handlebars outputs a raw handlebars function, so it is likely that you will want to use [gulp-define-module] to make the handlebars template available via a specific namespace or for use with a module system. The example above makes this template available for loading via [node's require](http://nodejs.org/api/globals.html#globals_require).

## Compiling to a namespace for the browser

[gulp-declare] can be used to compile templates for the browser. Just pipe the output of gulp-handlebars to gulp-declare:
[gulp-define-module] can also be used to make the template accessible via a namespace:

```javascript
var handlebars = require('gulp-handlebars');
var defineModule = require('gulp-define-module');
var concat = require('gulp-concat');

gulp.task('templates', function(){
gulp.src(['client/templates/*.hbs'])
.pipe(handlebars())
.pipe(defineModule('plain', {
wrapper: 'MyApp.templates['<%= name %>'] = <%= handlebars %>'
}))
.pipe(concat('templates.js'))
.pipe(gulp.dest('build/js/'));
});
```

The above example assumes that MyApp.templates will be defined before the `templates.js` script is included for use in the browser, and will make a file such as `example.hbs` available via `MyApp.templates.example`. See the [gulp-define-module] documentation for more details.

[gulp-declare] is another option that can be used to compile templates for the browser.

```javascript
var handlebars = require('gulp-handlebars');
var defineModule = require('gulp-define-module');
var declare = require('gulp-declare');
var concat = require('gulp-concat');

gulp.task('templates', function(){
gulp.src(['client/templates/*.hbs'])
.pipe(handlebars())
.pipe(defineModule('plain'))
.pipe(declare({
namespace: 'MyApp.templates'
}))
Expand All @@ -43,27 +67,31 @@ gulp.task('templates', function(){
});
```

This will result in a more robust building of the namespace. For a file, `App.Header.hbs`, the result would be:

## API
```javascript
this["MyApp"] = this["MyApp"] || {};
this["MyApp"]["templates"] = this["MyApp"]["templates"] || {};
this["MyApp"]["templates"]["App"] = this["MyApp"]["templates"]["App"] || {};
this["MyApp"]["templates"]["App"]["Header"] = Handlebars.template(function() { /* compiled handlebars template function */});
```

### handlebars(options)
The use of [gulp-define-module] was still needed in this example to get the `Handlebars.template` wrapper.


## Compiling to various module systems

#### options.outputType
Type: `String`
Default: `bare`
[gulp-define-module] can be used to prepare the output for use with common module systems such as AMD, Node, and CommonJS. Please see the documentation for more details on how to use that in a gulp chain.

The desired output type. One of the following:
gulp-handlebars makes the following available for use in the [define-module wrapper](https://github.com/wbyoung/gulp-define-module#optionswrapper):

* `node` - Produce Node modules
* `amd` - Produce AMD modules
* `commonjs` - Produce CommonJS modules
* `bare` - Return an unmolested function definition
- `handlebars`: The handlebars template fully wrapped (`Handlebars.template(<%= contents %>)`).

#### options.wrapped
Type: `Boolean`
Default: `false`
gulp-handlebars also sets a default [`require`](https://github.com/wbyoung/gulp-define-module#optionsrequire) of `{ Handlebars: 'handlebars' }` for [gulp-define-module].

Whether to wrap compiled template functions in a call to `Handlebars.template`.
## API

### handlebars(options)

#### options.compilerOptions
Type: `Object`
Expand All @@ -76,4 +104,6 @@ Compiler options to pass to `Handlebars.precompile()`.
[npm-url]: https://npmjs.org/package/gulp-handlebars
[npm-image]: https://badge.fury.io/js/gulp-handlebars.png

[gulp-declare]: https://github.com/lazd/gulp-declare
[gulp-define-module]: https://github.com/wbyoung/gulp-define-module
[gulp-handlebars]: https://github.com/lazd/gulp-handlebars
[gulp-declare]: https://github.com/lazd/gulp-declare
78 changes: 26 additions & 52 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,31 @@
var map = require('vinyl-map');
var es = require('event-stream');
var rename = require('gulp-rename');
var Handlebars = require('handlebars');
var extend = require('xtend');
'use strict';

var outputTypes = ['amd', 'commonjs', 'node', 'bare'];
var through = require('through');
var path = require('path');
var gutil = require('gulp-util');
var Handlebars = require('handlebars');

module.exports = function(options) {
options = extend({
compilerOptions: {},
wrapped: false,
outputType: 'bare' // amd, commonjs, node, bare
}, options);

if (outputTypes.indexOf(options.outputType) === -1) {
throw new Error('Invalid output type: '+options.outputType);
}

var compileHandlebars = function(contents, path) {
// Perform pre-compilation
// This will throw if errors are encountered
var compiled = Handlebars.precompile(contents.toString(), options.compilerOptions);

if (options.wrapped) {
compiled = 'Handlebars.template('+compiled+')';
}

// Handle different output times
if (options.outputType === 'amd') {
compiled = "define(['handlebars'], function(Handlebars) {return "+compiled+";});";
var opts = options || {};
var compilerOptions = opts.compilerOptions || {};
return through(function(file) {
if (file.isNull()) { return this.queue(file); } // pass along
if (file.isStream()) { return this.emit('error', new gutil.PluginError('gulp-handlebars', 'Streaming not supported')); }
var contents = file.contents.toString();
var compiled = null;
try { compiled = Handlebars.precompile(contents, compilerOptions).toString(); }
catch (err) { this.emit('error', err); }
if (compiled) {
file.contents = new Buffer(compiled);
file.path = gutil.replaceExtension(file.path, '.js');
file.defineModuleOptions = {
require: { Handlebars: 'handlebars' },
context: {
handlebars: 'Handlebars.template(<%= contents %>)'
},
wrapper: '<%= handlebars %>'
};
this.queue(file);
}
else if (options.outputType === 'commonjs') {
compiled = "module.exports = function(Handlebars) {return "+compiled+";};";
}
else if (options.outputType === 'node') {
compiled = "module.exports = "+compiled+";";

if (options.wrapped) {
// Only require Handlebars if wrapped
compiled = "var Handlebars = global.Handlebars || require('handlebars');"+compiled;
}
}

return compiled;
};

var doRename = function(dir, base, ext) {
// Change the extension to .js
return base+'.js';
};

return es.pipeline(
map(compileHandlebars),
rename(doRename)
);
});
};
9 changes: 3 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
{
"name": "gulp-handlebars",
"version": "1.0.2",
"version": "2.0.0",
"description": "Handlebars plugin for gulp",
"main": "index.js",
"dependencies": {
"vinyl-map": "0.1.0",
"through": "~2.3.0",
"handlebars": "~1.1.2",
"xtend": "~2.1.1",
"gulp-rename": "~0.2.2",
"event-stream": "~3.1.0"
"gulp-util": "~2.2.0"
},
"devDependencies": {
"gulp-util": "~2.2.12",
"should": "~2.1.1",
"mocha": "~1.15.1"
},
Expand Down
File renamed without changes.
8 changes: 0 additions & 8 deletions test/expected/Basic_amd.js

This file was deleted.

8 changes: 0 additions & 8 deletions test/expected/Basic_bare.js

This file was deleted.

8 changes: 0 additions & 8 deletions test/expected/Basic_commonjs.js

This file was deleted.

8 changes: 0 additions & 8 deletions test/expected/Basic_node.js

This file was deleted.

Loading

0 comments on commit 6f68760

Please sign in to comment.