这是我对此的看法.使用grunt的标准模板机制,页面元数据在一个对象中定义,在实际页面文件之外,如你所建议的那样(我不能说我喜欢这个).
/*global module:false*/
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
meta: {
version: '0.1.0',
banner: '/*! PROJECT_NAME - v - ' +
'\n' +
'* http://PROJECT_WEBSITE/\n' +
'* Copyright (c) ' +
'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: '/head.tmpl',
footer: '/footer.tmpl',
src: [
'/index.html',
'/about.html',
'/contact.html'
],
dest: '.' // destination *directory*, probably better than specifying same file names twice
}
},
// processes templates in page files
buildPages: {
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:
pages.forEach(function(p) {
print(
'
' +((curPage === p) ? p.title : ('' + p.title + '')) +
'
\n');
});
%>
footer.tmpl: