More specifically, I want to add the titles by referencing an external JSON file, let's call it titles.json.
One of the things I use grunt for is to build static HTML files for design and debugging. This would be really helpful during development, not just for titles but potentially other data as well, such as setting the active nav link.
I'm currently concatenating HTML files using the process described by the accepted answer here: Using grunt concat, how would I automate the concatenation of the same file to many other files?
EDIT: I now use assemble for this, it was created to make working with templates and external data very easy.
Here is my take on this. Uses grunt's standard template mechanism, page metadata is defined in an object, outside of actual page files, as you suggested (I can't say I like this).
gruntfile (including the wrap
task from Using grunt concat, how would I automate the concatenation of the same file to many other files?):
/*global module:false*/
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
meta: {
version: '0.1.0',
banner: '/*! PROJECT_NAME - v<%= meta.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
'* http://PROJECT_WEBSITE/\n' +
'* Copyright (c) <%= grunt.template.today("yyyy") %> ' +
'YOUR_NAME; Licensed MIT */'
},
// Paths
project: {
partials: 'assets/partials', // don't put trailing slash
pages: 'assets/pages', // don't put trailing slash
less: 'assets/less',
css: 'assets/css',
img: 'assets/img',
js: 'assets/js'
},
// Used for page title and nav generation.
// It's an array to ensure correct order for nav
pages: [{
file: 'index.html',
title: 'My homepage'
/* This format can be extended to something like:
* {
* title: 'My homepage',
* header: 'Welcome to my site',
* navtitle: 'Home'
* }
* Although I think it's best to keep page metadata as close to content as possible,
* i.e. right inside pages files (think YAML headers in Jekyll pages)
*/
}, {
file: 'about.html',
title: 'About me'
}, {
file: 'contact.html',
title: 'Contact'
}],
// wraps files with header and footer
wrap: {
html: {
header: '<%= project.partials %>/head.tmpl',
footer: '<%= project.partials %>/footer.tmpl',
src: [
'<%= project.pages %>/index.html',
'<%= project.pages %>/about.html',
'<%= project.pages %>/contact.html'
],
dest: '.' // destination *directory*, probably better than specifying same file names twice
}
},
// processes templates in page files
buildPages: {
pages: '<config:pages>', // page files metadata
dir: '.' // page files location dir
}
});
// Default task.
grunt.registerTask('default', 'wrap buildPages');
grunt.registerMultiTask('wrap', 'Wraps source files with specified header and footer', function() {
var data = this.data,
path = require('path'),
dest = grunt.template.process(data.dest),
files = grunt.file.expandFiles(this.file.src),
header = grunt.file.read(grunt.template.process(data.header)),
footer = grunt.file.read(grunt.template.process(data.footer)),
sep = grunt.utils.linefeed;
files.forEach(function(f) {
var p = dest + '/' + path.basename(f),
contents = grunt.file.read(f);
grunt.file.write(p, header + sep + contents + sep + footer);
grunt.log.writeln('File "' + p + '" created.');
});
});
grunt.registerTask('buildPages', 'Processes templates in page files', function() {
// NOTE: current implementation replaces files
var data = grunt.config('buildPages'),
pages = data.pages,
dir = data.dir,
contents,
curPath;
pages.forEach(function(page) {
curPath = dir + '/' + page.file;
contents = grunt.file.read(curPath);
// feed the entire pages array and current entry to the template
grunt.file.write(curPath, grunt.template.process(contents, {
pages: pages,
curPage: page
}));
grunt.log.writeln('Page at "' + curPath + '" built.');
});
});
};
head.tmpl:
<!DOCTYPE html>
<html>
<head>
<title><%= curPage.title %></title>
</head>
<body>
<!-- NAV -->
<ul class="nav">
<%
pages.forEach(function(p) {
print(
'<li class="' + ((curPage === p) ? 'active' : '') + '">' +
((curPage === p) ? p.title : ('<a href="' + p.file + '">' + p.title + '</a>')) +
'</li>\n'
);
});
%>
</ul>
<!-- /NAV -->
<!-- MAIN CONTENT -->
<div class="main">
footer.tmpl:
</div>
<!-- /MAIN CONTENT -->
</body>
</html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With