jaspervdj / hakyll

A static website compiler library in Haskell
jaspervdj.be/hakyll
Other
2.69k stars 411 forks source link

Hakyll, pandoc-crossref filter and bibtex #365

Open anderflash opened 9 years ago

anderflash commented 9 years ago

Hi, I'm trying to put bibtex and pandoc-crossref to work in a Hakyll wiki config. I have this almost default code:

match "posts/*" $ do
        route $ setExtension "html"
        compile $ do
            -- modification begin
            item <- getUnderlying
            bibFile <- liftM (fromMaybe "") $ getMetadataField item "biblio"
            cslFile <- liftM (fromMaybe "chicago") $ getMetadataField item "csl"
            let compiler = if bibFile /= ""
                then bibtexCompiler cslFile bibFile
                else pandocCompilerWithTransformM defaultHakyllReaderOptions pandocOptions (transformer "pandoc-crossref" defaultHakyllReaderOptions pandocOptions)
            compiler
            -- modification end
                >>= loadAndApplyTemplate "templates/post.html"    postCtx
                >>= loadAndApplyTemplate "templates/default.html" postCtx
                >>= relativizeUrls

If the post has a bibtex file attached, process the bibtex, else skip bibtex processing, working only with the pandoc-crossref.

My problem is the bibtexCompiler code. I want to put pandoc-crossref inside it:

bibtexCompiler :: String -> String -> Compiler (Item String)
bibtexCompiler cslFileName bibFileName = do 
    csl <- load (fromFilePath $ "csl/"++cslFileName)
    bib <- load (fromFilePath $ "bib/"++bibFileName)
    --liftM (writePandocWith pandocOptions)
    --    (getResourceBody >>= readPandocBiblio def csl bib)
    writePandocWith pandocOptions <$>
        (traverse transformer "pandoc-crossref" def pandocOptions =<< readPandocBiblio def csl bib =<< getResourceBody)

transformer  :: Script  -> ReaderOptions  -> WriterOptions -> (Pandoc -> Compiler Pandoc)
transformer script reader_opts writer_opts pandoc = 
    do let input_json = writeJSON writer_opts pandoc
       output_json <- unixFilter script [] input_json
       return $ 
          either (error.show) id $  -- this line needs to be uncommented atm.
          readJSON reader_opts output_json 

I've seen the code for pandocCompilerWithTransformM:

pandocCompilerWithTransformM :: ReaderOptions -> WriterOptions
                    -> (Pandoc -> Compiler Pandoc)
                    -> Compiler (Item String)
pandocCompilerWithTransformM ropt wopt f =
    writePandocWith wopt <$>
        (traverse f =<< readPandocWith ropt =<< getResourceBody)

That's why I'm trying to use this code, replacing readPandocWith ropt with readPandocBiblio def csl bib, which has the same return type. But it doesn't work.

It compiles and runs correctly, and it shows the bibliography and the Figure 1, but the citation shows [\@author], even though it shows [1]. The reason I create the issue here is that whether I remove the traverse transformer ..., the citation works (it shows [1]), but the pandoc-crossref not.

Thanks

krsch commented 8 years ago

Could you post a sample site to a gist? It would simplify working on this issue (if it's still an issue).

jaspervdj commented 8 years ago

Yes, it would be useful if you could dump a standalone .zip or gist so we can easily reproduce it.

klpn commented 6 years ago

I was looking for the same thing. A perhaps somewhat kludgy solution which, however, gives me correct citations, as well as cross-references, is to use the Pandoc program itself as a filter. From my site program:

bibtexCompiler :: String -> Compiler (Item String)
bibtexCompiler lang = do 
    csl <- load (fromFilePath $ lang ++ ".csl")
    bib <- load "static-dust.bib"
    getResourceBody 
      >>= withItemBody (unixFilter "pandoc" [ "-F"
                                            , "pandoc-crossref"
                                            , "-t"
                                            , "markdown"
                                            , "-M"
                                            , "crossrefYaml=pandoc-crossref-"++lang++".yaml"
                                            ])
      >>= readPandocBiblio pandocReaderOptions csl bib
      >>= return . writePandocWith pandocWriterOptions
arrowd commented 6 months ago

For pandocCompiler users here's the code that solved the problem for me:

pandocCompilerWithTransformM defaultHakyllReaderOptions defaultHakyllWriterOptions plantumlFilter
  where
    plantumlFilter = recompilingUnsafeCompiler
      . runIOorExplode
      . applyFilters noEngine def
          [JSONFilter "/usr/local/lib/python3.9/site-packages/pandoc_plantuml_filter.py"]
          []