Blogging with Hakyll

Posted on 2019-11-27 , Tags: blog, hakyll, haskell

I’ve been considering migrating from ghost for the following reasons for quite some time:

  1. ghost is bloated: There’s too many features that I’m not gonna to use and it, together with the database, consumes a lot of memory
  2. ghost has poor support for mathjax: Any linebreaks will break your mathjax environment, so yeah, you have to scramble all your equations into one line which is super unreadable and annoying.
  3. ghost is not extensible, all the modules are hard coded into it.
  4. I don’t actually need a dynamic blog as I’m comfortable with using a normal text editor write blogs (actually I’m using emacs) and using git to track all the files and publishing it.

After some research I found Hakyll the perfect candidate for blogging. It supports a huge amount of document formats as it uses pandoc to generate webpage. Not only that, it also supports embedding bibtex citations into markdown and automatically generates all the bibliography at the end of the webpage via the module pandoc-citeproc. This is a huge up for me because I will sometimes cite other papers in my blog post and it relieves me from manually formating bibliographies.

It is very extensible(in Haskell) and somewhat well-documented. It functions more like a static site generator library than the generator itself.

So that’s all my motivations for switching to Hakyll, I shall now introduce you the structure of my customized site.hs. Oh, before start, you should probably read the tutorial written by the author.

Generating bibliography

We sould first load csl files and bibtex files using cslCompiler and biblioCompiler.

We can then build the compiler: readPandocBiblio readerOpt cslPath bibPath which will be used to combine with other compilers.

For the syntax for citing, please refer to the “citation” section in the pandoc user manual.

Building tags

This blog post from javarn.github.io covered this topic.

Optionally embedding mathjax

The idea is that we create a context that reads all the metadata of a post and check if there’s mathjax in it. If there is, then add a const context (script field) which will then be added to the post when applying the templates.

Generating png from LaTeX formulae

Mathjax is great, but it’s nowhere near perfect, as it only provides limited packages.

What if we can use actual LaTeX to compile the blogpost and extract the equations out as images and embed them into the HTML generated? We can use the library latex-svg (written by me). It works by simply using pdftex + dvisvgm + pdfcrop1 to generate svg which can be embedded in HTML With the help of this library, we can typeset beautiful equations:


\int_U \left( \psi \, \Delta \varphi + \nabla \psi \cdot \nabla \varphi \right)\, dV = \oint_{\partial U}\psi\,\nabla\varphi\cdot d\mathbf{S}

and even tikz diagrams !


\begin{tikzpicture}
\matrix (m) [matrix of math nodes,
row sep=3em, column sep=3em,
text height=1.5ex,
text depth=0.25ex]{
            & \lambda\omega             &              & \lambda C                   \\
\lambda 2   &                           & \lambda P 2                                \\
            & \lambda\underline{\omega} &              & \lambda P\underline{\omega} \\
\lambda{\to}&                           & \lambda P  \\
};
\path[-{Latex[length=2.5mm, width=1.5mm]}]
(m-1-2) edge (m-1-4)
(m-2-1) edge (m-2-3)
        edge (m-1-2)
(m-3-2) edge (m-1-2)
        edge (m-3-4)
(m-4-1) edge (m-2-1)
        edge (m-3-2)
        edge (m-4-3)
(m-3-4) edge (m-1-4)
(m-2-3) edge (m-1-4)
(m-4-3) edge (m-3-4)
        edge (m-2-3);
\end{tikzpicture}

Syntax highlighting

Quoting hakyll’s faq:

Syntax highlighting is enabled by default in Hakyll if you are using a somewhat recent version of Pandoc (1.9 and onwards). Note that you also need to include some CSS in order for this to work!

Haskell:

fac :: Int -> Int
fac n = foldr1 (*) [1..n]

Python:

def fac(n: Int) -> Int:
    if n == 0:
        return 1
    else:
        return n * fac(n - 1)

Agda:

∧-elim : (A : Set)(B : Set) -> ((C : Set) -> (A -> B -> C) -> C) -> A
∧-elim A B p = p A (\a b -> a)

  1. source↩︎

License

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License
Creative Commons License