hakyll 4.10.0.0 → 4.11.0.0
raw patch · 14 files changed
+279/−79 lines, 14 filesdep +file-embeddep −system-filepathdep ~QuickCheckdep ~basedep ~binarynew-component:exe:hakyll-websitePVP ok
version bump matches the API change (PVP)
Dependencies added: file-embed
Dependencies removed: system-filepath
Dependency ranges changed: QuickCheck, base, binary, http-types, pandoc, pandoc-citeproc, tasty, tasty-hunit
API changes (from Hackage documentation)
+ Hakyll.Web.Template: readTemplateElems :: String -> [TemplateElement]
+ Hakyll.Web.Template: template :: [TemplateElement] -> Template
Files
- CHANGELOG.md +15/−0
- hakyll.cabal +60/−37
- lib/Hakyll/Core/Identifier/Pattern.hs +4/−2
- lib/Hakyll/Web/Feed.hs +34/−14
- lib/Hakyll/Web/Pandoc/Biblio.hs +4/−1
- lib/Hakyll/Web/Template.hs +2/−0
- lib/Hakyll/Web/Template/Internal.hs +0/−1
- tests/Hakyll/Core/Identifier/Tests.hs +1/−0
- tests/Hakyll/Core/Provider/Tests.hs +2/−2
- tests/Hakyll/Core/Rules/Tests.hs +2/−2
- tests/Hakyll/Core/Store/Tests.hs +7/−7
- tests/Hakyll/Core/UnixFilter/Tests.hs +7/−7
- tests/Hakyll/Web/Html/Tests.hs +6/−6
- web/site.hs +135/−0
CHANGELOG.md view
@@ -4,6 +4,21 @@ # Releases +## Hakyll 4.11.0.0++- Bump binary to 0.9+- Bump pandoc to 2.1+- Bump pandoc-citeproc to 0.13+- Bump http-types to 0.11+- Bump QuickCheck to 2.11+- Bump tasty to 1.0+- Bump tasty-hunit to 0.10+- Remove system-filepath dependency+- Embed feed templates rather than using data-files (contribution by Roman+ Kuznetsov)+- Fix pthread link error on GHC-8.2.2 (contribution by Shinya Yamaguchi)+- Extend capture with Regex handling (contribution by frederik-h)+ ## Hakyll 4.10.0.0 - Bump Pandoc to 2.0 (contribution by Vaibhav Sagar)
hakyll.cabal view
@@ -1,5 +1,5 @@ Name: hakyll-Version: 4.10.0.0+Version: 4.11.0.0 Synopsis: A static website compiler library Description:@@ -37,7 +37,7 @@ License-File: LICENSE Category: Web -Cabal-Version: >= 1.8+Cabal-Version: >= 1.10 Build-Type: Simple Data-Dir: data @@ -56,10 +56,6 @@ example/index.html example/about.rst example/contact.markdown- templates/atom-item.xml- templates/atom.xml- templates/rss-item.xml- templates/rss.xml Extra-source-files: CHANGELOG.md@@ -77,6 +73,10 @@ tests/data/strip.html.out tests/data/template.html tests/data/template.html.out+ data/templates/atom-item.xml+ data/templates/atom.xml+ data/templates/rss-item.xml+ data/templates/rss.xml Source-Repository head Type: git@@ -94,9 +94,15 @@ Description: Include external link checking Default: True +Flag buildWebsite+ Description: Build the hakyll website+ Default: False+ Manual: True+ Library- Ghc-Options: -Wall- Hs-Source-Dirs: lib+ Ghc-Options: -Wall+ Hs-Source-Dirs: lib+ Default-language: Haskell2010 Exposed-Modules: Hakyll@@ -154,7 +160,7 @@ Build-Depends: base >= 4.8 && < 5,- binary >= 0.5 && < 0.9,+ binary >= 0.5 && < 0.10, blaze-html >= 0.5 && < 0.10, blaze-markup >= 0.5.1 && < 0.9, bytestring >= 0.9 && < 0.11,@@ -168,8 +174,8 @@ mtl >= 1 && < 2.3, network >= 2.6 && < 2.7, network-uri >= 2.6 && < 2.7,- pandoc >= 2.0.5 && < 2.1,- pandoc-citeproc >= 0.12.1.1 && < 0.13,+ pandoc >= 2.0.5 && < 2.2,+ pandoc-citeproc >= 0.13 && < 0.14, parsec >= 3.0 && < 3.2, process >= 1.6 && < 1.7, random >= 1.0 && < 1.2,@@ -184,16 +190,16 @@ unordered-containers >= 0.2 && < 0.3, vector >= 0.11 && < 0.13, yaml >= 0.8.11 && < 0.9,- optparse-applicative >= 0.12 && < 0.15+ optparse-applicative >= 0.12 && < 0.15,+ file-embed >= 0.0.10.1 && < 0.0.11 If flag(previewServer) Build-depends: wai >= 3.2 && < 3.3, warp >= 3.2 && < 3.3, wai-app-static >= 3.1 && < 3.2,- http-types >= 0.9 && < 0.10,- fsnotify >= 0.2 && < 0.3,- system-filepath >= 0.4.6 && <= 0.5+ http-types >= 0.9 && < 0.12,+ fsnotify >= 0.2 && < 0.3 Cpp-options: -DPREVIEW_SERVER Other-modules:@@ -202,8 +208,7 @@ If flag(watchServer) Build-depends:- fsnotify >= 0.2 && < 0.3,- system-filepath >= 0.4.6 && <= 0.5+ fsnotify >= 0.2 && < 0.3 Cpp-options: -DWATCH_SERVER Other-modules:@@ -212,15 +217,16 @@ If flag(checkExternal) Build-depends: http-conduit >= 2.2 && < 2.3,- http-types >= 0.7 && < 0.10+ http-types >= 0.7 && < 0.12 Cpp-options: -DCHECK_EXTERNAL Test-suite hakyll-tests- Type: exitcode-stdio-1.0- Hs-source-dirs: tests- Main-is: TestSuite.hs- Ghc-options: -Wall+ Type: exitcode-stdio-1.0+ Hs-source-dirs: tests+ Main-is: TestSuite.hs+ Ghc-options: -Wall -threaded+ Default-language: Haskell2010 Other-modules: Hakyll.Core.Dependencies.Tests@@ -243,13 +249,13 @@ Build-Depends: hakyll,- QuickCheck >= 2.8 && < 2.11,- tasty >= 0.11 && < 0.12,- tasty-hunit >= 0.9 && < 0.10,+ QuickCheck >= 2.8 && < 2.12,+ tasty >= 0.11 && < 1.1,+ tasty-hunit >= 0.9 && < 0.11, tasty-quickcheck >= 0.8 && < 0.10, -- Copy pasted from hakyll dependencies: base >= 4.8 && < 5,- binary >= 0.5 && < 0.9,+ binary >= 0.5 && < 0.10, blaze-html >= 0.5 && < 0.10, blaze-markup >= 0.5.1 && < 0.9, bytestring >= 0.9 && < 0.11,@@ -263,8 +269,8 @@ mtl >= 1 && < 2.3, network >= 2.6 && < 2.7, network-uri >= 2.6 && < 2.7,- pandoc >= 2.0.5 && < 2.1,- pandoc-citeproc >= 0.12.1.1 && < 0.13,+ pandoc >= 2.0.5 && < 2.2,+ pandoc-citeproc >= 0.13 && < 0.14, parsec >= 3.0 && < 3.2, process >= 1.6 && < 1.7, random >= 1.0 && < 1.2,@@ -286,30 +292,29 @@ wai >= 3.2 && < 3.3, warp >= 3.2 && < 3.3, wai-app-static >= 3.1 && < 3.2,- http-types >= 0.9 && < 0.10,- fsnotify >= 0.2 && < 0.3,- system-filepath >= 0.4.6 && <= 0.5+ http-types >= 0.9 && < 0.12,+ fsnotify >= 0.2 && < 0.3 Cpp-options: -DPREVIEW_SERVER If flag(watchServer) Build-depends:- fsnotify >= 0.2 && < 0.3,- system-filepath >= 0.4.6 && <= 0.5+ fsnotify >= 0.2 && < 0.3 Cpp-options: -DWATCH_SERVER If flag(checkExternal) Build-depends: http-conduit >= 2.2 && < 2.3,- http-types >= 0.7 && < 0.10+ http-types >= 0.7 && < 0.12 Cpp-options: -DCHECK_EXTERNAL Executable hakyll-init- Ghc-options: -Wall- Hs-source-dirs: src- Main-is: Init.hs+ Main-is: Init.hs+ Ghc-options: -Wall -threaded+ Hs-source-dirs: src+ Default-language: Haskell2010 Other-modules: Paths_hakyll@@ -319,3 +324,21 @@ base >= 4 && < 5, directory >= 1.0 && < 1.4, filepath >= 1.0 && < 1.5++Executable hakyll-website+ Main-is: site.hs+ Ghc-options: -Wall -threaded+ Hs-source-dirs: web+ Default-language: Haskell2010++ If flag(buildWebsite)+ Buildable: True+ Else+ Buildable: False++ Build-depends:+ hakyll,+ base >= 4 && < 5,+ directory >= 1.0 && < 1.4,+ filepath >= 1.0 && < 1.5,+ pandoc >= 2.0.5 && < 2.2
lib/Hakyll/Core/Identifier/Pattern.hs view
@@ -27,7 +27,7 @@ -- * @\"foo\/*.html\"@ will match all HTML files in the @\"foo\/\"@ directory. -- -- The 'capture' function allows the user to get access to the elements captured--- by the capture elements in the pattern.+-- by the capture elements in a glob or regex pattern. module Hakyll.Core.Identifier.Pattern ( -- * The pattern type Pattern@@ -260,9 +260,11 @@ ----------------------------------------------------------------------------------- | Match a glob against a pattern, generating a list of captures+-- | Match a glob or regex pattern against an identifier, generating a list of captures capture :: Pattern -> Identifier -> Maybe [String] capture (Glob p) i = capture' p (toFilePath i)+capture (Regex pat) i = Just groups+ where (_, _, _, groups) = ((toFilePath i) =~ pat) :: (String, String, String, [String]) capture _ _ = Nothing
lib/Hakyll/Web/Feed.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE TemplateHaskell #-}+ -------------------------------------------------------------------------------- -- | A Module that allows easy rendering of RSS feeds. --@@ -25,19 +27,38 @@ -------------------------------------------------------------------------------- import Hakyll.Core.Compiler-import Hakyll.Core.Compiler.Internal import Hakyll.Core.Item-import Hakyll.Core.Util.String (replaceAll)+import Hakyll.Core.Util.String (replaceAll) import Hakyll.Web.Template import Hakyll.Web.Template.Context import Hakyll.Web.Template.List ---------------------------------------------------------------------------------import Paths_hakyll+import Data.FileEmbed (embedFile)+import qualified Data.Text as T+import qualified Data.Text.Encoding as T --------------------------------------------------------------------------------+rssTemplate :: String+rssTemplate = T.unpack $+ T.decodeUtf8 $(embedFile "data/templates/rss.xml")++rssItemTemplate :: String+rssItemTemplate = T.unpack $+ T.decodeUtf8 $(embedFile "data/templates/rss-item.xml")++atomTemplate :: String+atomTemplate = T.unpack $+ T.decodeUtf8 $(embedFile "data/templates/atom.xml")++atomItemTemplate :: String+atomItemTemplate = T.unpack $+ T.decodeUtf8 $(embedFile "data/templates/atom-item.xml")+++-------------------------------------------------------------------------------- -- | This is a data structure to keep the configuration of a feed. data FeedConfiguration = FeedConfiguration { -- | Title of the feed.@@ -55,15 +76,15 @@ -------------------------------------------------------------------------------- -- | Abstract function to render any feed.-renderFeed :: FilePath -- ^ Feed template- -> FilePath -- ^ Item template+renderFeed :: String -- ^ Default feed template+ -> String -- ^ Default item template -> FeedConfiguration -- ^ Feed configuration -> Context String -- ^ Context for the items -> [Item String] -- ^ Input items -> Compiler (Item String) -- ^ Resulting item-renderFeed feedPath itemPath config itemContext items = do- feedTpl <- loadTemplate feedPath- itemTpl <- loadTemplate itemPath+renderFeed defFeed defItem config itemContext items = do+ feedTpl <- readTemplateFile defFeed+ itemTpl <- readTemplateFile defItem protectedItems <- mapM (applyFilter protectCDATA) items body <- makeItem =<< applyTemplateList itemTpl itemContext' protectedItems@@ -73,10 +94,6 @@ applyFilter tr str = return $ fmap tr str protectCDATA :: String -> String protectCDATA = replaceAll "]]>" (const "]]>")- -- Auxiliary: load a template from a datafile- loadTemplate path = do- file <- compilerUnsafeIO $ getDataFileName path- unsafeReadTemplateFile file itemContext' = mconcat [ itemContext@@ -105,7 +122,10 @@ ListField _ _ -> fail "Hakyll.Web.Feed.renderFeed: Internal error" StringField s -> return s + readTemplateFile :: String -> Compiler Template+ readTemplateFile value = pure $ template $ readTemplateElems value + -------------------------------------------------------------------------------- -- | Render an RSS feed with a number of items. renderRss :: FeedConfiguration -- ^ Feed configuration@@ -113,7 +133,7 @@ -> [Item String] -- ^ Feed items -> Compiler (Item String) -- ^ Resulting feed renderRss config context = renderFeed- "templates/rss.xml" "templates/rss-item.xml" config+ rssTemplate rssItemTemplate config (makeItemContext "%a, %d %b %Y %H:%M:%S UT" context) @@ -124,7 +144,7 @@ -> [Item String] -- ^ Feed items -> Compiler (Item String) -- ^ Resulting feed renderAtom config context = renderFeed- "templates/atom.xml" "templates/atom-item.xml" config+ atomTemplate atomItemTemplate config (makeItemContext "%Y-%m-%dT%H:%M:%SZ" context)
lib/Hakyll/Web/Pandoc/Biblio.hs view
@@ -84,7 +84,10 @@ biblioCompiler :: Compiler (Item Biblio) biblioCompiler = do filePath <- toFilePath <$> getUnderlying- makeItem =<< unsafeCompiler (Biblio <$> CSL.readBiblioFile filePath)+ makeItem =<< unsafeCompiler (Biblio <$> CSL.readBiblioFile idpred filePath)+ where+ -- This is a filter on citations. We include all citations.+ idpred = const True --------------------------------------------------------------------------------
lib/Hakyll/Web/Template.hs view
@@ -140,6 +140,8 @@ -- module Hakyll.Web.Template ( Template+ , template+ , readTemplateElems , templateBodyCompiler , templateCompiler , applyTemplate
lib/Hakyll/Web/Template/Internal.hs view
@@ -200,4 +200,3 @@ unsafeReadTemplateFile file = do tpl <- unsafeCompiler $ readFile file pure $ template $ readTemplateElemsFile file tpl-
tests/Hakyll/Core/Identifier/Tests.hs view
@@ -42,6 +42,7 @@ , Just ["lol", "fun/large"] @=? capture "*cat/**.jpg" "lolcat/fun/large.jpg" , Just [] @=? capture "\\*.jpg" "*.jpg" , Nothing @=? capture "\\*.jpg" "foo.jpg"+ , Just ["xyz","42"] @=? capture (fromRegex "cat-([a-z]+)/foo([0-9]+).jpg") "cat-xyz/foo42.jpg" ]
tests/Hakyll/Core/Provider/Tests.hs view
@@ -9,7 +9,7 @@ import Hakyll.Core.Metadata import Hakyll.Core.Provider import Test.Tasty (TestTree, testGroup)-import Test.Tasty.HUnit (Assertion, assert, testCase, (@=?))+import Test.Tasty.HUnit (Assertion, testCase, (@=?)) import TestSuite.Util @@ -25,7 +25,7 @@ case01 = do store <- newTestStore provider <- newTestProvider store- assert $ resourceExists provider "example.md"+ True @=? resourceExists provider "example.md" metadata <- resourceMetadata provider "example.md" Just "An example" @=? lookupString "title" metadata
tests/Hakyll/Core/Rules/Tests.hs view
@@ -20,7 +20,7 @@ import Hakyll.Web.Pandoc import System.FilePath ((</>)) import Test.Tasty (TestTree, testGroup)-import Test.Tasty.HUnit (Assertion, assert, (@=?))+import Test.Tasty.HUnit (Assertion, (@=?)) import TestSuite.Util @@ -50,7 +50,7 @@ checkRoute "example.mv1" (sv "mv1" "example.md") checkRoute "example.mv2" (sv "mv2" "example.md") checkRoute "food/example.md" (sv "metadataMatch" "example.md")- readIORef ioref >>= assert+ readIORef ioref >>= (True @=?) cleanTestEnv where sv g = setVersion (Just g)
tests/Hakyll/Core/Store/Tests.hs view
@@ -63,11 +63,11 @@ -- Store a string and try to fetch an int Store.set store ["foo", "bar"] ("qux" :: String) value <- Store.get store ["foo", "bar"] :: IO (Store.Result Int)- H.assert $ case value of- Store.WrongType e t ->- e == typeOf (undefined :: Int) &&- t == typeOf (undefined :: String)- _ -> False+ case value of+ Store.WrongType e t -> do+ typeOf (undefined :: Int) H.@=? e+ typeOf (undefined :: String) H.@=? t+ _ -> H.assertFailure "Expecting WrongType" cleanTestEnv @@ -78,6 +78,6 @@ Store.set store ["foo", "bar"] ("qux" :: String) good <- Store.isMember store ["foo", "bar"] bad <- Store.isMember store ["foo", "baz"]- H.assert good- H.assert (not bad)+ True H.@=? good+ False H.@=? bad cleanTestEnv
tests/Hakyll/Core/UnixFilter/Tests.hs view
@@ -39,7 +39,7 @@ provider <- newTestProvider store output <- testCompilerDone store provider testMarkdown compiler expected <- testCompilerDone store provider testMarkdown getResourceString- H.assert $ rev (itemBody expected) == lines (itemBody output)+ rev (itemBody expected) H.@=? lines (itemBody output) cleanTestEnv where compiler = getResourceString >>= withItemBody (unixFilter "rev" [])@@ -52,9 +52,9 @@ store <- newTestStore provider <- newTestProvider store result <- testCompiler store provider testMarkdown compiler- H.assert $ case result of- CompilerError es -> any ("exit code" `isInfixOf`) es- _ -> False+ case result of+ CompilerError es -> True H.@=? any ("exit code" `isInfixOf`) es+ _ -> H.assertFailure "Expecting CompilerError" cleanTestEnv where compiler = getResourceString >>= withItemBody (unixFilter "false" [])@@ -66,9 +66,9 @@ store <- newTestStore provider <- newTestProvider store result <- testCompiler store provider testMarkdown compiler- H.assert $ case result of- CompilerError es -> any ("invalid option" `isInfixOf`) es- _ -> False+ case result of+ CompilerError es -> True H.@=? any ("invalid option" `isInfixOf`) es+ _ -> H.assertFailure "Expecting CompilerError" cleanTestEnv where compiler = getResourceString >>= withItemBody (unixFilter "head" ["-#"])
tests/Hakyll/Web/Html/Tests.hs view
@@ -7,7 +7,7 @@ -------------------------------------------------------------------------------- import Data.Char (toUpper) import Test.Tasty (TestTree, testGroup)-import Test.Tasty.HUnit (assert, (@=?))+import Test.Tasty.HUnit ((@=?)) --------------------------------------------------------------------------------@@ -64,11 +64,11 @@ ] , fromAssertions "isExternal"- [ assert (isExternal "http://reddit.com")- , assert (isExternal "https://mail.google.com")- , assert (isExternal "//ajax.googleapis.com")- , assert (not (isExternal "../header.png"))- , assert (not (isExternal "/foo/index.html"))+ [ True @=? isExternal "http://reddit.com"+ , True @=? isExternal "https://mail.google.com"+ , True @=? isExternal "//ajax.googleapis.com"+ , False @=? isExternal "../header.png"+ , False @=? isExternal "/foo/index.html" ] , fromAssertions "stripTags"
+ web/site.hs view
@@ -0,0 +1,135 @@+--------------------------------------------------------------------------------+{-# LANGUAGE OverloadedStrings #-}+import Control.Arrow (second)+import Control.Monad (forM_)+import Data.Char (isDigit)+import Data.List (isPrefixOf, sortBy)+import Data.Monoid ((<>))+import Data.Ord (comparing)+import Hakyll+import System.Directory (copyFile)+import System.FilePath (dropTrailingPathSeparator, splitPath)+import Text.Pandoc+++--------------------------------------------------------------------------------+main :: IO ()+main = hakyllWith config $ do+ -- Copy CHANGELOG.md here.+ preprocess $ copyFile "../CHANGELOG.md" "releases.markdown"++ -- CSS+ match "css/*" $ do+ route idRoute+ compile compressCssCompiler++ -- Static directories+ forM_ ["images/*", "examples/*"] $ \f -> match f $ do+ 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"+ compile $ pandocCompiler+ >>= loadAndApplyTemplate "templates/default.html" defaultContext+ >>= relativizeUrls++ -- Tutorials+ match "tutorials/*" $ do+ route $ setExtension "html"+ compile $ pandocCompilerWith defaultHakyllReaderOptions withToc+ >>= loadAndApplyTemplate "templates/tutorial.html" defaultContext+ >>= loadAndApplyTemplate "templates/default.html" defaultContext+ >>= relativizeUrls++ -- Tutorial list+ create ["tutorials.html"] $ do+ route idRoute+ compile $ do+ tuts <-+ sortBy (comparing itemIdentifier) <$> loadAll "tutorials/*"++ let tutorialsCtx =+ constField "title" "Tutorials" `mappend`+ listField "tutorials" tutorialCtx (return tuts) `mappend`+ defaultContext++ makeItem ""+ >>= loadAndApplyTemplate "templates/tutorials.html" tutorialsCtx+ >>= loadAndApplyTemplate "templates/default.html" tutorialsCtx+ >>= relativizeUrls++ -- Templates+ match "templates/*" $ compile templateCompiler+ where+ withToc = defaultHakyllWriterOptions+ { writerTableOfContents = True+ , writerTemplate = Just "$toc$\n$body$"+ }+++--------------------------------------------------------------------------------+config :: Configuration+config = defaultConfiguration+ { deployCommand = "rsync --checksum -ave 'ssh -p 2222' \+ \_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+++--------------------------------------------------------------------------------+data TutorialType = SeriesTutorial | ArticlesTutorial | ExternalTutorial+ deriving (Eq)+++--------------------------------------------------------------------------------+-- | Partition tutorials into tutorial series, other articles, external articles+tutorialCtx :: Context String+tutorialCtx =+ field "isSeries" (isTutorialType SeriesTutorial) <>+ field "isArticle" (isTutorialType ArticlesTutorial) <>+ field "isExternal" (isTutorialType ExternalTutorial) <>+ defaultContext+ where+ getTutorialType item = do+ mbExternal <- getMetadataField (itemIdentifier item) "external"+ return $ case mbExternal of+ Just _ -> ExternalTutorial+ _ -> case splitPath (toFilePath $ itemIdentifier item) of+ [_, (x : _)] -> if isDigit x then SeriesTutorial else ArticlesTutorial+ _ -> ArticlesTutorial++ isTutorialType ty0 item = do+ ty1 <- getTutorialType item+ if ty0 == ty1 then return "yes" else fail "no"