Feep! » Blog » Post

RSS feed, and other blog improvements

Someone emailed me a few weeks ago and asked me to add an RSS feed to this blog. That’s done (and while I was at it I added h-entry markup to the index page in case anyone has a use for it); and since I’m here I figured I may as well talk about the underlying code, which has changed quite a lot since my last post on the topic.

The biggest change is that it’s now statically generated; I mentioned last time that I wasn’t even sure why I hadn’t done that in the first place, and I rectified the situation more or less immediately after that post. My opinions on prebuilt static site generators still stand, though, so as usual I rolled my own.

This time I tried using the Tup build system to supervise generating files. Normally I just make a single command that regenerates everything (which is very fast, since it doesn’t need to do much), but I needed a build system for some other static assets and I figured I may as well use it for everything. (Unlike my previous problems with build systems, this one I’m actually using the way it was intended, so it works out much better.) So, the core of the Tupfile looks like this:

# Build each post (depend on assets so we rebuild when their hash changes)
: foreach ../../blog/*.md | mermaid.min.js.asset katex.min.css.asset atom-one-light.css.asset |> node ./build_blogpost.js %f %o |> ../../public/blog/post/%B.html

# Build index file
# TODO: The %f below isn't actually used by the command, but is needed to convince Tup to rebuild the index when new posts are added.
: ../../blog/*.md |> node ./build_blogindex.js %f |> ../../public/blog/index.html ../../public/blog/index.rss

The rest is fairly straightforward code to shuffle templates around and generate output files; the core hasn’t changed that much since my last post (it’s still just rendering markdown into a template, after all); but it’s accumulated more flourishes to handle things like katex markup and rendering PIC diagrams, as seen in the bitwise operators post.

Actually, that last bit might be interesting as a representative example. The code looks like this:

const child_process = require('child_process')
md.use(require('markdown-it-fence'), 'dpic', {
	marker: ':',
	render(tokens, idx, options, env, self) {
		const token = tokens[idx]
		return '<figure>'+child_process.execSync('dpic -v', {
			input: `.PS\n${token.content}\n.PE\n`,

This simply takes a fenced block that starts with :::dpic, and feeds it through dpic -v to render an SVG which is dumped directly into the output.

This isn’t configurable, or scaleable, or really in any way a best practice; but it is easy to understand and modify, which makes this sort of approach perfect for little one-off things like this blog that aren’t likely to grow much and just need something simple but flexible.