packages feed

hakyll 4.15.1.0 → 4.15.1.1

raw patch · 7 files changed

+359/−124 lines, 7 filesdep ~aesondep ~fsnotifydep ~optparse-applicativePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: aeson, fsnotify, optparse-applicative, pandoc, resourcet, template-haskell, text, vector

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -4,6 +4,16 @@  # Releases +## Hakyll 4.15.1.1 (2022-01-20)++- Extend the documentation for `Hakyll.Core.Identifier` (contribution by+    malteneuss)+- Fix yet another regression caused by new dependency checking code+    (contribution by Laurent P. René de Cotret)+- Bump `pandoc` upper bound to allow 2.17 (contribution by Alexander Batischev)+- Website now points to Hackage rather than its own (often outdated) version of+    the docs (contribution by Jasper Van der Jeugt)+ ## Hakyll 4.15.1.0 (2021-10-25)  - Add `Hakyll.Web.Pandoc.Biblio` functions `readPandocBiblios` and@@ -19,7 +29,6 @@     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) 
hakyll.cabal view
@@ -1,5 +1,5 @@ Name:    hakyll-Version: 4.15.1.0+Version: 4.15.1.1  Synopsis: A static website compiler library Description:@@ -246,7 +246,7 @@     Other-Modules:       Hakyll.Web.Pandoc.Binary     Build-Depends:-      pandoc >= 2.11 && < 2.16+      pandoc >= 2.11 && < 2.18     Cpp-options:       -DUSE_PANDOC @@ -344,4 +344,4 @@     base      >= 4     && < 5,     directory >= 1.0   && < 1.4,     filepath  >= 1.0   && < 1.5,-    pandoc    >= 2.11  && < 2.16+    pandoc    >= 2.11  && < 2.18
lib/Hakyll/Core/Identifier.hs view
@@ -1,12 +1,16 @@ ----------------------------------------------------------------------------------- | An identifier is a type used to uniquely identify an item. An identifier is--- conceptually similar to a file path. Examples of identifiers are:+-- | An identifier is a type used to uniquely name an item. An identifier+-- is similar to a file path, but can contain additional details (e.g. +-- item's version). Examples of identifiers are: -- -- * @posts/foo.markdown@ -- -- * @index@ -- -- * @error/404@+--+-- See 'Identifier' for details.+ {-# LANGUAGE DeriveDataTypeable         #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Hakyll.Core.Identifier@@ -32,6 +36,70 @@   --------------------------------------------------------------------------------+{- | A key data type to identify a compiled 'Hakyll.Core.Item.Item' in the 'Hakyll.Core.Store.Store'.+Conceptually, it's a combination of a file path and a version name.+The version is used only when a file is+compiled within a rule using the 'version' wrapper function+(the same source file+can be compiled into several items in the store, so the version exists to distinguish+them).+Use functions like 'fromFilePath', 'setVersion', 'Hakyll.Core.Metadata.getMatches' to build an 'Identifier'.++=== __Usage Examples__+Normally, compiled items are saved to the store by 'Hakyll.Core.Rules.Rules' with an automatic, implicit identifier+and loaded from the store by the user in another rule with a manual, explicit identifier.++__Identifiers when using match__.+Using 'Hakyll.Core.Rules.match' builds an implicit identifier that corresponds to the expanded, relative path+of the source file on disk (relative to the project directory configured+with 'Hakyll.Core.Configuration.providerDirectory'):++@+-- e.g. file on disk: 'posts\/hakyll.md'+match "posts/*" $ do                                          -- saved with implicit identifier 'posts\/hakyll.md'+    compile pandocCompiler++match "about/*" $ do+    compile $ do+        compiledPost <- load (fromFilePath "posts/hakyll.md") -- load with explicit identifier+        ...+@+Normally, the identifier is only explicitly created to pass to one of the 'Hakyll.Core.Compiler.load' functions.++__Identifiers when using create__.+Using 'Hakyll.Core.Rules.create' (thereby inventing a file path with no underlying file on disk)+builds an implicit identifier that corresponds to the invented file path:++@+create ["index.html"] $ do                                -- saved with implicit identifier 'index.html'+    compile $ makeItem ("Hello world" :: String)++match "about/*" $ do+    compile $ do+        compiledIndex <- load (fromFilePath "index.html") -- load with an explicit identifier+        ...+@++__Identifiers when using versions__.+With 'Hakyll.Core.Rules.version' the same file can be compiled into several items in the store.+A version name is needed to distinguish them:++@+-- e.g. file on disk: 'posts\/hakyll.md'+match "posts/*" $ do                              -- saved with implicit identifier ('posts\/hakyll.md', no-version)+    compile pandocCompiler++match "posts/*" $ version "raw" $ do              -- saved with implicit identifier ('posts\/hakyll.md', version 'raw')+    compile getResourceBody++match "about/*" $ do+    compile $ do+        compiledPost <- load (fromFilePath "posts/hakyll.md")                      -- load no-version version+        rawPost <- load . setVersion (Just "raw") $ fromFilePath "posts/hakyll.md" -- load version 'raw'+    ...+@+Use 'setVersion' to set (or replace) the version of an identifier like @fromFilePath "posts/hakyll.md"@.+-} data Identifier = Identifier     { identifierVersion :: Maybe String     , identifierPath    :: String@@ -62,17 +130,42 @@   ----------------------------------------------------------------------------------- | Parse an identifier from a string+{- | Parse an identifier from a file path string. For example, ++@+-- e.g. file on disk: 'posts\/hakyll.md'+match "posts/*" $ do                                          -- saved with implicit identifier 'posts\/hakyll.md'+    compile pandocCompiler++match "about/*" $ do+    compile $ do+        compiledPost <- load (fromFilePath "posts/hakyll.md") -- load with explicit identifier+        ...+@+-} fromFilePath :: FilePath -> Identifier fromFilePath = Identifier Nothing . normalise   ----------------------------------------------------------------------------------- | Convert an identifier to a relative 'FilePath'+-- | Convert an identifier back to a relative 'FilePath'. toFilePath :: Identifier -> FilePath toFilePath = normalise . identifierPath   --------------------------------------------------------------------------------+{- | Set or override the version of an identifier in order to specify which version of an 'Hakyll.Core.Item.Item' +to 'Hakyll.Core.Compiler.load' from the 'Hakyll.Core.Store.Store'. For example,++@+match "posts/*" $ version "raw" $ do              -- saved with implicit identifier ('posts\/hakyll.md', version 'raw')+    compile getResourceBody++match "about/*" $ do+    compile $ do+        rawPost <- load . setVersion (Just "raw") $ fromFilePath "posts/hakyll.md" -- load version 'raw'+        ...+@+-} setVersion :: Maybe String -> Identifier -> Identifier setVersion v i = i {identifierVersion = v}
lib/Hakyll/Core/Routes.hs view
@@ -1,35 +1,49 @@ ----------------------------------------------------------------------------------- | Once a target is compiled, the user usually wants to save it to the disk.--- This is where the 'Routes' type comes in; it determines where a certain--- target should be written.------ Suppose we have an item @foo\/bar.markdown@. We can render this to--- @foo\/bar.html@ using:------ > route "foo/bar.markdown" (setExtension ".html")------ If we do not want to change the extension, we can use 'idRoute', the simplest--- route available:------ > route "foo/bar.markdown" idRoute------ That will route @foo\/bar.markdown@ to @foo\/bar.markdown@.------ Note that the extension says nothing about the content! If you set the--- extension to @.html@, it is your own responsibility to ensure that the--- content is indeed HTML.------ Finally, some special cases:------ * If there is no route for an item, this item will not be routed, so it will---   not appear in your site directory.------ * If an item matches multiple routes, the first rule will be chosen.+{- | 'Routes' is part of the 'Hakyll.Core.Rules.Rules' processing pipeline.+It determines if and where the compilation result of the underlying+'Hakyll.Core.Item.Item' being processed is written out to+(relative to the destination directory as configured in+'Hakyll.Core.Configuration.destinationDirectory').++* __If there is no route for an item, the compiled item won't be written+out to a file__ and so won't appear in the destination (site) directory.++* If an item matches multiple routes, the first route will be chosen.++__Examples__++Suppose we have a markdown file @posts\/hakyll.md@. We can route its+compilation result to @posts\/hakyll.html@ using 'setExtension':++> -- file on disk: '<project-directory>/posts/hakyll.md'+> match "posts/*" $ do+>     -- compilation result is written to '<destination-directory>/posts/hakyll.html'+>     route (setExtension "html")+>     compile pandocCompiler+Hint: You can configure the destination directory with+'Hakyll.Core.Configuration.destinationDirectory'.++If we do not want to change the extension, we can replace 'setExtension' with+'idRoute' (the simplest route available):++>     -- compilation result is written to '<destination-directory>/posts/hakyll.md'+>     route idRoute++That will route the file @posts\/hakyll.md@ from the project directory to+@posts\/hakyll.md@ in the destination directory.++Note: __The extension of the destination filepath says nothing about the+content!__ If you set the extension to @.html@, you have to ensure that the+compilation result is indeed HTML (for example with the+'Hakyll.Web.Pandoc.pandocCompiler' to transform Markdown to HTML).++Take a look at the built-in routes here for detailed usage examples.+-} {-# LANGUAGE CPP        #-} {-# LANGUAGE Rank2Types #-} module Hakyll.Core.Routes-    ( UsedMetadata-    , Routes+    ( Routes+    , UsedMetadata     , runRoutes     , idRoute     , setExtension@@ -109,30 +123,60 @@   ----------------------------------------------------------------------------------- | A route that uses the identifier as filepath. For example, the target with--- ID @foo\/bar@ will be written to the file @foo\/bar@.+{- | An "identity" route that interprets the identifier (of the item being+processed) as the destination filepath. This identifier is normally the+filepath of the source file being processed.+See 'Hakyll.Core.Identifier.Identifier' for details.++=== __Examples__+__Route when using match__++> -- e.g. file on disk: '<project-directory>/posts/hakyll.md'+>+> -- 'hakyll.md' source file implicitly gets filepath as identifier:+> -- 'posts/hakyll.md'+> match "posts/*" $ do+>+>     -- compilation result is written to '<destination-directory>/posts/hakyll.md'+>     route idRoute+>+>     compile getResourceBody+-} idRoute :: Routes idRoute = customRoute toFilePath   ----------------------------------------------------------------------------------- | Set (or replace) the extension of a route.------ Example:------ > runRoutes (setExtension "html") "foo/bar"------ Result:------ > Just "foo/bar.html"------ Example:------ > runRoutes (setExtension "html") "posts/the-art-of-trolling.markdown"------ Result:------ > Just "posts/the-art-of-trolling.html"+{- | Create a route like 'idRoute' that interprets the identifier (of the item+being processed) as the destination filepath but also sets (or replaces) the+extension suffix of that path. This identifier is normally the filepath of the+source file being processed.+See 'Hakyll.Core.Identifier.Identifier' for details.++=== __Examples__+__Route with an existing extension__++> -- e.g. file on disk: '<project-directory>/posts/hakyll.md'+>+> -- 'hakyll.md' source file implicitly gets filepath as identifier:+> -- 'posts/hakyll.md'+> match "posts/*" $ do+>+>     -- compilation result is written to '<destination-directory>/posts/hakyll.html'+>     route (setExtension "html")+>+>     compile pandocCompiler++__Route without an existing extension__++> -- implicitly gets identifier: 'about'+> create ["about"] $ do+>+>     -- compilation result is written to '<destination-directory>/about.html'+>     route (setExtension "html")+>+>     compile $ makeItem ("Hello world" :: String)+-} setExtension :: String -> Routes setExtension extension = customRoute $     (`replaceExtension` extension) . toFilePath@@ -147,31 +191,94 @@   ----------------------------------------------------------------------------------- | Create a custom route. This should almost always be used with--- 'matchRoute'-customRoute :: (Identifier -> FilePath) -> Routes+{- | Create a route where the destination filepath is built with the given+construction function. The provided identifier for that function is normally the+filepath of the source file being processed.+See 'Hakyll.Core.Identifier.Identifier' for details.++=== __Examples__+__Route that appends a custom extension__++> -- e.g. file on disk: '<project-directory>/posts/hakyll.md'+>+> -- 'hakyll.md' source file implicitly gets filepath as identifier:+> -- 'posts/hakyll.md'+> match "posts/*" $ do+>+>     -- compilation result is written to '<destination-directory>/posts/hakyll.md.html'+>     route $ customRoute ((<> ".html") . toFilePath)+>+>     compile pandocCompiler+Note that the last part of the destination filepath becomes @.md.html@+-}+customRoute :: (Identifier -> FilePath) -- ^ Destination filepath construction function+            -> Routes                   -- ^ Resulting route customRoute f = Routes $ const $ \id' -> return (Just (f id'), False)   ----------------------------------------------------------------------------------- | A route that always gives the same result. Obviously, you should only use--- this for a single compilation rule.+{- | Create a route that writes the compiled item to the given destination+filepath (ignoring any identifier or other data about the item being processed).+Warning: you should __use a specific destination path only for a single file in+a single compilation rule__. Otherwise it's unclear which of the contents should+be written to that route.++=== __Examples__+__Route to a specific filepath__++> -- implicitly gets identifier: 'main' (ignored on next line)+> create ["main"] $ do+>+>     -- compilation result is written to '<destination-directory>/index.html'+>     route $ constRoute "index.html"+>+>     compile $ makeItem ("<h1>Hello World</h1>" :: String)+-} constRoute :: FilePath -> Routes constRoute = customRoute . const   ----------------------------------------------------------------------------------- | Create a gsub route------ Example:------ > runRoutes (gsubRoute "rss/" (const "")) "tags/rss/bar.xml"------ Result:------ > Just "tags/bar.xml"-gsubRoute :: String              -- ^ Pattern-          -> (String -> String)  -- ^ Replacement+{- | Create a "substituting" route that searches for substrings (in the+underlying identifier) that match the given pattern and transforms them+according to the given replacement function.+The identifier here is that of the underlying item being processed and is+interpreted as an destination filepath. It's normally the filepath of the+source file being processed.+See 'Hakyll.Core.Identifier.Identifier' for details.++Hint: The name "gsub" comes from a similar function in +[R](https://www.r-project.org) and can be read as "globally substituting" +(globally in the Unix sense of repeated, not just once).++=== __Examples__+__Route that replaces part of the filepath__++> -- e.g. file on disk: '<project-directory>/posts/hakyll.md'+>+> -- 'hakyll.md' source file implicitly gets filepath as identifier:+> -- 'posts/hakyll.md'+> match "posts/*" $ do+>+>     -- compilation result is written to '<destination-directory>/haskell/hakyll.md'+>     route $ gsubRoute "posts/" (const "haskell/")+>+>     compile getResourceBody+Note that "posts\/" is replaced with "haskell\/" in the destination filepath.++__Route that removes part of the filepath__++> -- implicitly gets identifier: 'tags/rss/bar.xml'+> create ["tags/rss/bar.xml"] $ do+>+>     -- compilation result is written to '<destination-directory>/tags/bar.xml'+>     route $ gsubRoute "rss/" (const "")+>+>     compile ...+Note that "rss\/" is removed from the destination filepath.+-}+gsubRoute :: String              -- ^ Pattern to repeatedly match against in the underlying identifier+          -> (String -> String)  -- ^ Replacement function to apply to the matched substrings           -> Routes              -- ^ Resulting route gsubRoute pattern replacement = customRoute $     normalise . replaceAll pattern (replacement . removeWinPathSeparator) . removeWinPathSeparator . toFilePath@@ -182,27 +289,74 @@   ----------------------------------------------------------------------------------- | Get access to the metadata in order to determine the route-metadataRoute :: (Metadata -> Routes) -> Routes+{- | Wrapper function around other route construction functions to get+access to the metadata (of the underlying item being processed) and use that for+the destination filepath construction.+Warning: you have to __ensure that the accessed metadata fields actually+exists__.++=== __Examples__+__Route that uses a custom slug markdown metadata field__++To create a search engine optimized yet human-readable url, we can introduce+a [slug](https://en.wikipedia.org/wiki/Clean_URL#Slug) metadata field to our+files, e.g. like in the following Markdown file: 'posts\/hakyll.md'++> ---+> title: Hakyll Post+> slug: awesome-post+> ...+> ---+> In this blog post we learn about Hakyll ...++Then we can construct a route whose destination filepath is based on that field:++> match "posts/*" $ do+>+>     -- compilation result is written to '<destination-directory>/awesome-post.html'+>     route $ metadataRoute $ \meta ->+>         constRoute $ fromJust (lookupString "slug" meta) <> ".html"+>+>     compile pandocCompiler+Note how we wrap 'metadataRoute' around the 'constRoute' function and how the+slug is looked up from the markdown field to construct the destination filepath.+You can use helper functions like 'Hakyll.Core.Metadata.lookupString' to access+a specific metadata field.+-}+metadataRoute :: (Metadata -> Routes) -- ^ Wrapped route construction function+              -> Routes               -- ^ Resulting route metadataRoute f = Routes $ \r i -> do     metadata <- resourceMetadata (routesProvider r) (routesUnderlying r)     unRoutes (f metadata) r i   ----------------------------------------------------------------------------------- | Compose routes so that @f \`composeRoutes\` g@ is more or less equivalent--- with @g . f@.------ Example:------ > let routes = gsubRoute "rss/" (const "") `composeRoutes` setExtension "xml"--- > in runRoutes routes "tags/rss/bar"------ Result:------ > Just "tags/bar.xml"------ If the first route given fails, Hakyll will not apply the second route.+{- | Compose two routes where __the first route is applied before the second__.+So @f \`composeRoutes\` g@ is more or less equivalent with @g . f@.++Warning: If the first route fails (e.g. when using 'matchRoute'), Hakyll will+not apply the second route (if you need Hakyll to try the second route,+use '<>' on 'Routes' instead).++=== __Examples__+__Route that applies two transformations__++> -- e.g. file on disk: '<project-directory>/posts/hakyll.md'+>+> -- 'hakyll.md' source file implicitly gets filepath as identifier:+> -- 'posts/hakyll.md'+> match "posts/*" $ do+>+>     -- compilation result is written to '<destination-directory>/hakyll.html'+>     route $ gsubRoute "posts/" (const "") `composeRoutes` setExtension "html"+>+>     compile pandocCompiler+The identifier here is that of the underlying item being processed and is+interpreted as an destination filepath.+See 'Hakyll.Core.Identifier.Identifier' for details.+Note how we first remove the "posts\/" substring from that destination filepath+ with 'gsubRoute' and then replace the extension with 'setExtension'.+-} composeRoutes :: Routes  -- ^ First route to apply               -> Routes  -- ^ Second route to apply               -> Routes  -- ^ Resulting route
lib/Hakyll/Core/Runtime.hs view
@@ -334,7 +334,10 @@              -- Progress has been made if at least one of the              -- requirements can move forwards at the next pass-            let progress | length deps < length reqs = Progressed-                         | otherwise                 = Idled+            -- In some cases, dependencies have been processed in parallel in which case `deps` +            -- can be empty, and we can progress to the next stage. See issue #907+            let progress | null deps    = Progressed+                         | deps == reqs = Idled+                         | otherwise    = Progressed              return progress
lib/Hakyll/Web/Pandoc.hs view
@@ -109,14 +109,14 @@ -------------------------------------------------------------------------------- -- | 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 +-- 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) +renderPandocWithTransform ropt wopt f =+    renderPandocWithTransformM ropt wopt (return . f)   --------------------------------------------------------------------------------@@ -128,8 +128,8 @@                     -> (Pandoc -> Compiler Pandoc)                     -> Item String                     -> Compiler (Item String)-renderPandocWithTransformM ropt wopt f i = -    writePandocWith wopt <$> (traverse f =<< readPandocWith ropt i) +renderPandocWithTransformM ropt wopt f i =+    writePandocWith wopt <$> (traverse f =<< readPandocWith ropt i)   --------------------------------------------------------------------------------@@ -166,7 +166,7 @@ pandocCompilerWithTransformM :: ReaderOptions -> WriterOptions                     -> (Pandoc -> Compiler Pandoc)                     -> Compiler (Item String)-pandocCompilerWithTransformM ropt wopt f = +pandocCompilerWithTransformM ropt wopt f =     getResourceBody >>= renderPandocWithTransformM ropt wopt f  @@ -190,4 +190,10 @@     , -- We want to have hightlighting by default, to be compatible with earlier       -- Hakyll releases       writerHighlightStyle = Just pygments+    , -- Do not word-wrap produced HTML, and do not undo any word-wrapping+      -- that's already present in the markup. This is how Pandoc operated+      -- prior to 2.17, but the behaviour was changed for consistency with+      -- other Pandoc writers. We retain the old behaviour because it spares us+      -- the trouble of updating our golden tests.+      writerWrapText = WrapPreserve     }
web/site.hs view
@@ -26,16 +26,6 @@         route   idRoute         compile copyFileCompiler -    -- Haddock stuff-    match "reference/**.html" $ do-        route   idRoute-        compile $ fmap (withUrls hackage) <$> getResourceString--    -- Haddock stuff-    match ("reference/**" `mappend` complement "**.html") $ do-        route   idRoute-        compile copyFileCompiler-     -- Pages     match "*.markdown" $ do         route   $ setExtension "html"@@ -84,26 +74,6 @@                       \_site/* \                       \jaspervdj@jaspervdj.be:jaspervdj.be/hakyll/"     }-------------------------------------------------------------------------------------- | Turns------ > /usr/share/doc/ghc/html/libraries/base-4.6.0.0/Data-String.html------ into------ > http://hackage.haskell.org/packages/archive/base/4.6.0.0/doc/html/Data-String.html-hackage :: String -> String-hackage url-    | "/usr" `isPrefixOf` url =-        "http://hackage.haskell.org/packages/archive/" ++-        packageName ++ "/" ++ version' ++ "/doc/html/" ++ baseName-    | otherwise               = url-  where-    (packageName, version')  = second (drop 1) $ break (== '-') package-    (baseName : package : _) = map dropTrailingPathSeparator $-        reverse $ splitPath url   --------------------------------------------------------------------------------