Введение

Hakyll - отличная система генерации статичных вэб-сайтов (блогов, персональных страничек, …), написанная на языке Haskell. Фактически же, hakyll - это всего-навсего набор библиотек для сборки пользователем собственной Haskell-программы, которая и используется в дальнейшем для создания (генерации, обновления) статичных (HTML) вэб-страничек с использованием шаблонов.

На вход программе-генератору обычно поступают обыкновенные текстовые файлы в синтаксисе Markdown, в которых и содержится наполнение страниц сайта. Hakyll использует мощнейшую Haskell-библиотеку pandoc для преобразования информации из Markdown в HTML и многие другие форматы.

Компилятор pandoc, в частности, поддерживает рендеринг математических формул, записанных в тексте Markdown в LaTex-нотации, в MathJax для последующей вставки (и отрисовывания браузером) в тело вэб-страницы.

По-умолчанию Hakyll вызывает pandoc-компилятор с выключенной интерпретацией математических текстов. Это легко настраивается и даёт удобную возможность писать сложные математические формулы прямо в тексте markdown.

1. Изменение программы-генератора Hakyll

Пырвый шаг - это модификация генератора.

Для рендеринга математики в интересующих нас .markdown-файлов (у меня они хранятся в posts), откроем Main.hs генератора Hakyll и заменим дефолтную функцию pandocCompiler (пакет pandoc) на нашу собственную (с включёнными флагами MathJax):

-- Импортируем дополнительно
import qualified Data.Set as S
import Text.Pandoc.Options


{-
    ...
-}


-- Уравнение для нашей функции
pandocMathCompiler =
    let mathExtensions = [Ext_tex_math_dollars, Ext_tex_math_double_backslash,
                          Ext_latex_macros]
        defaultExtensions = writerExtensions defaultHakyllWriterOptions
        newExtensions = foldr S.insert defaultExtensions mathExtensions
        writerOptions = defaultHakyllWriterOptions {
                          writerExtensions = newExtensions,
                          writerHTMLMathMethod = MathJax ""
                        }
    in pandocCompilerWith defaultHakyllReaderOptions writerOptions



main :: IO ()
main = do

    {-
        ...
    -}

    -- Заменяем дефолтную функцию pandocCompiler на нашу
    match "posts/*" $ do
        route   $ setExtension ".html"
        compile $ do
            pandocMathCompiler
                >>= saveSnapshot "content"
                >>= return . fmap demoteHeaders
                >>= loadAndApplyTemplate "templates/post.html" (postCtx tags)
                >>= loadAndApplyTemplate "templates/content.html" defaultContext
                >>= loadAndApplyTemplate "templates/default.html" defaultContext
                >>= relativizeUrls

    {-
        ...
    -}

Для моего генератора мне пришлось добавить зависимости containers и pandoc в .cabal-файл.

2. Изменение HTML-шаблона

Вторым шагом добавляем загрузку функционала MathJax в дефолтный шаблон (будущих) страничек с формулами (я добавил в <head> файла templates/default.html):

        <!-- enable MathJax -->
        <script type="text/javascript"
                src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
        </script>

Ввод математики

Для ввода LaTeX-математики в тексте Markdown теперь можно просто использовать двойной знак $:

Результат: $$ \ln x = \int_{-\infty}^x \frac 1 y \, dy  $$

Результат: $$ \ln x = \int_{-\infty}^x \frac 1 y , dy $$

Ещё пример:

Текст в markdown:

$$
    \require{AMScd}
    \begin{CD}
        K(X) @>{ch}>> H(X;\mathbb Q);\\
        @VVV @VVV \\
        K(Y) @>{ch}>> H(Y;\mathbb Q);
    \end{CD}
$$

Текст в markdown:

$$ \require{AMScd} \begin{CD} K(X) @>{ch}» H(X;\mathbb Q);\
@VVV @VVV \
K(Y) @>{ch}» H(Y;\mathbb Q); \end{CD} $$

Всё работает на ура!