Site Generation - Matt Whipple

This site is generated with pandoc(1). Each html file can be produced by the corresponding source markdown(2). The source files can be collected using a wildcard/glob which can then be used to derive the output files. The pattern itself can be used to call pandoc with the desired invocation.

To support execution in CI or on any system without a haskell environment, this will also support execution through a container.


Required Commands

This section will define some of the invoked commands using the required command Make recipe. For the time being this will just be copied around.

missing-command = $(error $(or ${${1}_INSTALL}, '${1}; is missing; please install ${1}))
required-command = $(or ${_${1}_which},          \
    $(eval _${1}_which=$(shell which ${1})), \
    ${_${1}_which},                          \
    $(call missing-command,${1}))

DOCKER = $(call required-command,docker)

Basic Project Structure

Next to define some basic project structure with inputs and outputs. A site PHONY target will be defined to enable building of all of the outputs.

OUT_DIR  := public/

SOURCES   = $(wildcard *.md)
OUTPUTS   = $(addprefix ${OUT_DIR},${})

site: ${OUTPUTS}
.PHONY: site

Define Docker Image

Running within a container requires selection of a Docker image. I’ll make use of one of the standard pandoc images (3).

PANDOC_IMAGE := pandoc/core:

Run Within Container if Specified

I typically use one of two patterns to run things in containers, either a prefixed target pattern (i.e. docker-<target>) or accepting a flag which swaps out how things are done. Here I’ll use the latter where the passing of a defined IN_DOCKER flag (often provided as an enviornment variable) modifies targets to run within defined containers rather than directly on the host.

If that IN_DOCKER flag is defined then pandoc should be run in a container which works within a bind mount of the local directory.

TODO: Extract and use current user

  PANDOC = ${DOCKER} run --rm --volume $(abspath .):/host -w /host ${PANDOC_IMAGE}
  PANDOC = $(call required-command,pandoc)

Store Commands in File

While it seems somewhat heavy, this project will also support a third means of execution. The pandoc image used above does not include make and therefore cannot readily use the invocations derived by the rules within this file. Since these steps can be done independently I’d rather go that route than introduce a customized image when wanting to use a pipeline of containers (for CI). It seems likely I’ll find a one-stop image at some point which will render this unnecessary, but for now this file will also support generation of a shell script containing what it would otherwise do.

Generation of such a file is fairly straightforward as it can amount to overriding the already defined PANDOC variable to echo to the specified file rather than call the produced command. The final functionality is very simple but is built on top of a fairly high level of comfort with the underlying tools.


clean-script: ; rm ${GEN_SCRIPT}
.PHONY: clean_script

${GEN_SCRIPT}: PANDOC = >> ${GEN_SCRIPT} echo pandoc
${GEN_SCRIPT}: clean-script site

Define Conversion Rule

With all of the building blocks defined, the rule to pass the sourcefiles through pandoc to produce the HTML output can be defined.

    ${PANDOC} --defaults pandoc.defaults -s -o ${@} ${<}

Pandoc defaults file

Pandoc will be configured through the use of the defaults file (1 sec. #default-files). supports which is pointed to above.

Define input and output formats

I’ll be using Pandoc enhanced Markdown as input and generating modern HTML. At some point in the future I may want to swap the output over to something more component/React based but that’s not particularly likely to actually happen and if so not for a bit yet.

from: markdown
to: html5

Configure Citations

I want to use citations with a global bibliography. The link-citations metadata field (1 sec. #other-relevant-metadata-fields) is helpful to provide appropriate hyperlinking. With the linking I also prefer more of a footnote citation style so this uses the numeric ISO 690 CSL style retrieved from the Zotero Style Repository(4). Without an appropriate background, sticking to an ISO standard seemed a safe choice.

citeproc: true
- sources.bib
  citation-style: iso690-numeric-en.csl
  link-citations: true
Pandoc - pandoc user’s guide [online]. June 2021. Available from:
Daring fireball: markdown [online]. 17 April 2021. Available from:
Pandoc/dockerfiles: Dockerfiles for various pandoc images [online]. May 2021. Available from:
Zotero style repository [online]. Available from: