@@ -1,11 +1,19 @@
11-- | Wraps pandocs bibiliography handling
2+--
3+-- In order to add a bibliography, you will need a bibliography file (e.g.
4+-- @.bib@) and a CSL file (@.csl@). Both need to be compiled with their
5+-- respective compilers ('biblioCompiler' and 'cslCompiler'). Then, you can
6+-- refer to these files when you use 'pageReadPandocBiblio'. This function also
7+-- takes a parser state for completeness -- you can use
8+-- 'defaultHakyllParserState' if you're unsure.
9+--
210{-# LANGUAGE Arrows, DeriveDataTypeable, GeneralizedNewtypeDeriving #-}
311module Hakyll.Web.Pandoc.Biblio
412 ( CSL
513 , cslCompiler
6− , References (..)
7− , referencesCompiler
8− , processBiblioCompiler
14+ , Biblio (..)
15+ , biblioCompiler
16+ , pageReadPandocBiblio
917 ) where
1018
1119import Control.Applicative ((<$>))
@@ -13,7 +21,7 @@ import Control.Arrow (arr, returnA)
1321import Data.Typeable (Typeable)
1422
1523import Data.Binary (Binary (..))
16−import Text.Pandoc (Pandoc)
24+import Text.Pandoc (Pandoc, ParserState (..))
1725import Text.Pandoc.Biblio (processBiblio)
1826import qualified Text.CSL as CSL
1927
@@ -22,6 +30,7 @@ import Hakyll.Core.Identifier
2230import Hakyll.Core.Resource
2331import Hakyll.Core.Writable
2432import Hakyll.Web.Page
33+import Hakyll.Web.Pandoc
2534
2635newtype CSL = CSL FilePath
2736 deriving (Binary, Show, Typeable, Writable)
@@ -29,29 +38,36 @@ newtype CSL = CSL FilePath
2938cslCompiler :: Compiler Resource CSL
3039cslCompiler = arr (CSL . unResource)
3140
32−newtype References = References [CSL.Reference]
41+newtype Biblio = Biblio [CSL.Reference]
3342 deriving (Show, Typeable)
3443
35−instance Binary References where
44+instance Binary Biblio where
3645 -- Ugly.
37− get = References . read <$> get
38− put (References rs) = put $ show rs
46+ get = Biblio . read <$> get
47+ put (Biblio rs) = put $ show rs
3948
40−instance Writable References where
49+instance Writable Biblio where
4150 write _ _ = return ()
4251
43−referencesCompiler :: Compiler Resource References
44−referencesCompiler = unsafeCompiler $
45− fmap References . CSL.readBiblioFile . unResource
52+biblioCompiler :: Compiler Resource Biblio
53+biblioCompiler = unsafeCompiler $
54+ fmap Biblio . CSL.readBiblioFile . unResource
4655
47−processBiblioCompiler :: Identifier CSL
48− -> Identifier References
49− -> Compiler (Page Pandoc) (Page Pandoc)
50−processBiblioCompiler csl refs = proc page -> do
51− let body = pageBody page
56+pageReadPandocBiblio :: ParserState
57+ -> Identifier CSL
58+ -> Identifier Biblio
59+ -> Compiler (Page String) (Page Pandoc)
60+pageReadPandocBiblio state csl refs = proc page -> do
5261 CSL csl' <- require_ csl -< ()
53− References refs' <- require_ refs -< ()
54− body' <- unsafeCompiler (tuc processBiblio) -< (csl', refs', body)
55− returnA -< page {pageBody = body'}
62+ Biblio refs' <- require_ refs -< ()
63+ -- We need to know the citation keys, add then *before* actually parsing the
64+ -- actual page. If we don't do this, pandoc won't even consider them
65+ -- citations!
66+ let cits = map CSL.refId refs'
67+ state' = state {stateCitations = stateCitations state ++ cits}
68+ pandocPage <- pageReadPandocWithA -< (state', page)
69+ let pandoc = pageBody pandocPage
70+ pandoc' <- unsafeCompiler (tuc processBiblio) -< (csl', refs', pandoc)
71+ returnA -< pandocPage {pageBody = pandoc'}
5672 where
5773 tuc f (x, y, z) = f x y z