1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
--------------------------------------------------------------------------------
-- | Wraps pandocs bibiliography handling
--
-- In order to add a bibliography, you will need a bibliography file (e.g.
-- @.bib@) and a CSL file (@.csl@). Both need to be compiled with their
-- respective compilers ('biblioCompiler' and 'cslCompiler'). Then, you can
-- refer to these files when you use 'readPandocBiblio'. This function also
-- takes the reader options for completeness -- you can use
-- 'defaultHakyllReaderOptions' if you're unsure.
-- 'pandocBiblioCompiler' is a convenience wrapper which works like 'pandocCompiler',
-- but also takes paths to compiled bibliography and csl files.
{-# LANGUAGE Arrows #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Hakyll.Web.Pandoc.Biblio
( CSL
, cslCompiler
, Biblio (..)
, biblioCompiler
, readPandocBiblio
, pandocBiblioCompiler
) where
--------------------------------------------------------------------------------
import Control.Monad (liftM, replicateM)
import Data.Binary (Binary (..))
import Data.Typeable (Typeable)
import Hakyll.Core.Compiler
import Hakyll.Core.Compiler.Internal
import Hakyll.Core.Identifier
import Hakyll.Core.Item
import Hakyll.Core.Provider
import Hakyll.Core.Writable
import Hakyll.Web.Pandoc
import Hakyll.Web.Pandoc.Binary ()
import qualified Text.CSL as CSL
import Text.CSL.Pandoc (processCites)
import Text.Pandoc (Pandoc, ReaderOptions (..),
enableExtension, Extension (..))
--------------------------------------------------------------------------------
data CSL = CSL
deriving (Show, Typeable)
--------------------------------------------------------------------------------
instance Binary CSL where
put CSL = return ()
get = return CSL
--------------------------------------------------------------------------------
instance Writable CSL where
-- Shouldn't be written.
write _ _ = return ()
--------------------------------------------------------------------------------
cslCompiler :: Compiler (Item CSL)
cslCompiler = makeItem CSL
--------------------------------------------------------------------------------
newtype Biblio = Biblio [CSL.Reference]
deriving (Show, Typeable)
--------------------------------------------------------------------------------
instance Binary Biblio where
-- Ugly.
get = do
len <- get
Biblio <$> replicateM len get
put (Biblio rs) = put (length rs) >> mapM_ put rs
--------------------------------------------------------------------------------
instance Writable Biblio where
-- Shouldn't be written.
write _ _ = return ()
--------------------------------------------------------------------------------
biblioCompiler :: Compiler (Item Biblio)
biblioCompiler = do
filePath <- getResourceFilePath
makeItem =<< unsafeCompiler (Biblio <$> CSL.readBiblioFile idpred filePath)
where
-- This is a filter on citations. We include all citations.
idpred = const True
--------------------------------------------------------------------------------
readPandocBiblio :: ReaderOptions
-> Item CSL
-> Item Biblio
-> (Item String)
-> Compiler (Item Pandoc)
readPandocBiblio ropt csl biblio item = do
-- Parse CSL file, if given
provider <- compilerProvider <$> compilerAsk
style <- unsafeCompiler $
CSL.readCSLFile Nothing . (resourceFilePath provider) . itemIdentifier $ csl
-- We need to know the citation keys, add then *before* actually parsing the
-- actual page. If we don't do this, pandoc won't even consider them
-- citations!
let Biblio refs = itemBody biblio
pandoc <- itemBody <$> readPandocWith ropt item
let pandoc' = processCites style refs pandoc
return $ fmap (const pandoc') item
--------------------------------------------------------------------------------
pandocBiblioCompiler :: String -> String -> Compiler (Item String)
pandocBiblioCompiler cslFileName bibFileName = do
csl <- load $ fromFilePath cslFileName
bib <- load $ fromFilePath bibFileName
liftM writePandoc
(getResourceBody >>= readPandocBiblio ropt csl bib)
where ropt = defaultHakyllReaderOptions
{ -- The following option enables citation rendering
readerExtensions = enableExtension Ext_citations $ readerExtensions defaultHakyllReaderOptions
}
|