Scott's Weblog The weblog of an IT pro focusing on cloud computing, Kubernetes, Linux, containers, and networking

A Markdown-to-PDF Workflow on Linux

In May of last year I wrote about using a Makefile with Markdown documents, in which I described how I use make and a Makefile along with CLI tools like multimarkdown (the binary, not the format) and Pandoc. At that time, I’d figured out how to use combinations of the various CLI tools to create various formats from the source Markdown document. The one format I hadn’t gotten right at that time was PDF. Pandoc can create PDFs, but only if LaTeX is installed. This article describes a method I found that allows me to create PDFs from my Markdown documents without using LaTeX.

Two tools are involved in this new conversion process: Pandoc, which I’ve discussed on this site before; and wkhtmltopdf, a new tool I just recently discovered. Basically, I use Pandoc to go from Markdown (MultiMarkdown, specifically) to HTML, and then use wkhtmltopdf to generate a PDF file from the HTML.

The first step in the process is to use Pandoc to convert from Markdown to HTML, including the use of CSS to include custom formatting. The command looks something like this:

pandoc --from=markdown_mmd+yaml_metadata_block+smart --standalone \
--to=html -V css=/home/slowe/Documents/std-styles.css \
--output=<destination-html-filename> <source-md-filename>

This generates an HTML document and links it to the specified CSS document for formatting. I could embed the CSS specification in the YAML metadata block at the top of the Markdown document, but then I’d lose the ability to create multiple versions of the document with different formatting. The -V css= parameter lets me specify formatting instructions at the time of creating the HTML document.

Once I have the HTML document, then I can create a paginated PDF with this command:

wkhtmltopdf -B 25mm -T 25mm -L 25mm -R 25mm \
-q -s Letter <source-html-filename> <destination-pdf-filename>

This will create a paginated PDF, based on US Letter paper size, with 25mm margins all the way around.

Putting these together into a make workflow, I can do something like this:

PD = /usr/local/bin/pandoc
PDFLAGS = --from=markdown_mmd+yaml_metadata_block+smart --standalone
WK = /usr/bin/wkhtmltopdf
WKFLAGS = -B 25mm -T 25mm -L 25mm -R 25mm -q -s Letter
CSS ?= /home/slowe/Documents/std-styles.css

%.md.pdf: %.md
        $(PD) $(PDFLAGS) --to=html -V css=$(CSS) $< | $(WK) $(WKFLAGS) - $@

With this in place, all I have to do is type make filename.md.pdf. Make will use pandoc to convert from Markdown to HTML, then pipe those results to wkhtmltopdf to create a paginated PDF. The beauty of defining the stylesheet to use as a variable is that I can override it on the command line if desired:

make CSS=/path/to/alternate/styles.css filename.md.pdf

This makes it super-easy to create PDFs from source Markdown documents.

Have suggestions for improvement? I’m always open to learn more—feel free to hit me on Twitter.

Metadata and Navigation

Be social and share this post!