July 10, 2016
I have worked intensively on the Oden User Guide lately, primarly on improving content, but also on providing high-quality PDF and HTML output formats with detailed control over typesetting.
For some code listings and syntax examples I want the typesetting to convey the meaning of text in the listing – user input, command output, placeholders, etc. The User Guide build uses Pandoc to transform Markdown documents to PDF (through LaTeX) and to HTML. I could not find a good way to express the custom formatting in a way that worked with both LaTeX and HTML using standard Pandoc functionality.
Therefore, I created a filter to handle my input format. Using this filter, I can write code listings in separate files, using a small subset of HTML. Here’s an example of a shell command listing source file from the User Guide:
<strong>GOPATH=PWD/target/go:$GOPATH go build -o hello hello/main</strong>
$ <strong>./hello</strong>
$ Hello, world!
The strong
tags in the listing are part of the HTML
subset I use. To include listings in the Pandoc Markdown source I use
regular code block syntax and add the custom include
and
formatted
attributes:
```{include=src/listings/hello-world-go-build-and-run.html formatted=true}
```
The output, both in HTML and PDF, looks like this:
$ GOPATH=PWD/target/go:$GOPATH go build -o hello hello/main
$ ./hello
Hello, world!
For listings explaining the syntax of the Oden language I want placeholders to be typeset in italic text. Where the language supports a sequence of forms I want to express that using placeholder expressions with subscripts. The following listing source file explains the let binding syntax of Oden.
<em>identifier<sub>1</sub></em> = <em>expression<sub>1</sub></em>
let <em>identifier<sub>2</sub></em> = <em>expression<sub>2</sub></em>
...<em>identifier<sub>n</sub></em> = <em>expression<sub>n</sub></em>
<em>body-expression</em> in
When included in the document, just like in the example before, the output looks like this:
let identifier1 = expression1
identifier2 = expression2
...
identifiern = expressionn
in body-expression
The filter is very simplistic in that it only supports
em
, strong
, and sub
elements, but
it suits the needs of the Oden User Guide. I find extending Pandoc with
filters very powerful, and I hope you find this technique and the blog
post useful. If you are interested in the complete solution, including
the Makefile compiling the filter and running Pandoc, please see doc/user-guide
in the Oden repository.
Long live Pandoc!