packages feed

hakyll 4.13.4.1 → 4.14.0.0

raw patch · 15 files changed

+870/−93 lines, 15 filesdep +tasty-goldendep −pandoc-citeprocdep ~pandocdep ~randomPVP ok

version bump matches the API change (PVP)

Dependencies added: tasty-golden

Dependencies removed: pandoc-citeproc

Dependency ranges changed: pandoc, random

API changes (from Hackage documentation)

+ Hakyll.Web.Pandoc: renderPandocWithTransform :: ReaderOptions -> WriterOptions -> (Pandoc -> Pandoc) -> Item String -> Compiler (Item String)
+ Hakyll.Web.Pandoc: renderPandocWithTransformM :: ReaderOptions -> WriterOptions -> (Pandoc -> Compiler Pandoc) -> Item String -> Compiler (Item String)
+ Hakyll.Web.Pandoc.Biblio: [unBiblio] :: Biblio -> ByteString
- Hakyll.Web.Pandoc.Biblio: Biblio :: [Reference] -> Biblio
+ Hakyll.Web.Pandoc.Biblio: Biblio :: ByteString -> Biblio

Files

CHANGELOG.md view
@@ -4,6 +4,15 @@  # Releases +## Hakyll 4.14.0.0 (2021-03-14)++- Add `renderPandocWithTransform` and `renderPandocWithTransformM` (by Norman+  Liu)+- Make sure the initial project is writable (by Tobias Bora)+- Bump `pandoc` to 2.11.*+- Bump `file-embed` upper bound to 0.0.14+- Bump `random` upper bound to 1.2+ ## Hakyll 4.13.4.1 (2020-09-30)  - Bump `pandoc` to 2.10.*
hakyll.cabal view
@@ -1,5 +1,5 @@ Name:    hakyll-Version: 4.13.4.1+Version: 4.14.0.0  Synopsis: A static website compiler library Description:@@ -59,6 +59,11 @@  Extra-source-files:   CHANGELOG.md+  tests/data/biblio/biblio01.golden+  tests/data/biblio/chicago.csl+  tests/data/biblio/default.html+  tests/data/biblio/page.markdown+  tests/data/biblio/refs.bib   tests/data/embed.html   tests/data/example.md   tests/data/example.md.metadata@@ -174,7 +179,7 @@     data-default         >= 0.4      && < 0.8,     deepseq              >= 1.3      && < 1.5,     directory            >= 1.2.7.0  && < 1.4,-    file-embed           >= 0.0.10.1 && < 0.0.12,+    file-embed           >= 0.0.10.1 && < 0.0.14,     filepath             >= 1.0      && < 1.5,     lrucache             >= 1.1.1    && < 1.3,     memory               >= 0.14.18  && < 0.16,@@ -183,7 +188,7 @@     optparse-applicative >= 0.12     && < 0.16,     parsec               >= 3.0      && < 3.2,     process              >= 1.6      && < 1.7,-    random               >= 1.0      && < 1.2,+    random               >= 1.0      && < 1.3,     regex-tdfa           >= 1.1      && < 1.4,     resourcet            >= 1.1      && < 1.3,     scientific           >= 0.3.4    && < 0.4,@@ -232,8 +237,7 @@     Other-Modules:       Hakyll.Web.Pandoc.Binary     Build-Depends:-      pandoc          >= 2.10     && < 2.11,-      pandoc-citeproc >= 0.14     && < 0.18+      pandoc >= 2.11 && < 2.12     Cpp-options:       -DUSE_PANDOC @@ -267,6 +271,7 @@     hakyll,     QuickCheck                 >= 2.8  && < 2.15,     tasty                      >= 0.11 && < 1.4,+    tasty-golden               >= 2.3  && < 2.4,     tasty-hunit                >= 0.9  && < 0.11,     tasty-quickcheck           >= 0.8  && < 0.11,     -- Copy pasted from hakyll dependencies:@@ -292,6 +297,7 @@    If flag(usePandoc)     Other-modules:+      Hakyll.Web.Pandoc.Biblio.Tests       Hakyll.Web.Pandoc.FileType.Tests     Cpp-options:       -DUSE_PANDOC@@ -327,4 +333,4 @@     base      >= 4     && < 5,     directory >= 1.0   && < 1.4,     filepath  >= 1.0   && < 1.5,-    pandoc    >= 2.10  && < 2.11+    pandoc    >= 2.11  && < 2.12
lib/Hakyll/Core/Item.hs view
@@ -2,6 +2,7 @@ -- | An item is a combination of some content and its 'Identifier'. This way, we -- can still use the 'Identifier' to access metadata. {-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveTraversable  #-} module Hakyll.Core.Item     ( Item (..)     , itemSetBody@@ -25,23 +26,7 @@ data Item a = Item     { itemIdentifier :: Identifier     , itemBody       :: a-    } deriving (Show, Typeable)------------------------------------------------------------------------------------instance Functor Item where-    fmap f (Item i x) = Item i (f x)------------------------------------------------------------------------------------instance Foldable Item where-    foldr f z (Item _ x) = f x z------------------------------------------------------------------------------------instance Traversable Item where-    traverse f (Item i x) = Item i <$> f x-+    } deriving (Show, Typeable, Functor, Foldable, Traversable)  -------------------------------------------------------------------------------- instance Binary a => Binary (Item a) where
lib/Hakyll/Web/Pandoc.hs view
@@ -8,6 +8,8 @@     , writePandocWith     , renderPandoc     , renderPandocWith+    , renderPandocWithTransform+    , renderPandocWithTransformM        -- * Derived compilers     , pandocCompiler@@ -104,6 +106,32 @@   --------------------------------------------------------------------------------+-- | An extension of `renderPandocWith`, which allows you to specify a custom+-- Pandoc transformation on the input `Item`.+-- Useful if you want to do your own transformations before running +-- custom Pandoc transformations, e.g. using a `funcField` to transform raw content.+renderPandocWithTransform :: ReaderOptions -> WriterOptions+                    -> (Pandoc -> Pandoc)+                    -> Item String+                    -> Compiler (Item String)+renderPandocWithTransform ropt wopt f = +    renderPandocWithTransformM ropt wopt (return . f) +++--------------------------------------------------------------------------------+-- | Similar to `renderPandocWithTransform`, but the Pandoc transformation is+-- monadic. This is useful when you want the pandoc+-- transformation to use the `Compiler` information such as routes,+-- metadata, etc. along with your own transformations beforehand.+renderPandocWithTransformM :: ReaderOptions -> WriterOptions+                    -> (Pandoc -> Compiler Pandoc)+                    -> Item String+                    -> Compiler (Item String)+renderPandocWithTransformM ropt wopt f i = +    writePandocWith wopt <$> (traverse f =<< readPandocWith ropt i) +++-------------------------------------------------------------------------------- -- | Read a page render using pandoc pandocCompiler :: Compiler (Item String) pandocCompiler =@@ -137,9 +165,8 @@ pandocCompilerWithTransformM :: ReaderOptions -> WriterOptions                     -> (Pandoc -> Compiler Pandoc)                     -> Compiler (Item String)-pandocCompilerWithTransformM ropt wopt f =-    writePandocWith wopt <$>-        (traverse f =<< readPandocWith ropt =<< getResourceBody)+pandocCompilerWithTransformM ropt wopt f = +    getResourceBody >>= renderPandocWithTransformM ropt wopt f   --------------------------------------------------------------------------------
lib/Hakyll/Web/Pandoc/Biblio.hs view
@@ -12,6 +12,7 @@ {-# LANGUAGE Arrows                     #-} {-# LANGUAGE DeriveDataTypeable         #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings          #-} module Hakyll.Web.Pandoc.Biblio     ( CSL     , cslCompiler@@ -23,34 +24,32 @@   ---------------------------------------------------------------------------------import           Control.Monad            (liftM, replicateM)-import           Data.Binary              (Binary (..))-import           Data.Typeable            (Typeable)+import           Control.Monad                 (liftM)+import           Data.Binary                   (Binary (..))+import qualified Data.ByteString               as B+import qualified Data.ByteString.Lazy          as BL+import qualified Data.Map                      as Map+import qualified Data.Time                     as Time+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 (..))+import           Text.Pandoc                   (Extension (..), Pandoc,+                                                ReaderOptions (..),+                                                enableExtension)+import qualified Text.Pandoc                   as Pandoc+import qualified Text.Pandoc.Citeproc          as Pandoc (processCitations)   ---------------------------------------------------------------------------------data CSL = CSL-    deriving (Show, Typeable)+newtype CSL = CSL {unCSL :: B.ByteString}+    deriving (Binary, Show, Typeable)  ----------------------------------------------------------------------------------instance Binary CSL where-    put CSL = return ()-    get     = return CSL - -------------------------------------------------------------------------------- instance Writable CSL where     -- Shouldn't be written.@@ -59,21 +58,12 @@  -------------------------------------------------------------------------------- cslCompiler :: Compiler (Item CSL)-cslCompiler = makeItem CSL------------------------------------------------------------------------------------newtype Biblio = Biblio [CSL.Reference]-    deriving (Show, Typeable)+cslCompiler = fmap (CSL . BL.toStrict) <$> getResourceLBS   ---------------------------------------------------------------------------------instance Binary Biblio where-    -- Ugly.-    get             = do-        len <- get-        Biblio <$> replicateM len get-    put (Biblio rs) = put (length rs) >> mapM_ put rs+newtype Biblio = Biblio {unBiblio :: B.ByteString}+    deriving (Binary, Show, Typeable)   --------------------------------------------------------------------------------@@ -84,12 +74,7 @@  -------------------------------------------------------------------------------- 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+biblioCompiler = fmap (Biblio . BL.toStrict) <$> getResourceLBS   --------------------------------------------------------------------------------@@ -99,21 +84,45 @@                  -> (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+    -- 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.+    --+    -- So instead, we try treating Pandoc as a black box.  Pandoc can read+    -- specific csl and bilbio files based on metadata keys.+    --+    -- So we load the CSL and Biblio files and pass them to Pandoc using the+    -- ersatz filesystem.+    Pandoc.Pandoc (Pandoc.Meta meta) blocks <- itemBody <$>+        readPandocWith ropt item -    -- 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+    let 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+            }+        biblioMeta = Pandoc.Meta .+            Map.insert "csl" (Pandoc.MetaString "_hakyll/style.csl") .+            Map.insert "bibliography" (Pandoc.MetaString "_hakyll/refs.bib") $+            meta+        errOrPandoc = Pandoc.runPure $ do+            Pandoc.modifyPureState addBiblioFiles+            Pandoc.processCitations $ Pandoc.Pandoc biblioMeta blocks -    return $ fmap (const pandoc') item+    pandoc <- case errOrPandoc of+        Left  e -> compilerThrow ["Error during processCitations: " ++ show e]+        Right x -> return x +    return $ fmap (const pandoc) item++  where+    zeroTime = Time.UTCTime (toEnum 0) 0+ --------------------------------------------------------------------------------+-- | Compiles a markdown file via Pandoc. Requires the .csl and .bib files to be known to the compiler via match statements. pandocBiblioCompiler :: String -> String -> Compiler (Item String) pandocBiblioCompiler cslFileName bibFileName = do     csl <- load $ fromFilePath cslFileName
lib/Hakyll/Web/Pandoc/Binary.hs view
@@ -4,9 +4,6 @@  import           Data.Binary        (Binary (..)) -import qualified Text.CSL           as CSL-import qualified Text.CSL.Reference as REF-import qualified Text.CSL.Style     as STY import           Text.Pandoc  --------------------------------------------------------------------------------@@ -18,7 +15,6 @@ instance Binary Cell instance Binary ColSpan instance Binary ColWidth-instance Binary CSL.Reference instance Binary Citation instance Binary CitationMode instance Binary Format@@ -27,17 +23,9 @@ instance Binary ListNumberStyle instance Binary MathType instance Binary QuoteType-instance Binary REF.CLabel-instance Binary REF.CNum-instance Binary REF.Literal-instance Binary REF.RefDate-instance Binary REF.RefType-instance Binary REF.Season instance Binary Row instance Binary RowHeadColumns instance Binary RowSpan-instance Binary STY.Agent-instance Binary STY.Formatted instance Binary TableBody instance Binary TableFoot instance Binary TableHead
lib/Hakyll/Web/Template/Context.hs view
@@ -60,8 +60,7 @@ import           Data.Semigroup                (Semigroup (..)) #endif import           Data.Time.Clock               (UTCTime (..))-import           Data.Time.Format              (formatTime)-import qualified Data.Time.Format              as TF+import           Data.Time.Format              (formatTime, parseTimeM) import           Data.Time.Locale.Compat       (TimeLocale, defaultTimeLocale) import           Hakyll.Core.Compiler import           Hakyll.Core.Compiler.Internal@@ -463,10 +462,3 @@ missingField :: Context a missingField = Context $ \k _ _ -> noResult $     "Missing field '" ++ k ++ "' in context"--parseTimeM :: Bool -> TimeLocale -> String -> String -> Maybe UTCTime-#if MIN_VERSION_time(1,5,0)-parseTimeM = TF.parseTimeM-#else-parseTimeM _ = TF.parseTime-#endif
src/Init.hs view
@@ -11,7 +11,8 @@ import           Data.List             (foldl', intercalate, isPrefixOf) import           Data.Version          (Version (..)) import           System.Directory      (canonicalizePath, copyFile,-                                        doesFileExist)+                                        doesFileExist,+                                        setPermissions, getPermissions, writable) import           System.Environment    (getArgs, getProgName) import           System.Exit           (exitFailure) import           System.FilePath       (splitDirectories, (</>))@@ -65,6 +66,10 @@                         putStrLn $ "Creating " ++ dst                         makeDirectories dst                         copyFile src dst+                        -- On some systems, the source folder may be readonly,+                        -- and copyFile will therefore create a readonly project...+                        p <- getPermissions dst+                        setPermissions dst (p {writable = True})                      putStrLn $ "Creating " ++ cabalPath                     createCabal cabalPath name
+ tests/Hakyll/Web/Pandoc/Biblio/Tests.hs view
@@ -0,0 +1,66 @@+--------------------------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+module Hakyll.Web.Pandoc.Biblio.Tests+    ( tests+    ) where+++--------------------------------------------------------------------------------+import           System.FilePath            ((</>))+import           Test.Tasty                 (TestTree, testGroup)+import           Test.Tasty.Golden          (goldenVsString)+import qualified Data.ByteString            as B+import qualified Data.ByteString.Lazy       as LBS+++--------------------------------------------------------------------------------+import           Hakyll+import           Hakyll.Core.Runtime+import           Hakyll.Web.Pandoc.Biblio+import qualified Hakyll.Core.Logger         as Logger+import           TestSuite.Util+++--------------------------------------------------------------------------------+tests :: TestTree+tests = testGroup "Hakyll.Web.Pandoc.Biblio.Tests" $+    [ goldenTest01+    ]++--------------------------------------------------------------------------------+goldenTestsDataDir :: FilePath+goldenTestsDataDir = "tests/data/biblio"++--------------------------------------------------------------------------------+goldenTest01 :: TestTree+goldenTest01 =+    goldenVsString+        "biblio01"+        (goldenTestsDataDir </> "biblio01.golden")+        (do+            -- Code lifted from https://github.com/jaspervdj/hakyll-citeproc-example.+            logger <- Logger.new Logger.Error+            let config = testConfiguration { providerDirectory = goldenTestsDataDir }+            _ <- run config logger $ do+                let myPandocBiblioCompiler = do+                        csl <- load "chicago.csl"+                        bib <- load "refs.bib"+                        getResourceBody >>=+                            readPandocBiblio defaultHakyllReaderOptions csl bib >>=+                            return . writePandoc++                match "default.html" $ compile templateCompiler+                match "chicago.csl" $ compile cslCompiler+                match "refs.bib"    $ 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)
tests/TestSuite.hs view
@@ -24,6 +24,7 @@ import qualified Hakyll.Web.Html.RelativizeUrls.Tests import qualified Hakyll.Web.Html.Tests #ifdef USE_PANDOC+import qualified Hakyll.Web.Pandoc.Biblio.Tests import qualified Hakyll.Web.Pandoc.FileType.Tests #endif import qualified Hakyll.Web.Template.Context.Tests@@ -48,6 +49,7 @@     , Hakyll.Web.Html.RelativizeUrls.Tests.tests     , Hakyll.Web.Html.Tests.tests #ifdef USE_PANDOC+    , Hakyll.Web.Pandoc.Biblio.Tests.tests     , Hakyll.Web.Pandoc.FileType.Tests.tests #endif     , Hakyll.Web.Tags.Tests.tests
+ tests/data/biblio/biblio01.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/chicago.csl view
@@ -0,0 +1,648 @@+<?xml version="1.0" encoding="utf-8"?>+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="display-and-sort" page-range-format="chicago">+  <info>+    <title>Chicago Manual of Style 17th edition (author-date)</title>+    <id>http://www.zotero.org/styles/chicago-author-date</id>+    <link href="http://www.zotero.org/styles/chicago-author-date" rel="self"/>+    <link href="http://www.chicagomanualofstyle.org/tools_citationguide.html" rel="documentation"/>+    <author>+      <name>Julian Onions</name>+      <email>julian.onions@gmail.com</email>+    </author>+    <contributor>+      <name>Sebastian Karcher</name>+    </contributor>+    <contributor>+      <name>Richard Karnesky</name>+      <email>karnesky+zotero@gmail.com</email>+      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>+    </contributor>+    <contributor>+      <name>Andrew Dunning</name>+      <email>andrew.dunning@utoronto.ca</email>+      <uri>https://orcid.org/0000-0003-0464-5036</uri>+    </contributor>+    <contributor>+      <name>Matthew Roth</name>+      <email>matthew.g.roth@yale.edu</email>+      <uri> https://orcid.org/0000-0001-7902-6331</uri>+    </contributor>+    <category citation-format="author-date"/>+    <category field="generic-base"/>+    <summary>The author-date variant of the Chicago style</summary>+    <updated>2018-01-24T12:00:00+00:00</updated>+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>+  </info>+  <locale xml:lang="en">+    <terms>+      <term name="editor" form="verb-short">ed.</term>+      <term name="container-author" form="verb">by</term>+      <term name="translator" form="verb-short">trans.</term>+      <term name="editortranslator" form="verb">edited and translated by</term>+      <term name="translator" form="short">trans.</term>+    </terms>+  </locale>+  <macro name="secondary-contributors">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="none">+        <group delimiter=". ">+          <names variable="editor translator" delimiter=". ">+            <label form="verb" text-case="capitalize-first" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+          <names variable="director" delimiter=". ">+            <label form="verb" text-case="capitalize-first" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="container-contributors">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <group prefix=", " delimiter=", ">+          <names variable="container-author" delimiter=", ">+            <label form="verb" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+          <names variable="editor translator" delimiter=", ">+            <label form="verb" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="editor">+    <names variable="editor">+      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>+      <label form="short" prefix=", "/>+    </names>+  </macro>+  <macro name="translator">+    <names variable="translator">+      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>+      <label form="short" prefix=", "/>+    </names>+  </macro>+  <macro name="recipient">+    <choose>+      <if type="personal_communication">+        <choose>+          <if variable="genre">+            <text variable="genre" text-case="capitalize-first"/>+          </if>+          <else>+            <text term="letter" text-case="capitalize-first"/>+          </else>+        </choose>+      </if>+    </choose>+    <names variable="recipient" delimiter=", ">+      <label form="verb" prefix=" " text-case="lowercase" suffix=" "/>+      <name and="text" delimiter=", "/>+    </names>+  </macro>+  <macro name="substitute-title">+    <choose>+      <if type="article-magazine article-newspaper review review-book" match="any">+        <text macro="container-title"/>+      </if>+    </choose>+  </macro>+  <macro name="contributors">+    <group delimiter=". ">+      <names variable="author">+        <name and="text" name-as-sort-order="first" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>+        <label form="short" prefix=", "/>+        <substitute>+          <names variable="editor"/>+          <names variable="translator"/>+          <names variable="director"/>+          <text macro="substitute-title"/>+          <text macro="title"/>+        </substitute>+      </names>+      <text macro="recipient"/>+    </group>+  </macro>+  <macro name="contributors-short">+    <names variable="author">+      <name form="short" and="text" delimiter=", " initialize-with=". "/>+      <substitute>+        <names variable="editor"/>+        <names variable="translator"/>+        <names variable="director"/>+        <text macro="substitute-title"/>+        <text macro="title"/>+      </substitute>+    </names>+  </macro>+  <macro name="interviewer">+    <names variable="interviewer" delimiter=", ">+      <label form="verb" prefix=" " text-case="capitalize-first" suffix=" "/>+      <name and="text" delimiter=", "/>+    </names>+  </macro>+  <macro name="archive">+    <group delimiter=". ">+      <text variable="archive_location" text-case="capitalize-first"/>+      <text variable="archive"/>+      <text variable="archive-place"/>+    </group>+  </macro>+  <macro name="access">+    <group delimiter=". ">+      <choose>+        <if type="graphic report" match="any">+          <text macro="archive"/>+        </if>+        <else-if type="article-journal bill book chapter legal_case legislation motion_picture paper-conference" match="none">+          <text macro="archive"/>+        </else-if>+      </choose>+      <choose>+        <if type="webpage post-weblog" match="any">+          <date variable="issued" form="text"/>+        </if>+      </choose>+      <choose>+        <if variable="issued" match="none">+          <group delimiter=" ">+            <text term="accessed" text-case="capitalize-first"/>+            <date variable="accessed" form="text"/>+          </group>+        </if>+      </choose>+      <choose>+        <if type="legal_case" match="none">+          <choose>+            <if variable="DOI">+              <text variable="DOI" prefix="https://doi.org/"/>+            </if>+            <else>+              <text variable="URL"/>+            </else>+          </choose>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="title">+    <choose>+      <if variable="title" match="none">+        <choose>+          <if type="personal_communication" match="none">+            <text variable="genre" text-case="capitalize-first"/>+          </if>+        </choose>+      </if>+      <else-if type="bill book graphic legislation motion_picture song" match="any">+        <text variable="title" text-case="title" font-style="italic"/>+        <group prefix=" (" suffix=")" delimiter=" ">+          <text term="version"/>+          <text variable="version"/>+        </group>+      </else-if>+      <else-if variable="reviewed-author">+        <choose>+          <if variable="reviewed-title">+            <group delimiter=". ">+              <text variable="title" text-case="title" quotes="true"/>+              <group delimiter=", ">+                <text variable="reviewed-title" text-case="title" font-style="italic" prefix="Review of "/>+                <names variable="reviewed-author">+                  <label form="verb-short" text-case="lowercase" suffix=" "/>+                  <name and="text" delimiter=", "/>+                </names>+              </group>+            </group>+          </if>+          <else>+            <group delimiter=", ">+              <text variable="title" text-case="title" font-style="italic" prefix="Review of "/>+              <names variable="reviewed-author">+                <label form="verb-short" text-case="lowercase" suffix=" "/>+                <name and="text" delimiter=", "/>+              </names>+            </group>+          </else>+        </choose>+      </else-if>+      <else-if type="legal_case interview patent" match="any">+        <text variable="title"/>+      </else-if>+      <else>+        <text variable="title" text-case="title" quotes="true"/>+      </else>+    </choose>+  </macro>+  <macro name="edition">+    <choose>+      <if type="bill book graphic legal_case legislation motion_picture report song" match="any">+        <choose>+          <if is-numeric="edition">+            <group delimiter=" " prefix=". ">+              <number variable="edition" form="ordinal"/>+              <text term="edition" form="short" strip-periods="true"/>+            </group>+          </if>+          <else>+            <text variable="edition" text-case="capitalize-first" prefix=". "/>+          </else>+        </choose>+      </if>+      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <choose>+          <if is-numeric="edition">+            <group delimiter=" " prefix=", ">+              <number variable="edition" form="ordinal"/>+              <text term="edition" form="short"/>+            </group>+          </if>+          <else>+            <text variable="edition" prefix=", "/>+          </else>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="locators">+    <choose>+      <if type="article-journal">+        <choose>+          <if variable="volume">+            <text variable="volume" prefix=" "/>+            <group prefix=" (" suffix=")">+              <choose>+                <if variable="issue">+                  <text variable="issue"/>+                </if>+                <else>+                  <date variable="issued">+                    <date-part name="month"/>+                  </date>+                </else>+              </choose>+            </group>+          </if>+          <else-if variable="issue">+            <group delimiter=" " prefix=", ">+              <text term="issue" form="short"/>+              <text variable="issue"/>+              <date variable="issued" prefix="(" suffix=")">+                <date-part name="month"/>+              </date>+            </group>+          </else-if>+          <else>+            <date variable="issued" prefix=", ">+              <date-part name="month"/>+            </date>+          </else>+        </choose>+      </if>+      <else-if type="legal_case">+        <text variable="volume" prefix=", "/>+        <text variable="container-title" prefix=" "/>+        <text variable="page" prefix=" "/>+      </else-if>+      <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">+        <group prefix=". " delimiter=". ">+          <group>+            <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>+            <number variable="volume" form="numeric"/>+          </group>+          <group>+            <number variable="number-of-volumes" form="numeric"/>+            <text term="volume" form="short" prefix=" " plural="true"/>+          </group>+        </group>+      </else-if>+      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <choose>+          <if variable="page" match="none">+            <group prefix=". ">+              <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>+              <number variable="volume" form="numeric"/>+            </group>+          </if>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="locators-chapter">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <choose>+          <if variable="page">+            <group prefix=", ">+              <text variable="volume" suffix=":"/>+              <text variable="page"/>+            </group>+          </if>+        </choose>+      </if>+    </choose>+  </macro>+  <macro name="locators-article">+    <choose>+      <if type="article-newspaper">+        <group prefix=", " delimiter=", ">+          <group delimiter=" ">+            <text variable="edition"/>+            <text term="edition"/>+          </group>+          <group>+            <text term="section" form="short" suffix=" "/>+            <text variable="section"/>+          </group>+        </group>+      </if>+      <else-if type="article-journal">+        <choose>+          <if variable="volume issue" match="any">+            <text variable="page" prefix=": "/>+          </if>+          <else>+            <text variable="page" prefix=", "/>+          </else>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="point-locators">+    <choose>+      <if variable="locator">+        <choose>+          <if locator="page" match="none">+            <choose>+              <if type="bill book graphic legal_case legislation motion_picture report song" match="any">+                <choose>+                  <if variable="volume">+                    <group>+                      <text term="volume" form="short" suffix=" "/>+                      <number variable="volume" form="numeric"/>+                      <label variable="locator" form="short" prefix=", " suffix=" "/>+                    </group>+                  </if>+                  <else>+                    <label variable="locator" form="short" suffix=" "/>+                  </else>+                </choose>+              </if>+              <else>+                <label variable="locator" form="short" suffix=" "/>+              </else>+            </choose>+          </if>+          <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">+            <number variable="volume" form="numeric" suffix=":"/>+          </else-if>+        </choose>+        <text variable="locator"/>+      </if>+    </choose>+  </macro>+  <macro name="container-prefix">+    <text term="in" text-case="capitalize-first"/>+  </macro>+  <macro name="container-title">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <text macro="container-prefix" suffix=" "/>+      </if>+    </choose>+    <choose>+      <if type="webpage">+        <text variable="container-title" text-case="title"/>+      </if>+      <else-if type="legal_case" match="none">+        <group delimiter=" ">+          <text variable="container-title" text-case="title" font-style="italic"/>+          <choose>+            <if type="post-weblog">+              <text value="(blog)"/>+            </if>+          </choose>+        </group>+      </else-if>+    </choose>+  </macro>+  <macro name="publisher">+    <group delimiter=": ">+      <text variable="publisher-place"/>+      <text variable="publisher"/>+    </group>+  </macro>+  <macro name="date">+    <choose>+      <if variable="issued">+        <group delimiter=" ">+          <date variable="original-date" form="text" date-parts="year" prefix="(" suffix=")"/>+          <date variable="issued">+            <date-part name="year"/>+          </date>+        </group>+      </if>+      <else-if variable="status">+        <text variable="status" text-case="capitalize-first"/>+      </else-if>+      <else>+        <text term="no date" form="short"/>+      </else>+    </choose>+  </macro>+  <macro name="date-in-text">+    <choose>+      <if variable="issued">+        <group delimiter=" ">+          <date variable="original-date" form="text" date-parts="year" prefix="[" suffix="]"/>+          <date variable="issued">+            <date-part name="year"/>+          </date>+        </group>+      </if>+      <else-if variable="status">+        <text variable="status"/>+      </else-if>+      <else>+        <text term="no date" form="short"/>+      </else>+    </choose>+  </macro>+  <macro name="day-month">+    <date variable="issued">+      <date-part name="month"/>+      <date-part name="day" prefix=" "/>+    </date>+  </macro>+  <macro name="collection-title">+    <choose>+      <if match="none" type="article-journal">+        <choose>+          <if match="none" is-numeric="collection-number">+            <group delimiter=", ">+              <text variable="collection-title" text-case="title"/>+              <text variable="collection-number"/>+            </group>+          </if>+          <else>+            <group delimiter=" ">+              <text variable="collection-title" text-case="title"/>+              <text variable="collection-number"/>+            </group>+          </else>+        </choose>+      </if>+    </choose>+  </macro>+  <macro name="collection-title-journal">+    <choose>+      <if type="article-journal">+        <group delimiter=" ">+          <text variable="collection-title"/>+          <text variable="collection-number"/>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="event">+    <group>+      <text term="presented at" suffix=" "/>+      <text variable="event"/>+    </group>+  </macro>+  <macro name="description">+    <choose>+      <if type="interview">+        <group delimiter=". ">+          <text macro="interviewer"/>+          <text variable="medium" text-case="capitalize-first"/>+        </group>+      </if>+      <else-if type="patent">+        <group delimiter=" " prefix=". ">+          <text variable="authority"/>+          <text variable="number"/>+        </group>+      </else-if>+      <else>+        <text variable="medium" text-case="capitalize-first" prefix=". "/>+      </else>+    </choose>+    <choose>+      <if variable="title" match="none"/>+      <else-if type="thesis personal_communication speech" match="any"/>+      <else>+        <group delimiter=" " prefix=". ">+          <text variable="genre" text-case="capitalize-first"/>+          <choose>+            <if type="report">+              <text variable="number"/>+            </if>+          </choose>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="issue">+    <choose>+      <if type="legal_case">+        <text variable="authority" prefix=". "/>+      </if>+      <else-if type="speech">+        <group prefix=". " delimiter=", ">+          <group delimiter=" ">+            <text variable="genre" text-case="capitalize-first"/>+            <text macro="event"/>+          </group>+          <text variable="event-place"/>+          <text macro="day-month"/>+        </group>+      </else-if>+      <else-if type="article-newspaper article-magazine personal_communication" match="any">+        <date variable="issued" form="text" prefix=", "/>+      </else-if>+      <else-if type="patent">+        <group delimiter=", " prefix=", ">+          <group delimiter=" ">+            <!--Needs Localization-->+            <text value="filed"/>+            <date variable="submitted" form="text"/>+          </group>+          <group delimiter=" ">+            <choose>+              <if variable="issued submitted" match="all">+                <text term="and"/>+              </if>+            </choose>+            <!--Needs Localization-->+            <text value="issued"/>+            <date variable="issued" form="text"/>+          </group>+        </group>+      </else-if>+      <else-if type="article-journal" match="any"/>+      <else>+        <group prefix=". " delimiter=", ">+          <choose>+            <if type="thesis">+              <text variable="genre" text-case="capitalize-first"/>+            </if>+          </choose>+          <text macro="publisher"/>+        </group>+      </else>+    </choose>+  </macro>+  <citation et-al-min="4" et-al-use-first="1" disambiguate-add-year-suffix="true" disambiguate-add-names="true" disambiguate-add-givenname="true" givenname-disambiguation-rule="primary-name" collapse="year">+    <layout prefix="(" suffix=")" delimiter="; ">+      <group delimiter=", ">+        <choose>+          <if variable="issued accessed" match="any">+            <group delimiter=" ">+              <text macro="contributors-short"/>+              <text macro="date-in-text"/>+            </group>+          </if>+          <!---comma before forthcoming and n.d.-->+          <else>+            <group delimiter=", ">+              <text macro="contributors-short"/>+              <text macro="date-in-text"/>+            </group>+          </else>+        </choose>+        <text macro="point-locators"/>+      </group>+    </layout>+  </citation>+  <bibliography hanging-indent="true" et-al-min="11" et-al-use-first="7" subsequent-author-substitute="&#8212;&#8212;&#8212;" entry-spacing="0">+    <sort>+      <key macro="contributors"/>+      <key variable="issued"/>+      <key variable="title"/>+    </sort>+    <layout suffix=".">+      <group delimiter=". ">+        <text macro="contributors"/>+        <text macro="date"/>+        <text macro="title"/>+      </group>+      <text macro="description"/>+      <text macro="secondary-contributors" prefix=". "/>+      <text macro="container-title" prefix=". "/>+      <text macro="container-contributors"/>+      <text macro="edition"/>+      <text macro="locators-chapter"/>+      <text macro="collection-title-journal" prefix=", " suffix=", "/>+      <text macro="locators"/>+      <text macro="collection-title" prefix=". "/>+      <text macro="issue"/>+      <text macro="locators-article"/>+      <text macro="access" prefix=". "/>+    </layout>+  </bibliography>+</style>
+ tests/data/biblio/default.html view
@@ -0,0 +1,11 @@+<!doctype html>+<html lang="en">+    <head>+        <meta charset="utf-8">+        <title>$title$</title>+    </head>+    <body>+        <h1>$title$</h1>+        $body$+    </body>+</html>
+ tests/data/biblio/page.markdown view
@@ -0,0 +1,5 @@+---+title: This page cites a paper.+---++I would like to cite one of my favourite papers [@meijer1991functional] here.
+ tests/data/biblio/refs.bib view
@@ -0,0 +1,8 @@+@inproceedings{meijer1991functional,+  title={Functional programming with bananas, lenses, envelopes and barbed wire},+  author={Meijer, Erik and Fokkinga, Maarten and Paterson, Ross},+  booktitle={Conference on Functional Programming Languages and Computer Architecture},+  pages={124--144},+  year={1991},+  organization={Springer}+}