Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gulp-util #27

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"node": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 4,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"laxcomma": true,
"laxbreak": true,
"shadow": true,
"devel": true
}
93 changes: 66 additions & 27 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,56 @@
'use strict';
var gutil = require('gulp-util');
var through = require('through2');
var Handlebars = require('handlebars');
var fs = require('fs');
var _ = require('lodash'),
gutil = require('gulp-util'),
through = require('through2'),
Handlebars = require('handlebars'),
yaml = require('js-yaml'),
fs = require('fs'),
path = require('path');

module.exports = function (data, opts) {

var options = opts || {};
//Go through a partials object
if(options.partials){
for(var p in options.partials){
Handlebars.registerPartial(p, options.partials[p]);
var register = function(directories, fn, context) {
if(!directories || !_.isFunction(fn)) {
return;
}
}
//Go through a helpers object
if(options.helpers){
for(var h in options.helpers){
Handlebars.registerHelper(h, options.helpers[h]);

if(_.isString(directories)) {
directories = [directories];
}
}
// Go through a partials directory array
if(options.batch){
// Allow single string
if(typeof options.batch === 'string') options.batch = [options.batch];

options.batch.forEach(function (b) {
var filenames = fs.readdirSync(b);

directories.forEach(function(dir) {
var filenames = fs.readdirSync(dir);
filenames.forEach(function (filename) {
// Needs a better name extractor (maybe with the path module)
var name = filename.split('.')[0];
// Don't allow hidden files
if(!name.length) return;
var template = fs.readFileSync(b + '/' + filename, 'utf8');
Handlebars.registerPartial(b.split('/').pop() + '/' + name, template);
if(filename.indexOf('.') === 0) {
return;
}

var name = path.basename(filename, path.extname(filename));
var content;
if(path.extname(filename) === '.js') {
content = require(path.resolve(dir + path.sep + filename))[name];
} else {
content = fs.readFileSync(dir + path.sep + filename, 'utf8');
}

if(context) {
fn.call(context, name, content);
} else {
fn(name, content);
}
});
});
};

if (options.partials) {
register(options.partials, Handlebars.registerPartial, Handlebars);
}

if (options.helpers) {
register(options.helpers, Handlebars.registerHelper, Handlebars);
}

return through.obj(function (file, enc, cb) {
if (file.isNull()) {
Expand All @@ -51,7 +64,33 @@ module.exports = function (data, opts) {
}

try {
var template = Handlebars.compile(file.contents.toString());
var template = Handlebars.compile(file.contents.toString()),
jsonFile = '',
yamlFile = '',
dataFile = '',
dataFromFile = {};

if (options.data) {
if (_.isString(options.data)) {
jsonFile = gutil.replaceExtension(file.path.replace(options.templates, options.data), '.json');
yamlFile = gutil.replaceExtension(file.path.replace(options.templates, options.data), '.yaml');
} else if(_.isBoolean(options.data)) {
jsonFile = gutil.replaceExtension(file.path, '.json');
yamlFile = gutil.replaceExtension(file.path, '.yaml');
} else {
throw new Error('options.data should be a string or a boolean');
}

if (fs.existsSync(jsonFile)) {
dataFile = jsonFile;
dataFromFile = JSON.parse(fs.readFileSync(jsonFile, 'utf8'));
} else if (fs.existsSync(yamlFile)) {
dataFile = yamlFile;
dataFromFile = yaml.safeLoad(fs.readFileSync(yamlFile, 'utf8'));
}
}

data = _.extend({}, data, dataFromFile);
file.contents = new Buffer(template(data));
} catch (err) {
this.emit('error', new gutil.PluginError('gulp-compile-handlebars', err));
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
],
"dependencies": {
"gulp-util": "~2.2.10",
"through2": "~0.4.0",
"handlebars": "~2.0"
"handlebars": "~2.0",
"js-yaml": "^3.0.2",
"lodash": "^2.4.1",
"through2": "~0.4.0"
},
"devDependencies": {
"mocha": "*"
Expand Down
82 changes: 58 additions & 24 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,64 +1,98 @@
# [gulp](https://github.com/wearefractal/gulp)-compile-handlebars
Forked from [gulp-template](https://github.com/sindresorhus/gulp-template)
Inspired by [grunt-compile-handlebars](https://github.com/patrickkettner/grunt-compile-handlebars)

> Compile [Handlebars templates](http://www.handlebarsjs.com/)

## Install
## New in this fork

In this fork, the focus is to make it dead simple to build static website using handlebars, in a well structured project.

It means that it is pretty opinionated as to how you should organised your files.

Install with [npm](https://npmjs.org/package/gulp-compile-handlebars)
The project structure that is working for me looks like this :

```
npm install --save-dev gulp-compile-handlebars
|-src
|---data
|-----en
|-----fr
|---helpers
|---partials
|---templates
|-----en
|-----fr
```

I've taken the example of a multilang website to insist on the fact that the data folder structure should mimic the templates folder structure.

## Install

_Currently:_
`npm install p-j/gulp-compile-handlebars --save-dev`

## Example

### `src/hello.handlebars`
```handlebars
{{!-- src/templates/hello.handlebars --}}

```erb
<h1>Hello {{firstName}}</h1>
<h2>HELLO! {{capitals firstName}}</h2>
<h1>Hello {{firstName}} {{lastName}}</h1>
<h2>HELLO! {{capitals firstName}} {{capitals lastName}}</h2>
{{> footer}}
```

### `gulpfile.js`
```handlebars
{{!-- src/partials/footer.handlebars --}}

<footer>the end</footer>
```

```javascript
// src/helpers/capitals.js

module.exports.capitals = function (str) {
return str.toUpperCase();
};
```

```yml
# src/data/hello.yaml

lastName: "Parker"
```

```js
// gulpfile.js

var gulp = require('gulp');
var handlebars = require('gulp-compile-handlebars');

gulp.task('default', function () {
var templateData = {
firstName: 'Kaanon'
firstName: 'Jérémie'
},
options = {
partials : {
footer : '<footer>the end</footer>'
},
helpers : {
capitals : function(str){
return str.toUpperCase();
}
templates: 'src/templates',
data: 'src/data'
partials : 'src/partials',
helpers : 'src/helpers'
}
}

return gulp.src('src/hello.handlebars')
return gulp.src(['src/templates/*.handlebars'])
.pipe(handlebars(templateData, options))
.pipe(rename('hello.html'))
.pipe(gulp.dest('dist'));
});
```

### `dist/hello.html`

Result:
```html
<h1>Hello Kaanon</h1>
<h2>HELLO! KAANON</h2>
<!-- dist/hello.html -->
<h1>Hello Jérémie Parker</h1>
<h2>HELLO! JÉRÉMIE PARKER</h2>
<footer>the end</footer>
```

## License
Based on [Kaanon MacFarlane](http://kaanon.com) works which was itself base on [Sindre Sorhus](http://sindresorhus.com)'s.

MIT © [Kaanon MacFarlane](http://kaanon.com)
[MIT](http://opensource.org/licenses/MIT) © [Jérémie Parker](http://jeremie-parker.com)
24 changes: 14 additions & 10 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
'use strict';
var assert = require('assert');
var gutil = require('gulp-util');
var template = require('./index');
var template = require('./index.js');

it('should compile Handlebars templates', function (cb) {
var stream = template(
{
people: ['foo', 'bar'],
message: 'BAZ'
},
{
partials : { header : '<header/>' },
helpers : { toLower : function(str) { return str.toLowerCase(); } }
});
var data = {
people: ['foo', 'bar']
};

var options = {
templates: 'test/templates',
data: 'test/data',
partials: 'test/partials',
helpers: 'test/helpers'
};

var stream = template(data, options);

stream.on('data', function (data) {
assert.equal(data.contents.toString(), '<header/><li>foo</li><li>bar</li> baz');
cb();
});

stream.write(new gutil.File({
path: 'test/test.handlebars',
contents: new Buffer('{{> header}}{{#each people}}<li>{{.}}</li>{{/each}} {{toLower message}}')
}));

Expand Down
1 change: 1 addition & 0 deletions test/data/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
message: BAZ
4 changes: 4 additions & 0 deletions test/helpers/toLower.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'use strict';
module.exports.toLower = function (str) {
return str.toLowerCase();
};
1 change: 1 addition & 0 deletions test/partials/header.handlebars
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<header/>