packages feed

hakyll 4.15.0.1 → 4.15.1.0

raw patch · 17 files changed

+407/−62 lines, 17 filesdep ~aesondep ~pandocPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: aeson, pandoc

API changes (from Hackage documentation)

+ Hakyll.Web.Html: instance GHC.Show.Show Hakyll.Web.Html.Srcset
+ Hakyll.Web.Html: instance GHC.Show.Show Hakyll.Web.Html.SrcsetImageCandidate
+ Hakyll.Web.Pandoc.Biblio: processPandocBiblios :: Item CSL -> [Item Biblio] -> Item Pandoc -> Compiler (Item Pandoc)
+ Hakyll.Web.Pandoc.Biblio: readPandocBiblios :: ReaderOptions -> Item CSL -> [Item Biblio] -> Item String -> Compiler (Item Pandoc)

Files

CHANGELOG.md view
@@ -4,6 +4,23 @@  # Releases +## Hakyll 4.15.1.0 (2021-10-25)++- Add `Hakyll.Web.Pandoc.Biblio` functions `readPandocBiblios` and+    `processPandocBiblios`, which let one use multiple bibliographies+    (contribution by Benjamin Eskola)+- Preserve file extension of bibliography files when passing them to Pandoc.+    This enables one to use not just BibTex, but also YAML and JSON files+    (contribution by Benjamin Eskola)+- Fix URL extraction for `srcset` attribute. This affects+    `Hakyll.Web.HTML.relativizeUrls` and other such functions (contribution by+    Alexander Batischev)+- Bump `bytestring` upper bound to allow 0.11 (contribution by Alexander+    Batischev)+- Bump `pandoc` upper bound to allow 2.15 (contribution by Alexander Batischev)+- Bump `aeson` bounds to allow 2.0 (contribution by Alexander Batischev)++ ## Hakyll 4.15.0.1 (2021-10-02)  - Add missing test file to the package (contribution by Alexander Batischev)
hakyll.cabal view
@@ -1,5 +1,5 @@ Name:    hakyll-Version: 4.15.0.1+Version: 4.15.1.0  Synopsis: A static website compiler library Description:@@ -59,11 +59,15 @@  Extra-source-files:   CHANGELOG.md-  tests/data/biblio/biblio01.golden   tests/data/biblio/chicago.csl+  tests/data/biblio/cites-meijer.golden+  tests/data/biblio/cites-multiple.golden+  tests/data/biblio/cites-multiple.markdown   tests/data/biblio/default.html   tests/data/biblio/page.markdown   tests/data/biblio/refs.bib+  tests/data/biblio/refs.yaml+  tests/data/biblio/refs2.yaml   tests/data/embed.html   tests/data/example.md   tests/data/example.md.metadata@@ -173,12 +177,12 @@     Paths_hakyll    Build-Depends:-    aeson                >= 1.0      && < 1.6,+    aeson                >= 1.0      && < 1.6 || >= 2.0 && < 2.1,     base                 >= 4.8      && < 5,     binary               >= 0.5      && < 0.10,     blaze-html           >= 0.5      && < 0.10,     blaze-markup         >= 0.5.1    && < 0.9,-    bytestring           >= 0.9      && < 0.11,+    bytestring           >= 0.9      && < 0.12,     containers           >= 0.3      && < 0.7,     data-default         >= 0.4      && < 0.8,     deepseq              >= 1.3      && < 1.5,@@ -242,7 +246,7 @@     Other-Modules:       Hakyll.Web.Pandoc.Binary     Build-Depends:-      pandoc >= 2.11 && < 2.15+      pandoc >= 2.11 && < 2.16     Cpp-options:       -DUSE_PANDOC @@ -280,10 +284,12 @@     tasty-hunit                >= 0.9  && < 0.11,     tasty-quickcheck           >= 0.8  && < 0.11,     -- Copy pasted from hakyll dependencies:+    aeson                >= 1.0      && < 1.6 || >= 2.0 && < 2.1,     base                 >= 4.8      && < 5,-    bytestring           >= 0.9      && < 0.11,+    bytestring           >= 0.9      && < 0.12,     containers           >= 0.3      && < 0.7,     filepath             >= 1.0      && < 1.5,+    tagsoup              >= 0.13.1   && < 0.15,     text                 >= 0.11     && < 1.3,     unordered-containers >= 0.2      && < 0.3,     yaml                 >= 0.8.11   && < 0.12@@ -338,4 +344,4 @@     base      >= 4     && < 5,     directory >= 1.0   && < 1.4,     filepath  >= 1.0   && < 1.5,-    pandoc    >= 2.11  && < 2.15+    pandoc    >= 2.11  && < 2.16
lib/Hakyll/Core/Metadata.hs view
@@ -1,4 +1,5 @@ --------------------------------------------------------------------------------+{-# LANGUAGE CPP #-} module Hakyll.Core.Metadata     ( Metadata     , lookupString@@ -14,12 +15,16 @@   ---------------------------------------------------------------------------------import           Control.Arrow                  (second) import           Control.Monad                  (forM) import           Control.Monad.Fail             (MonadFail) import           Data.Binary                    (Binary (..), getWord8,                                                  putWord8, Get)-import qualified Data.HashMap.Strict            as HMS+#if MIN_VERSION_aeson(2,0,0)+import qualified Data.Aeson.KeyMap              as KeyMap+import qualified Data.Aeson.Key                 as AK+#else+import qualified Data.HashMap.Strict            as KeyMap+#endif import qualified Data.Set                       as S import qualified Data.Text                      as T import qualified Data.Vector                    as V@@ -35,13 +40,13 @@  -------------------------------------------------------------------------------- lookupString :: String -> Metadata -> Maybe String-lookupString key meta = HMS.lookup (T.pack key) meta >>= Yaml.toString+lookupString key meta = KeyMap.lookup (keyFromString key) meta >>= Yaml.toString   -------------------------------------------------------------------------------- lookupStringList :: String -> Metadata -> Maybe [String] lookupStringList key meta =-    HMS.lookup (T.pack key) meta >>= Yaml.toList >>= mapM Yaml.toString+    KeyMap.lookup (keyFromString key) meta >>= Yaml.toList >>= mapM Yaml.toString   --------------------------------------------------------------------------------@@ -106,7 +111,7 @@         Yaml.Object obj -> do             putWord8 0             let list :: [(T.Text, BinaryYaml)]-                list = map (second BinaryYaml) $ HMS.toList obj+                list = map (\(k, v) -> (keyToText k, BinaryYaml v)) $ KeyMap.toList obj             put list          Yaml.Array arr -> do@@ -125,7 +130,7 @@             0 -> do                 list <- get :: Get [(T.Text, BinaryYaml)]                 return $ BinaryYaml $ Yaml.Object $-                    HMS.fromList $ map (second unBinaryYaml) list+                    KeyMap.fromList $ map (\(k, v) -> (keyFromText k, unBinaryYaml v)) list              1 -> do                 list <- get :: Get [BinaryYaml]@@ -137,3 +142,25 @@             4 -> BinaryYaml . Yaml.Bool   <$> get             5 -> return $ BinaryYaml Yaml.Null             _ -> fail "Data.Binary.get: Invalid Binary Metadata"+++--------------------------------------------------------------------------------+#if MIN_VERSION_aeson(2,0,0)+keyFromString :: String -> AK.Key+keyFromString = AK.fromString++keyToText :: AK.Key -> T.Text+keyToText = AK.toText++keyFromText :: T.Text -> AK.Key+keyFromText = AK.fromText+#else+keyFromString :: String -> T.Text+keyFromString = T.pack++keyToText :: T.Text -> T.Text+keyToText = id++keyFromText :: T.Text -> T.Text+keyFromText = id+#endif
lib/Hakyll/Core/Provider/Metadata.hs view
@@ -144,9 +144,9 @@       where         hint = case err of             Yaml.InvalidYaml (Just (Yaml.YamlParseException {..}))-                | yamlProblem == problem -> "\n" +++                | yamlProblem ==  "mapping values are not allowed in this context" -> "\n" ++                     "Hint: if the metadata value contains characters such\n" ++                     "as ':' or '-', try enclosing it in quotes."+            Yaml.AesonException "Error in $: parsing HashMap ~Text failed, expected Object, but encountered String"+                -> "\nHint: in metadata, keys and values are separated by a colon *and* a space."             _ -> ""--        problem = "mapping values are not allowed in this context"
lib/Hakyll/Web/Html.hs view
@@ -25,12 +25,17 @@ -------------------------------------------------------------------------------- import           Data.Char                       (digitToInt, intToDigit,                                                   isDigit, toLower)-import           Data.List                       (isPrefixOf)+import           Data.Either                     (fromRight)+import           Data.List                       (isPrefixOf, intercalate)+import           Data.Maybe                      (fromMaybe) import qualified Data.Set                        as S+import           Control.Monad                   (void) import           System.FilePath                 (joinPath, splitPath,                                                   takeDirectory) import           Text.Blaze.Html                 (toHtml) import           Text.Blaze.Html.Renderer.String (renderHtml)+import qualified Text.Parsec                     as P+import qualified Text.Parsec.Char                as PC import qualified Text.HTML.TagSoup               as TS import           Network.URI                     (isUnreserved, escapeURIString) @@ -71,12 +76,21 @@  -------------------------------------------------------------------------------- isUrlAttribute :: String -> Bool-isUrlAttribute = (`elem` ["src", "href", "data", "poster", "srcset"])+isUrlAttribute = (`elem` ["src", "href", "data", "poster"])   --------------------------------------------------------------------------------+-- | Extract URLs from tags' attributes. Those would be the same URLs on which+-- `withUrls` would act. getUrls :: [TS.Tag String] -> [String]-getUrls tags = [v | TS.TagOpen _ as <- tags, (k, v) <- as, isUrlAttribute k]+getUrls tags = [u | TS.TagOpen _ as <- tags, (k, v) <- as, u <- extractUrls k v]+  where+  extractUrls "srcset" value =+    let srcset = fmap unSrcset $ P.parse srcsetParser "" value+    in map srcsetImageCandidateUrl $ fromRight [] srcset+  extractUrls key value+    | isUrlAttribute key = [value]+    | otherwise = []   --------------------------------------------------------------------------------@@ -86,6 +100,14 @@   where     tag (TS.TagOpen s a) = TS.TagOpen s $ map attr a     tag x                = x++    attr input@("srcset", v)   =+      case fmap unSrcset $ P.parse srcsetParser "" v of+        Right srcset ->+          let srcset' = map (\i -> i { srcsetImageCandidateUrl = f $ srcsetImageCandidateUrl i }) srcset+              srcset'' = show $ Srcset srcset'+          in ("srcset", srcset'')+        Left _ -> input     attr (k, v)          = (k, if isUrlAttribute k then f v else v)  @@ -142,7 +164,7 @@ -------------------------------------------------------------------------------- -- | Get the relative url to the site root, for a given (absolute) url toSiteRoot :: String -> String-toSiteRoot = removeWinPathSeparator . emptyException . joinPath +toSiteRoot = removeWinPathSeparator . emptyException . joinPath            . map parent . filter relevant . splitPath . takeDirectory   where     parent            = const ".."@@ -198,3 +220,83 @@ -- > "Me &amp; Dean" escapeHtml :: String -> String escapeHtml = renderHtml . toHtml+++--------------------------------------------------------------------------------+data Srcset = Srcset {+    unSrcset :: [SrcsetImageCandidate]+  }+++--------------------------------------------------------------------------------+instance Show Srcset where+  show set = intercalate ", " $ map show $ unSrcset set+++--------------------------------------------------------------------------------+data SrcsetImageCandidate = SrcsetImageCandidate {+    srcsetImageCandidateUrl :: String+  , srcsetImageCandidateDescriptor :: Maybe String+  }+++--------------------------------------------------------------------------------+instance Show SrcsetImageCandidate where+  show candidate =+    let url = srcsetImageCandidateUrl candidate+    in case srcsetImageCandidateDescriptor candidate of+      Just desc -> concat [url, " ", desc]+      Nothing -> url+++--------------------------------------------------------------------------------+-- HTML spec: https://html.spec.whatwg.org/#srcset-attributes+srcsetParser :: P.Parsec String () Srcset+srcsetParser = do+  result <- candidate `P.sepBy1` (PC.char ',')+  P.eof+  return $ Srcset result+  where+  candidate :: P.Parsec String () SrcsetImageCandidate+  candidate = do+    P.skipMany ascii_whitespace+    u <- url+    P.skipMany ascii_whitespace+    desc <- P.optionMaybe $ P.choice $ fmap P.try [width_descriptor, px_density_descriptor]+    P.skipMany ascii_whitespace+    return $ SrcsetImageCandidate {+        srcsetImageCandidateUrl = u+      , srcsetImageCandidateDescriptor = desc+      }++  -- This is an over-simplification, but should be good enough for our purposes+  url :: P.Parsec String () String+  url = P.many1 $ PC.noneOf " ,"++  ascii_whitespace :: P.Parsec String () ()+  ascii_whitespace = void $ P.oneOf "\x09\x0A\x0C\x0D\x20"++  width_descriptor :: P.Parsec String () String+  width_descriptor = do+    number <- P.many1 PC.digit+    void $ PC.char 'w'+    return $ concat [number, "w"]++  px_density_descriptor :: P.Parsec String () String+  px_density_descriptor = do+    sign <- P.optionMaybe $ PC.char '-'+    int <- P.many1 PC.digit+    frac <- P.optionMaybe $ do+      void $ PC.char '.'+      frac <- P.many1 PC.digit+      return $ concat [".", frac]+    expon <- P.optionMaybe $ do+      letter <- P.oneOf "eE"+      e_sign <- P.optionMaybe $ PC.oneOf "-+"+      number <- P.many1 PC.digit+      return $ concat [[letter], mb $ fmap show e_sign, number]+    void $ PC.char 'x'+    return $ concat [mb $ fmap show sign, int, mb frac, mb expon, "x"]++  mb :: Maybe String -> String+  mb = fromMaybe ""
lib/Hakyll/Web/Pandoc/Biblio.hs view
@@ -21,7 +21,9 @@     , Biblio (..)     , biblioCompiler     , readPandocBiblio+    , readPandocBiblios     , processPandocBiblio+    , processPandocBiblios     , pandocBiblioCompiler     ) where @@ -33,6 +35,7 @@ import qualified Data.ByteString.Lazy          as BL import qualified Data.Map                      as Map import qualified Data.Time                     as Time+import qualified Data.Text                     as T (pack) import           Data.Typeable                 (Typeable) import           Hakyll.Core.Compiler import           Hakyll.Core.Compiler.Internal@@ -45,6 +48,7 @@                                                 enableExtension) import qualified Text.Pandoc                   as Pandoc import qualified Text.Pandoc.Citeproc          as Pandoc (processCitations)+import           System.FilePath               (addExtension, takeExtension)   --------------------------------------------------------------------------------@@ -86,9 +90,16 @@                  -> Item Biblio                  -> (Item String)                  -> Compiler (Item Pandoc)-readPandocBiblio ropt csl biblio item = do+readPandocBiblio ropt csl biblio = readPandocBiblios ropt csl [biblio]++readPandocBiblios :: ReaderOptions+                  -> Item CSL+                  -> [Item Biblio]+                  -> (Item String)+                  -> Compiler (Item Pandoc)+readPandocBiblios ropt csl biblios item = do   pandoc <- readPandocWith ropt item-  processPandocBiblio csl biblio pandoc+  processPandocBiblios csl biblios pandoc   --------------------------------------------------------------------------------@@ -96,7 +107,13 @@                     -> Item Biblio                     -> (Item Pandoc)                     -> Compiler (Item Pandoc)-processPandocBiblio csl biblio item = do+processPandocBiblio csl biblio = processPandocBiblios csl [biblio]++processPandocBiblios :: Item CSL+                     -> [Item Biblio]+                     -> (Item Pandoc)+                     -> Compiler (Item Pandoc)+processPandocBiblios csl biblios item = do     -- It's not straightforward to use the Pandoc API as of 2.11 to deal with     -- citations, since it doesn't export many things in 'Text.Pandoc.Citeproc'.     -- The 'citeproc' package is also hard to use.@@ -108,16 +125,25 @@     -- ersatz filesystem.     let Pandoc.Pandoc (Pandoc.Meta meta) blocks = itemBody item         cslFile = Pandoc.FileInfo zeroTime . unCSL $ itemBody csl-        bibFile = Pandoc.FileInfo zeroTime . unBiblio $ itemBody biblio-        addBiblioFiles = \st -> st-            { Pandoc.stFiles =-                Pandoc.insertInFileTree "_hakyll/style.csl" cslFile .-                Pandoc.insertInFileTree "_hakyll/refs.bib" bibFile $-                Pandoc.stFiles st-            }+        bibFiles = zipWith (\x y ->+            ( addExtension ("_hakyll/bibliography-" ++ show x)+                           (takeExtension $ toFilePath $ itemIdentifier y)+            , Pandoc.FileInfo zeroTime . unBiblio . itemBody $ y+            )+          )+          [0 ..]+          biblios++        stFiles = foldr ((.) . uncurry Pandoc.insertInFileTree)+                    (Pandoc.insertInFileTree "_hakyll/style.csl" cslFile)+                    bibFiles++        addBiblioFiles = \st -> st { Pandoc.stFiles = stFiles $ Pandoc.stFiles st }+         biblioMeta = Pandoc.Meta .             Map.insert "csl" (Pandoc.MetaString "_hakyll/style.csl") .-            Map.insert "bibliography" (Pandoc.MetaString "_hakyll/refs.bib") $+            Map.insert "bibliography"+              (Pandoc.MetaList $ map (Pandoc.MetaString . T.pack . fst) bibFiles) $             meta         errOrPandoc = Pandoc.runPure $ do             Pandoc.modifyPureState addBiblioFiles
lib/Hakyll/Web/Template/Context.hs view
@@ -10,7 +10,7 @@ -- > … <> functionField "concat" (const . concat) <> … -- -- which will allow you to use the @concat@ identifier as a function that takes--- arbitrarily many stings and concatenates them to a new string:+-- arbitrarily many strings and concatenates them to a new string: -- -- > $partial(concat("templates/categories/", category))$ --
tests/Hakyll/Core/Provider/Metadata/Tests.hs view
@@ -1,12 +1,18 @@ --------------------------------------------------------------------------------+{-# LANGUAGE CPP #-} module Hakyll.Core.Provider.Metadata.Tests     ( tests     ) where   ---------------------------------------------------------------------------------import qualified Data.HashMap.Strict           as HMS+#if MIN_VERSION_aeson(2,0,0)+import qualified Data.Aeson.KeyMap             as KeyMap+import qualified Data.Aeson.Key                as AK+#else+import qualified Data.HashMap.Strict           as KeyMap import qualified Data.Text                     as T+#endif import qualified Data.Yaml                     as Yaml import           Hakyll.Core.Metadata import           Hakyll.Core.Provider.Metadata@@ -26,10 +32,7 @@ testPage01 :: Assertion testPage01 =     (meta [("foo", "bar")], "qux\n") `expectRight` parsePage-    "---\n\-    \foo: bar\n\-    \---\n\-    \qux\n"+    "---\nfoo: bar\n---\nqux\n"   --------------------------------------------------------------------------------@@ -37,21 +40,22 @@ testPage02 =     (meta [("description", descr)], "Hello I am dog\n") `expectRight`     parsePage-    "---\n\-    \description: A long description that would look better if it\n\-    \             spanned multiple lines and was indented\n\-    \---\n\-    \Hello I am dog\n"+    "---\ndescription: A long description that would look better if it\n             spanned multiple lines and was indented\n---\nHello I am dog\n"   where     descr :: String     descr =-        "A long description that would look better if it \-        \spanned multiple lines and was indented"+        "A long description that would look better if it spanned multiple lines and was indented"   -------------------------------------------------------------------------------- meta :: Yaml.ToJSON a => [(String, a)] -> Metadata-meta pairs = HMS.fromList [(T.pack k, Yaml.toJSON v) | (k, v) <- pairs]+meta pairs = KeyMap.fromList [(keyFromString k, Yaml.toJSON v) | (k, v) <- pairs]+  where+#if MIN_VERSION_aeson(2,0,0)+  keyFromString = AK.fromString+#else+  keyFromString = T.pack+#endif   --------------------------------------------------------------------------------
tests/Hakyll/Web/Html/RelativizeUrls/Tests.hs view
@@ -35,4 +35,6 @@         , "<script src=\"//ajax.googleapis.com/jquery.min.js\"></script>" @=?             relativizeUrlsWith "../.."                 "<script src=\"//ajax.googleapis.com/jquery.min.js\"></script>"+        , "<img srcset=\"./image.png 200w, ./image2.png 400w\" />"  @=?+            relativizeUrlsWith "." "<img srcset=\"/image.png 200w, /image2.png 400w\" />"         ]
tests/Hakyll/Web/Html/Tests.hs view
@@ -8,6 +8,7 @@ import           Data.Char        (toUpper) import           Test.Tasty       (TestTree, testGroup) import           Test.Tasty.HUnit ((@=?))+import qualified Text.HTML.TagSoup               as TS   --------------------------------------------------------------------------------@@ -34,6 +35,23 @@             demoteHeadersBy 0 "<h4>A h4 title</h4>" -- Assert that a demotion of @N < 1@ is a no-op.         ] +    , fromAssertions "getUrls"+        [ ["/image1.png", "/image2.jpeg", "https://example.com", "/game.swf", "/poster.jpeg"] @=?+            getUrls [+                TS.TagOpen "img" [("src", "/image1.png")]+              , TS.TagOpen "img" [("src", "/image2.jpeg")]+              , TS.TagOpen "a" [("href", "https://example.com")]+              , TS.TagOpen "object" [("data", "/game.swf")]+              , TS.TagOpen "video" [("poster", "/poster.jpeg")]+              ]+        , ["/image1.png", "/image2.jpeg", "/image3.bmp"] @=?+            getUrls [ TS.TagOpen "img" [("srcset", "/image1.png 10w, /image2.jpeg, /image3.bmp 1.3x")] ]++        -- Invalid srcset specification means no URLs are extracted+        , [] @=?+            getUrls [ TS.TagOpen "img" [("srcset", "/image1.png 10wide, /image2.jpeg, /image3.bmp 1.3px")] ]+        ]+     , fromAssertions "withUrls"         [ "<a href=\"FOO\">bar</a>" @=?             withUrls (map toUpper) "<a href=\"foo\">bar</a>"@@ -51,6 +69,16 @@         -- Test minimizing elements         , "<meta bar=\"foo\" />" @=?             withUrls id "<meta bar=\"foo\" />"++        -- Test that URLs are extracted from img's srcset+        , "<img srcset=\"foo 200w\" />" @=?+            withUrls (const "foo") "<img srcset=\"/path/to/image.png 200w\" />"+        , "<img srcset=\"bar 200w, bar 400w\" />" @=?+            withUrls (const "bar") "<img srcset=\"/small.jpeg 200w, /img/large.jpeg 400w\" />"++        -- Invalid srcsets are left unchanged+        , "<img srcset=\"/image1.png 200px\" />" @=?+            withUrls (const "bar") "<img srcset=\"/image1.png 200px\" />"         ]      , fromAssertions "toUrl"
tests/Hakyll/Web/Pandoc/Biblio/Tests.hs view
@@ -25,6 +25,8 @@ tests :: TestTree tests = testGroup "Hakyll.Web.Pandoc.Biblio.Tests" $     [ goldenTest01+    , goldenTest02+    , goldenTest03     ]  --------------------------------------------------------------------------------@@ -36,7 +38,7 @@ goldenTest01 =     goldenVsString         "biblio01"-        (goldenTestsDataDir </> "biblio01.golden")+        (goldenTestsDataDir </> "cites-meijer.golden")         (do             -- Code lifted from https://github.com/jaspervdj/hakyll-citeproc-example.             logger <- Logger.new Logger.Error@@ -60,6 +62,74 @@              output <- fmap LBS.fromStrict $ B.readFile $                     destinationDirectory testConfiguration </> "page.html"++            cleanTestEnv++            return output)++goldenTest02 :: TestTree+goldenTest02 =+    goldenVsString+        "biblio02"+        (goldenTestsDataDir </> "cites-meijer.golden")+        (do+            -- Code lifted from https://github.com/jaspervdj/hakyll-citeproc-example.+            logger <- Logger.new Logger.Error+            let config = testConfiguration { providerDirectory = goldenTestsDataDir }+            _ <- run RunModeNormal config logger $ do+                let myPandocBiblioCompiler = do+                        csl <- load "chicago.csl"+                        bib <- load "refs.yaml"+                        getResourceBody >>=+                            readPandocBiblio defaultHakyllReaderOptions csl bib >>=+                            return . writePandoc++                match "default.html" $ compile templateCompiler+                match "chicago.csl" $ compile cslCompiler+                match "refs.yaml"    $ compile biblioCompiler+                match "page.markdown" $ do+                    route $ setExtension "html"+                    compile $+                        myPandocBiblioCompiler >>=+                        loadAndApplyTemplate "default.html" defaultContext++            output <- fmap LBS.fromStrict $ B.readFile $+                    destinationDirectory testConfiguration </> "page.html"++            cleanTestEnv++            return output)++goldenTest03 :: TestTree+goldenTest03 =+    goldenVsString+        "biblio03"+        (goldenTestsDataDir </> "cites-multiple.golden")+        (do+            -- Code lifted from https://github.com/jaspervdj/hakyll-citeproc-example.+            logger <- Logger.new Logger.Error+            let config = testConfiguration { providerDirectory = goldenTestsDataDir }+            _ <- run RunModeNormal config logger $ do+                let myPandocBiblioCompiler = do+                        csl <- load "chicago.csl"+                        bib1 <- load "refs.bib"+                        bib2 <- load "refs2.yaml"+                        getResourceBody >>=+                            readPandocBiblios defaultHakyllReaderOptions csl [bib1, bib2] >>=+                            return . writePandoc++                match "default.html" $ compile templateCompiler+                match "chicago.csl" $ compile cslCompiler+                match "refs.bib"    $ compile biblioCompiler+                match "refs2.yaml"    $ compile biblioCompiler+                match "cites-multiple.markdown" $ do+                    route $ setExtension "html"+                    compile $+                        myPandocBiblioCompiler >>=+                        loadAndApplyTemplate "default.html" defaultContext++            output <- fmap LBS.fromStrict $ B.readFile $+                    destinationDirectory testConfiguration </> "cites-multiple.html"              cleanTestEnv 
− tests/data/biblio/biblio01.golden
@@ -1,16 +0,0 @@-<!doctype html>-<html lang="en">-    <head>-        <meta charset="utf-8">-        <title>This page cites a paper.</title>-    </head>-    <body>-        <h1>This page cites a paper.</h1>-        <p>I would like to cite one of my favourite papers <span class="citation" data-cites="meijer1991functional">(Meijer, Fokkinga, and Paterson 1991)</span> here.</p>-<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">-<div id="ref-meijer1991functional" class="csl-entry" role="doc-biblioentry">-Meijer, Erik, Maarten Fokkinga, and Ross Paterson. 1991. <span>“Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire.”</span> In <em>Conference on Functional Programming Languages and Computer Architecture</em>, 124–44. Springer.-</div>-</div>-    </body>-</html>
+ tests/data/biblio/cites-meijer.golden view
@@ -0,0 +1,16 @@+<!doctype html>+<html lang="en">+    <head>+        <meta charset="utf-8">+        <title>This page cites a paper.</title>+    </head>+    <body>+        <h1>This page cites a paper.</h1>+        <p>I would like to cite one of my favourite papers <span class="citation" data-cites="meijer1991functional">(Meijer, Fokkinga, and Paterson 1991)</span> here.</p>+<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">+<div id="ref-meijer1991functional" class="csl-entry" role="doc-biblioentry">+Meijer, Erik, Maarten Fokkinga, and Ross Paterson. 1991. <span>“Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire.”</span> In <em>Conference on Functional Programming Languages and Computer Architecture</em>, 124–44. Springer.+</div>+</div>+    </body>+</html>
+ tests/data/biblio/cites-multiple.golden view
@@ -0,0 +1,20 @@+<!doctype html>+<html lang="en">+    <head>+        <meta charset="utf-8">+        <title>This page cites a paper and a book.</title>+    </head>+    <body>+        <h1>This page cites a paper and a book.</h1>+        <p>I would like to cite one of my favourite papers <span class="citation" data-cites="meijer1991functional">(Meijer, Fokkinga, and Paterson 1991)</span> here.</p>+<p>And also a book <span class="citation" data-cites="lipovaca2012">(Lipovača 2012)</span>.</p>+<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">+<div id="ref-lipovaca2012" class="csl-entry" role="doc-biblioentry">+Lipovača, Miran. 2012. <em>Learn You a Haskell for Great Good! A Beginner’s Guide</em>. San Francisco, CA: No Starch Press.+</div>+<div id="ref-meijer1991functional" class="csl-entry" role="doc-biblioentry">+Meijer, Erik, Maarten Fokkinga, and Ross Paterson. 1991. <span>“Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire.”</span> In <em>Conference on Functional Programming Languages and Computer Architecture</em>, 124–44. Springer.+</div>+</div>+    </body>+</html>
+ tests/data/biblio/cites-multiple.markdown view
@@ -0,0 +1,7 @@+---+title: This page cites a paper and a book.+---++I would like to cite one of my favourite papers [@meijer1991functional] here.++And also a book [@lipovaca2012].
+ tests/data/biblio/refs.yaml view
@@ -0,0 +1,18 @@+---+references:+- id: meijer1991functional+  author:+    - family: Meijer+      given: Erik+    - family: Fokkinga+      given: Maarten+    - family: Paterson+      given: Ross+  container-title: Conference on functional programming languages and computer architecture+  issued:+    - year: 1991+  page: 124–144+  publisher: Springer+  title: Functional programming with bananas, lenses, envelopes and barbed wire+  type: paper-conference+...
+ tests/data/biblio/refs2.yaml view
@@ -0,0 +1,18 @@+---+references:+- id: lipovaca2012+  author:+    - family: Lipovača+      given: Miran+  call-number: QA76.73.H37 L69 2012+  event-place: San Francisco, CA+  ISBN: 978-1-59327-283-8+  issued:+    - year: 2012+  number-of-pages: '375'+  publisher: No Starch Press+  publisher-place: San Francisco, CA+  source: Library of Congress ISBN+  title: Learn you a Haskell for great good! a beginner's guide+  type: book+...