4

I'm trying out Hakyll for an academia-and-math-heavy static website. I'd like to use pandoc-crossref for cross-references to equations.

What is the simplest way to include pandoc-crossref into the compiler chain?

So far, I was able to integrate a bibliography into the compiler like so

pandocComplilerWithBibAndOptions :: Compiler (Item String)
pandocComplilerWithBibAndOptions = do
    csl <- load $ fromFilePath "apa.csl"
    bib <- load $ fromFilePath "bibliography.bib"
    fmap write (getResourceString >>= read csl bib)
    where
        read = readPandocBiblio readerOptions
        write = writePandocWith writerOptions
        readerOptions = defaultHakyllReaderOptions {
            readerExtensions = newExtentions <> pandocExtensions
        }
        writerOptions = defaultHakyllWriterOptions {
            writerExtensions = newExtentions <> pandocExtensions,
            writerHTMLMathMethod = MathJax ""
        }
        newExtentions = extensionsFromList  [Ext_tex_math_double_backslash,
                                             Ext_citations,
                                             Ext_latex_macros]

main :: IO ()
main = hakyll $ do
    ...

    match "posts/*" $ do
        route $ setExtension "html"
        compile $ pandocComplilerWithBibAndOptions
            >>= loadAndApplyTemplate "templates/post.html"    postCtx
            >>= loadAndApplyTemplate "templates/default.html" postCtx
            >>= relativizeUrls

    match "*.bib" $ compile biblioCompiler
    match "*.csl" $ compile cslCompiler

   ...

While this works nicely, I am clueless on how to integrate the cross-references. My best bet would be to express it as some kind of transform and use pandocCompileWithTransformM, but then i wouldn't know how to integrate the bibliography.

fhchl
  • 711
  • 8
  • 18

1 Answers1

3

Using the Text.Pandoc.CrossRef API

import Text.Pandoc.CrossRef
import Text.Pandoc.Definition (Pandoc) -- pandoc-types

crossRef :: Pandoc -> Pandoc
crossRef = runCrossRef meta Nothing defaultCrossRefAction
  where
    meta = defaultMeta  -- Settings for crossref rendering

Try inserting this between read and write:

    fmap (write . fmap crossRef) (getResourceString >>= read csl bib)

Using the pandoc-crossref executable

pandoc-crossref provides a filter as an executable.

The pandoc library has a function applyFilters that lets you run such filters by providing the path to the executable.

applyFilters :: ... -> Pandoc -> m Pandoc

that you can insert between your read and write.

-- 
filterCrossRef :: Pandoc -> PandocIO Pandoc
filterCrossRef = applyFilters env ["pandoc-crossref"] []

There are a few extra steps needed to embed this into the hakyll Compiler monad (probably recompilingUnsafeCompiler in hakyll and something from PandocIO to IO in pandoc).

Li-yao Xia
  • 31,896
  • 2
  • 33
  • 56
  • Thanks, but it's not at all clear to me how to combine this function with any of the api of pandoc-crossref: https://hackage.haskell.org/package/pandoc-crossref-0.3.13.0/docs/Text-Pandoc-CrossRef.html . – fhchl Nov 28 '22 at 18:42
  • 1
    OK I updated my answer with more detailed steps. – Li-yao Xia Nov 29 '22 at 11:16
  • I have overseen something. Turn's out that pandoc-crossref has to process the document _before_ citeproc. With the above, citations with [@...] are not processed. – fhchl Nov 29 '22 at 12:40
  • 1
    Do you mean that `crossRef` has to happen somewhere in the middle of `read`? – Li-yao Xia Nov 29 '22 at 18:09
  • yeah, before `readPandocBiblio`. As citations and cross references use the same syntax, crossref as to run over the document before citeproc (before the citations are processed) as mentioned [here](https://lierdakil.github.io/pandoc-crossref/#citeproc-and-pandoc-crossref). – fhchl Nov 30 '22 at 08:02