Using NPM scripts to statically generate this site
So this blog started out as a few html pages, no shared master template or partial templates. But once I'd copy/pasted the same blocks of markup a couple of times, I wanted to do something about the repetition. Instead of using Jekyll, I thought I'd try out mustache.js and it's CLI. I'm sure there's a better way to do this, but I wanted to see where this road would lead.
I started off adding an NPM script to output an index.html page from a template, (an empty JSON file) and a partial.
"scripts": {
"mustache": "mustache -p templates/partials/page-head.template templates/data/empty.json templates/index.template > public/index.html"
}
That's pretty powerful, I can now use shared partials in each blog article.
With this I have to remember to add a file name to that script when I write a new post... another idea is to write a Node script to read in all the templates in a folder and build them.
"scripts": {
"template": "./bin/template.js"
}
Side note: I didn't have to write node ./bin/template.js, since the script has a hashbang #! /usr/bin/env node it'll be run by Node automatically. The script reads in all the filenames of the partials in /templates/partials/ and turns them into arguments that the Mustache CLI can use. Next it reads in all the blog post templates, and executes the Mustache CLI command to output the final HTML files in a folder ready to be deployed.
#! /usr/bin/env node
const fs = require('fs');
const shell = require('shelljs');
const partialsArgs = fs.readdirSync('./templates/partials/')
.filter(f => f.endsWith('.template'))
.reduce((args, partial) => `${args} -p templates/partials/${partial}`, '');
fs.readdirSync('./templates/')
.filter(filePath => filePath.endsWith('.template'))
.forEach((templatePath) => {
const templateName = templatePath.substring(0, templatePath.lastIndexOf('.template'));
const outputDir = templateName === 'index' ? 'public/' : 'public/writing/';
const command = `$(npm bin)/mustache ${partialsArgs} templates/data/empty.json templates/${templatePath} > ${outputDir}/${templateName}.html`;
console.log(command); // eslint-disable-line no-console
shell.exec(command);
});
With the watch and browser-sync modules, I can make a change to a template or partial and have the site rebuilt and reloaded in the browser automatically. I'm also using concurrently to run npm scripts in parallel.
"scripts": {
"dev": "concurrently 'npm run watch-templates' 'npm run browser-sync'",
"watch-templates": "watch 'npm run template' ./templates",
"template": "./bin/template.js",
"browser-sync": "browser-sync start --server 'public' --files './public'"
}