diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..638acbd --- /dev/null +++ b/.jshintrc @@ -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 +} diff --git a/index.js b/index.js index ac836e4..7c3dca3 100644 --- a/index.js +++ b/index.js @@ -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()) { @@ -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)); diff --git a/package.json b/package.json index 9002524..a4844bf 100644 --- a/package.json +++ b/package.json @@ -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": "*" diff --git a/readme.md b/readme.md index b0c66e5..fde6b75 100644 --- a/readme.md +++ b/readme.md @@ -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 -