Citations and Math in Hakyll

Posted on March 20, 2016 by Brian Jaress
Tags: code, haskell, hakyll, meta

This blog recently started using the Hakyll static site generator. There are many reasons for the change, the main ones being that static generation is a better overall fit and that Hakyll uses Pandoc.

So far, the only thing that has taxed my beginner’s knowledge of Haskell is supporting citations and math at the same time:

    -- In the main function of site.hs
    match "assets/*.bib" $ compile biblioCompiler
    match "assets/*.csl" $ compile cslCompiler
-- Somewhere at the top level of site.hs
customPandocCompiler :: Compiler (Item String)
customPandocCompiler = do
    csl <- load $ fromFilePath "assets/apa.csl"
    bib <- load $ fromFilePath "assets/citations.bib"
    fmap write (getResourceString >>= read csl bib)
        read = readPandocBiblio defaultHakyllReaderOptions
        write = writePandocWith writerOptions

writerOptions :: WriterOptions
writerOptions = defaultHakyllWriterOptions
    { writerHTMLMathMethod = MathJax ""

… and then then use customPandocCompiler in place of pandocCompiler.

Doing it only took those few lines of code, but I had to puzzle out some of what’s going on in the Hakyll codebase before I could write them. The Internet had several examples of using those options separately, but it wasn’t obvious how to combine them.

There were two key points to the solution:

  1. Hakyll source uses “compiler” to mean any stage (of any size) of the compilation process. What would be a rule, a command, a target, or an entire build config in some other build system are all all called “compilers” in Hakyll. In hindsight, that’s part of a pattern: Haskell programmers like to use trees where others would use a hierarchy.
  2. When the answer isn’t obvious, it usually is obvious to someone who assumes the answer is fmap or bind or whatever the appropriate popular Haskell idiom would be and then looks through type signatures and type class implementations to find out what the operands are.

Overall, I like Hakyll. Static generation has been more flexible, and Pandoc is my favorite way to generate documents. The integration issues of scripting a library layered on top of another library have put me on a crash course of reading other people’s Haskell code, but I was sort of hoping for that.


Updated the code to support link-citations: true in the YAML metadata and added a conclusion.