Skip to content

Instantly share code, notes, and snippets.

@hail2u
Last active December 21, 2015 13:09
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hail2u/6310613 to your computer and use it in GitHub Desktop.
Save hail2u/6310613 to your computer and use it in GitHub Desktop.
This Grunt task renders `foo.hbs` using data based on `metadata.json` (Base) and `foo.json` (Extend) with Handlebars.js. `foo.hbs` can include other Handlebars.js template (e.g. `styles.inc.hbs`).
module.exports = function (grunt) {
var _ = grunt.util._;
var async = grunt.util.async;
var hbs = require('handlebars');
var path = require('path');
var taskName = 'generate';
var taskDescription = 'Generate files using Handlebars.js.';
grunt.registerMultiTask(taskName, taskDescription, function () {
var done = this.async();
var dirTmpl = this.data.cwd;
var metadataBase = grunt.file.readJSON(dirTmpl + 'metadata.json');
hbs.registerHelper('include', function (file, options) {
var rendered = _applyTemplate(dirTmpl + file, this);
return new hbs.SafeString(rendered);
});
async.forEach(this.files, function (file, next) {
var template = file.src[0];
if (!grunt.file.exists(template)) {
grunt.log.warn('Source file "' + template + '" not found.');
next();
}
dirTmpl = path.dirname(template) + '/';
var metadata = _extendData(template);
var rendered = _applyTemplate(template, metadata);
grunt.file.write(file.dest, rendered);
grunt.log.writeln('File "' + file.dest + '" created.');
next();
}, function (err) {
done(err);
});
function _applyTemplate(file, data) {
var tmpl = hbs.compile(grunt.file.read(file));
return tmpl(data);
}
function _extendData(file) {
var data = _.extend({}, metadataBase);
var fileMetadata = file.replace(/\.\w+?$/, '.json');
if (grunt.file.isFile(fileMetadata)) {
_.extend(data, grunt.file.readJSON(fileMetadata));
}
return data;
}
});
};
module.exports = function (grunt) {
grunt.initConfig({
generate: {
all: {
expand: true,
cwd: '.grunt/html/',
src: ['**/*.hbs', '!**/*.inc.hbs'],
filter: 'isFile',
dest: './',
ext: '.html'
}
}
});
grunt.util.linefeed = '\n';
grunt.loadTasks('.grunt/tasks/');
grunt.registerTask('default', []);
grunt.registerTask('rebuild', [
'generate:all',
]);
};
<!doctype html>
<head>
<meta charset="UTF-8">
<meta name="description" content="{{description}}">
<title>{{title}}</title>
<link rel="canonical" href="{{canonical}}">
{{include "./styles.inc.hbs"}}
</head>
<body>
<h1>{{title}}</h1>
<p>{{description}}</p>
</body>
</html>
{
"canonical": "http://example.com/"
}
{
"title": "My Awesome Website",
"description": "I love internet!"
}
[.grunt]
[html]
metadata.json
index.hbs
index.json
styles.inc.hbs
[sub]
subdir.hbs
subdir.json
[tasks]
generate.js
Gruntfile.js
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/2.1.0/normalize.css">
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic">
<link rel="stylesheet" href="/css/default.css">
<!doctype html>
<head>
<meta charset="UTF-8">
<meta name="description" content="{{description}}">
<title>{{title}}</title>
<link rel="canonical" href="{{canonical}}">
{{! include template with real file system path}}
{{include "../styles.inc.hbs"}}
</head>
<body>
<h1>{{title}}</h1>
<p>{{description}}</p>
</body>
</html>
{
"canonical": "http://example.com/subdir/",
"title": "My Awesome Sub-directory!",
"description": "I love internet, too!"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment