## Using KaTeX with Hakyll

Lightning fast math rendering on the off-chance I ever get around to posting some maths.

When Khan Academy initially released KaTeX 0.1.0 last year I was overjoyed.
The performance comparison against MathJax was impressive and realistically the only reason **MathJax** has ever needed competition.
For those interested in seeing the difference first hand, IntMath has a decent test suite.

After looking under the hood though I could see my work was going to be cut out for me if I wanted to incorporate it into this blog.
Unlike **MathJax**, which scanned the `document.body`

and rendered math elements (indicated via `\[ ... \]`

tags) on the fly, **KaTeX** required the following syntax:

katex.render("c = \\pm\\sqrt{a^2 + b^2}", element);

Not really a problem in general, although it was obvious for my case I'd have to write some form of math parser for the markdown portion of Hakyll.
Still being quite the **Haskell** neophyte, this became something for the too hard basket.
Maybe I also rationalised the decision not to work on a solution due to the very restricted subset of **LaTeX** features implemented at the time.
I mean, not that I ever do much with relational algebra, but the natural join operator (aka the bowtie: \(\bowtie\)) wasn't introducted until v0.2.0.
How am I supposed to make a fancy outfit for my mathematical symbol cat illustrations without a bowtie?

Fast forward a year and **KaTeX** has matured immensely, and is currently at v0.5.0.
The feature list is much more expansive, and the only gripes I really have are the missing environments like `\align`

and the font modifers `\mathrm`

, `\mathbf`

, `\mathcal`

*etc.*
However, it looks like these will all be part of the next release according to the status of this pull request.

My personal saviour was introduced in v0.3.0 by the way of the auto-render extension which acts in a similar fashion to the **MathJax** implementation and scans for `$$ ... $$`

, `\[ ... \]`

and `\( ... \)`

tags.
The first two tags indicate the display size environment whereas the last tag is for inline maths.

Luckily, you can configure **Pandoc** such that **Hakyll** parses the single `$ ... $`

tag in markdown and renders it as `\( ... \)`

for use with **MathJax**.
Travis Athougies has a good writeup on how to do this on his blog here, although I overload my pandoc options a little different so that **Pygments** can be used to do the syntax highlighting on my blog (see my Pandoc.hs):

readerOpts :: ReaderOptions readerOpts = let extensions = S.fromList [ Ext_tex_math_dollars , Ext_inline_code_attributes , Ext_abbreviations ] in def { readerSmart = True , readerExtensions = S.union extensions (writerExtensions def) } writerOpts :: WriterOptions writerOpts = def { writerHTMLMathMethod = MathJax "" , writerHighlight = False , writerHtml5 = True }

So to get **KaTex** working from this starting point, we just need to build a maths context

import qualified Data.Map as M mathCtx :: Context a mathCtx = field "katex" $ \item -> do metadata <- getMetadata $ itemIdentifier item return $ if "katex" `M.member` metadata then "<link rel=\"stylesheet\" href=\"/css/katex.min.css\">\n\ \<script type=\"text/javascript\" src=\"/js/katex.min.js\"></script>\n\ \<script src=\"/js/auto-render.min.js\"></script>" else ""

and apply it to any template where the context is needed. For me, that's:

loadAndApplyTemplate "templates/default.html" (mathCtx `mappend` postCtx) full --- ... --- >>= loadAndApplyTemplate "templates/default.html" (mathCtx `mappend` indexCtx)

which you can checkout properly in my site.hs.
The reason I do it this way rather than just calling the stylesheet and .js files in `default.html`

is to keep the site as lean as possible.
Sure, I have some fancy things going on in the header *etc.* but I'm not pulling in `jQuery`

or some other large library for no good reason, and there's no good reason to load **KaTeX** on every page when only a few places will ever need it.

So I have a `katex`

field which, if activated in the preamble of a post (for instance, see the markdown of this entry here), pumps in the return result of the `katex`

field above into `default.html`

(full source here) and calls the auto-renderer.

$if(katex)$ $katex$ $endif$ <!-- ... --> $if(katex)$ <script> renderMathInElement(document.body); </script> $endif$

With all that in place, embedding maths into posts is essentially trivial, cross platform and most importantly seemless.
As an example, heres a short discussion about some of my recent work using just the `$ ... $`

inline and `$$ ... $$`

display tags in markdown.

Wick rotations are primarily used to find solutions to Minkowski space problems by an Euclidean space mapping. We can also use the rotation to evolve a time-dependent SchrÃ¶dinger equation and solve for time-independent solutions in three dimensions. To do so we transfer our TDSE into an imaginary time basis \(t=i\tau\):

$$i \hbar \frac{\partial}{\partial t}\Psi(\vec{r},t) = H\Psi(\vec{r},t) \Rightarrow - \hbar \frac{\partial}{\partial \tau}\Psi(\vec{r},\tau) = H\Psi(\vec{r},\tau)$$

which yields a general solution to the wavefunctions

$$\Psi(\vec{r},\tau) = \sum_{k=0}^\infty a_k\psi_k(\vec{r})e^{-E_k \tau}.$$

Using the Gram-Schmidt orthoganilsation procedure, higher order orthogonal eigenfunctions can be found by projecting a guess along the lower states. For example

$$\lvert\tilde{\psi^\prime_1}\rangle = \lvert\psi^\prime_1\rangle-\lvert\psi_0\rangle\langle\psi_0\vert\psi^\prime_1\rangle,$$

which can even identify eigenfunctions within a degenerate subspace, as each state is *chosen* to be orthogonal to the systems' basis.

**UPDATE:**

As of `Hakyll 4.8.0.0`

, a complete metadata overhaul has occured to support YAML. This has broken the `mathCtx`

function above and should be replaced by

mathCtx :: Context a mathCtx = field "katex" $ \item -> do katex <- getMetadataField (itemIdentifier item) "katex" return $ case katex of Just "false" -> "" Just "off" -> "" _ -> "<link rel=\"stylesheet\" href=\"/css/katex.min.css\">\n\ \<script type=\"text/javascript\" src=\"/js/katex.min.js\"></script>\n\ \<script src=\"/js/auto-render.min.js\"></script>"

Additionally, much of the gripes concerning **KaTeX**'s math coverage are null and void as the project has matured immensely since the time I initially wrote this post.