packages feed

hakyll 4.5.5.1 → 4.6.0.0

raw patch · 11 files changed

+217/−77 lines, 11 filesdep ~randomPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: random

API changes (from Hackage documentation)

+ Hakyll.Web.Template.Context: listFieldWith :: String -> Context a -> (Item b -> Compiler [Item a]) -> Context b
- Hakyll.Web.Template.Context: Context :: (String -> Item a -> Compiler ContextField) -> Context a
+ Hakyll.Web.Template.Context: Context :: (String -> [String] -> Item a -> Compiler ContextField) -> Context a
- Hakyll.Web.Template.Context: unContext :: Context a -> String -> Item a -> Compiler ContextField
+ Hakyll.Web.Template.Context: unContext :: Context a -> String -> [String] -> Item a -> Compiler ContextField

Files

hakyll.cabal view
@@ -1,5 +1,5 @@ Name:    hakyll-Version: 4.5.5.1+Version: 4.6.0.0  Synopsis: A static website compiler library Description:@@ -163,7 +163,7 @@     pandoc-citeproc >= 0.4    && < 0.5,     parsec          >= 3.0    && < 3.2,     process         >= 1.0    && < 1.3,-    random          >= 1.0    && < 1.1,+    random          >= 1.0    && < 1.2,     regex-base      >= 0.93   && < 0.94,     regex-tdfa      >= 1.1    && < 1.3,     tagsoup         >= 0.13.1 && < 0.14,@@ -250,7 +250,7 @@     pandoc-citeproc >= 0.4    && < 0.5,     parsec          >= 3.0    && < 3.2,     process         >= 1.0    && < 1.3,-    random          >= 1.0    && < 1.1,+    random          >= 1.0    && < 1.2,     regex-base      >= 0.93   && < 0.94,     regex-tdfa      >= 1.1    && < 1.3,     tagsoup         >= 0.13.1 && < 0.14,
src/Hakyll/Core/Rules.hs view
@@ -181,10 +181,32 @@ -- -- A useful utility for this purpose is 'makePatternDependency'. rulesExtraDependencies :: [Dependency] -> Rules a -> Rules a-rulesExtraDependencies deps = Rules . censor addDependencies . unRules+rulesExtraDependencies deps rules =+    -- Note that we add the dependencies seemingly twice here. However, this is+    -- done so that 'rulesExtraDependencies' works both if we have something+    -- like:+    --+    -- > match "*.css" $ rulesExtraDependencies [foo] $ ...+    --+    -- and something like:+    --+    -- > rulesExtraDependencies [foo] $ match "*.css" $ ...+    --+    -- (1) takes care of the latter and (2) of the former.+    Rules $ censor fixRuleSet $ do+        x <- unRules rules+        fixCompiler+        return x   where-    -- Adds the dependencies to the compilers in the ruleset-    addDependencies ruleSet = ruleSet+    -- (1) Adds the dependencies to the compilers we are yet to create+    fixCompiler = modify $ \s -> case rulesCompiler s of+        Nothing -> s+        Just c  -> s+            { rulesCompiler = Just $ compilerTellDependencies deps >> c+            }++    -- (2) Adds the dependencies to the compilers that are already in the ruleset+    fixRuleSet ruleSet = ruleSet         { rulesCompilers =             [ (i, compilerTellDependencies deps >> c)             | (i, c) <- rulesCompilers ruleSet
src/Hakyll/Core/Util/Parser.hs view
@@ -16,7 +16,7 @@ -------------------------------------------------------------------------------- metadataKey :: Parser String metadataKey = do-    i <- (:) <$> P.letter <*> (P.many $ P.alphaNum <|> P.oneOf " _-.")+    i <- (:) <$> P.letter <*> (P.many $ P.alphaNum <|> P.oneOf "_-.")     if i `elem` reservedKeys then mzero else return i  
src/Hakyll/Web/Feed.hs view
@@ -96,7 +96,7 @@     -- recent.     updatedField = field "updated" $ \_ -> case items of         []      -> return "Unknown"-        (x : _) -> unContext itemContext' "updated" x >>= \cf -> case cf of+        (x : _) -> unContext itemContext' "updated" [] x >>= \cf -> case cf of             ListField _ _ -> fail "Hakyll.Web.Feed.renderFeed: Internal error"             StringField s -> return s 
src/Hakyll/Web/Template.hs view
@@ -115,7 +115,7 @@ -- That is, calling @$partial$@ is equivalent to just copying and pasting -- template code. ---+{-# LANGUAGE ScopedTypeVariables #-} module Hakyll.Web.Template     ( Template     , templateCompiler@@ -161,44 +161,67 @@   ---------------------------------------------------------------------------------applyTemplate' :: Template         -- ^ Template-               -> Context a        -- ^ Context-               -> Item a           -- ^ Page-               -> Compiler String  -- ^ Resulting item+applyTemplate'+    :: forall a.+       Template         -- ^ Template+    -> Context a        -- ^ Context+    -> Item a           -- ^ Page+    -> Compiler String  -- ^ Resulting item applyTemplate' tpl context x = go tpl   where+    context' :: String -> [String] -> Item a -> Compiler ContextField     context' = unContext (context `mappend` missingField)+     go = liftM concat . mapM applyElem . unTemplate +    ---------------------------------------------------------------------------++    applyElem :: TemplateElement -> Compiler String+     applyElem (Chunk c) = return c -    applyElem Escaped = return "$"+    applyElem (Expr e) = applyExpr e >>= getString e -    applyElem (Key k) = context' k x >>= getString k+    applyElem Escaped = return "$" -    applyElem (If k t mf) = (context' k x >> go t) `catchError` handler+    applyElem (If e t mf) = (applyExpr e >> go t) `catchError` handler       where         handler _ = case mf of             Nothing -> return ""             Just f  -> go f -    applyElem (For k b s) = context' k x >>= \cf -> case cf of+    applyElem (For e b s) = applyExpr e >>= \cf -> case cf of         StringField _  -> fail $             "Hakyll.Web.Template.applyTemplateWith: expected ListField but " ++-            "got StringField for key " ++ show k+            "got StringField for expr " ++ show e         ListField c xs -> do             sep <- maybe (return "") go s             bs  <- mapM (applyTemplate' b c) xs             return $ intercalate sep bs -    applyElem (Partial p) = do+    applyElem (Partial e) = do+        p    <- applyExpr e >>= getString e         tpl' <- loadBody (fromFilePath p)         applyTemplate' tpl' context x +    ---------------------------------------------------------------------------++    applyExpr :: TemplateExpr -> Compiler ContextField++    applyExpr (Ident (TemplateKey k)) = context' k [] x++    applyExpr (Call (TemplateKey k) args) = do+        args' <- mapM (\e -> applyExpr e >>= getString e) args+        context' k args' x++    applyExpr (StringLiteral s) = return (StringField s)++    ----------------------------------------------------------------------------+     getString _ (StringField s) = return s-    getString k (ListField _ _) = fail $+    getString e (ListField _ _) = fail $         "Hakyll.Web.Template.applyTemplateWith: expected StringField but " ++-        "got ListField for key " ++ show k+        "got ListField for expr " ++ show e   --------------------------------------------------------------------------------
src/Hakyll/Web/Template/Context.hs view
@@ -6,6 +6,7 @@     , field     , constField     , listField+    , listFieldWith     , functionField     , mapContext @@ -33,7 +34,7 @@ import           Data.Monoid                   (Monoid (..)) import           Data.Time.Clock               (UTCTime (..)) import           Data.Time.Format              (formatTime, parseTime)-import           System.FilePath               (takeBaseName, takeFileName)+import           System.FilePath               (takeBaseName, splitDirectories) import           System.Locale                 (TimeLocale, defaultTimeLocale)  @@ -69,29 +70,30 @@ -- @ -- 'metadataField' \<\> field \"date\" fDate -- @--- +-- newtype Context a = Context-    { unContext :: String -> Item a -> Compiler ContextField+    { unContext :: String -> [String] -> Item a -> Compiler ContextField     }   -------------------------------------------------------------------------------- instance Monoid (Context a) where     mempty                          = missingField-    mappend (Context f) (Context g) = Context $ \k i -> f k i <|> g k i+    mappend (Context f) (Context g) = Context $ \k a i -> f k a i <|> g k a i   -------------------------------------------------------------------------------- field' :: String -> (Item a -> Compiler ContextField) -> Context a-field' key value = Context $ \k i -> if k == key then value i else empty+field' key value = Context $ \k _ i -> if k == key then value i else empty   -------------------------------------------------------------------------------- -- | Constructs a new field in the 'Context.'-field :: String  -- ^ Key-      -> (Item a -> Compiler String) -- ^ Function that constructs a -                                     -- value based on the item-      -> Context a+field+    :: String                      -- ^ Key+    -> (Item a -> Compiler String) -- ^ Function that constructs a value based+                                   -- on the item+    -> Context a field key value = field' key (fmap StringField . value)  @@ -103,22 +105,27 @@  -------------------------------------------------------------------------------- listField :: String -> Context a -> Compiler [Item a] -> Context b-listField key c xs = field' key $ \_ -> fmap (ListField c) xs+listField key c xs = listFieldWith key c (const xs)   --------------------------------------------------------------------------------+listFieldWith+    :: String -> Context a -> (Item b -> Compiler [Item a]) -> Context b+listFieldWith key c f = field' key $ fmap (ListField c) . f+++-------------------------------------------------------------------------------- functionField :: String -> ([String] -> Item a -> Compiler String) -> Context a-functionField name value = Context $ \k i -> case words k of-    []              -> empty-    (n : args)-        | n == name -> StringField <$> value args i-        | otherwise -> empty+functionField name value = Context $ \k args i ->+    if k == name+        then StringField <$> value args i+        else empty   -------------------------------------------------------------------------------- mapContext :: (String -> String) -> Context a -> Context a-mapContext f (Context c) = Context $ \k i -> do-    fld <- c k i+mapContext f (Context c) = Context $ \k a i -> do+    fld <- c k a i     case fld of         StringField str -> return $ StringField (f str)         ListField _ _   -> fail $@@ -132,12 +139,12 @@ --     1. A @$body$@ field -- --     2. Metadata fields---        +-- --     3. A @$url$@ 'urlField' -- --     4. A @$path$@ 'pathField' -----     5. A @$title$@ 'titleField'        +--     5. A @$title$@ 'titleField' defaultContext :: Context String defaultContext =     bodyField     "body"     `mappend`@@ -162,7 +169,7 @@ -------------------------------------------------------------------------------- -- | Map any field to its metadata value, if present metadataField :: Context a-metadataField = Context $ \k i -> do+metadataField = Context $ \k _ i -> do     value <- getMetadataField (itemIdentifier i) k     maybe empty (return . StringField) value @@ -218,7 +225,11 @@ -- Alternatively, when the metadata has a field called @path@ in a -- @folder/yyyy-mm-dd-title.extension@ format (the convention for pages) -- and no @published@ metadata field set, this function can render--- the date.+-- the date. This pattern matches the file name or directory names +-- that begins with @yyyy-mm-dd@ . For example:+-- @folder//yyyy-mm-dd-title//dist//main.extension@ .+-- In case of multiple matches, the rightmost one is used.+ dateField :: String     -- ^ Key in which the rendered date should be placed           -> String     -- ^ Format to use on the date           -> Context a  -- ^ Resulting context@@ -249,12 +260,12 @@ getItemUTC locale id' = do     metadata <- getMetadata id'     let tryField k fmt = M.lookup k metadata >>= parseTime' fmt-        fn             = takeFileName $ toFilePath id'+        paths          = splitDirectories $ toFilePath id'      maybe empty' return $ msum $         [tryField "published" fmt | fmt <- formats] ++         [tryField "date"      fmt | fmt <- formats] ++-        [parseTime' "%Y-%m-%d" $ intercalate "-" $ take 3 $ splitAll "-" fn]+        [parseTime' "%Y-%m-%d" $ intercalate "-" $ take 3 $ splitAll "-" fnCand | fnCand <- reverse paths]   where     empty'     = fail $ "Hakyll.Web.Template.Context.getItemUTC: " ++         "could not parse time for " ++ show id'@@ -306,6 +317,6 @@  -------------------------------------------------------------------------------- missingField :: Context a-missingField = Context $ \k i -> fail $+missingField = Context $ \k _ i -> fail $     "Missing field $" ++ k ++ "$ in context for item " ++     show (itemIdentifier i)
src/Hakyll/Web/Template/Internal.hs view
@@ -4,6 +4,8 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Hakyll.Web.Template.Internal     ( Template (..)+    , TemplateKey (..)+    , TemplateExpr (..)     , TemplateElement (..)     , readTemplate     ) where@@ -14,6 +16,7 @@ import           Control.Monad           (void) import           Data.Binary             (Binary, get, getWord8, put, putWord8) import           Data.Typeable           (Typeable)+import           Data.List (intercalate) import           GHC.Exts                (IsString (..)) import qualified Text.Parsec             as P import qualified Text.Parsec.String      as P@@ -38,29 +41,44 @@   --------------------------------------------------------------------------------+instance IsString Template where+    fromString = readTemplate+++--------------------------------------------------------------------------------+newtype TemplateKey = TemplateKey String+    deriving (Binary, Show, Eq, Typeable)+++--------------------------------------------------------------------------------+instance IsString TemplateKey where+    fromString = TemplateKey+++-------------------------------------------------------------------------------- -- | Elements of a template. data TemplateElement     = Chunk String-    | Key String+    | Expr TemplateExpr     | Escaped-    | If String Template (Maybe Template)   -- key, then branch, else branch-    | For String Template (Maybe Template)  -- key, body, separator-    | Partial String                        -- filename+    | If TemplateExpr Template (Maybe Template)   -- expr, then, else+    | For TemplateExpr Template (Maybe Template)  -- expr, body, separator+    | Partial TemplateExpr                        -- filename     deriving (Show, Eq, Typeable)   -------------------------------------------------------------------------------- instance Binary TemplateElement where     put (Chunk string) = putWord8 0 >> put string-    put (Key k)        = putWord8 1 >> put k+    put (Expr e)       = putWord8 1 >> put e     put (Escaped)      = putWord8 2-    put (If k t f  )   = putWord8 3 >> put k >> put t >> put f-    put (For k b s)    = putWord8 4 >> put k >> put b >> put s-    put (Partial p)    = putWord8 5 >> put p+    put (If e t f  )   = putWord8 3 >> put e >> put t >> put f+    put (For e b s)    = putWord8 4 >> put e >> put b >> put s+    put (Partial e)    = putWord8 5 >> put e      get = getWord8 >>= \tag -> case tag of         0 -> Chunk <$> get-        1 -> Key   <$> get+        1 -> Expr <$> get         2 -> pure Escaped         3 -> If <$> get <*> get <*> get         4 -> For <$> get <*> get <*> get@@ -70,11 +88,37 @@   ---------------------------------------------------------------------------------instance IsString Template where-    fromString = readTemplate+-- | Expression in a template+data TemplateExpr+    = Ident TemplateKey+    | Call TemplateKey [TemplateExpr]+    | StringLiteral String+    deriving (Eq, Typeable)   --------------------------------------------------------------------------------+instance Show TemplateExpr where+    show (Ident (TemplateKey k))   = k+    show (Call (TemplateKey k) as) =+        k ++ "(" ++ intercalate ", " (map show as) ++ ")"+    show (StringLiteral s)         = show s+++--------------------------------------------------------------------------------+instance Binary TemplateExpr where+    put (Ident k)         = putWord8 0 >> put k+    put (Call k as)       = putWord8 1 >> put k >> put as+    put (StringLiteral s) = putWord8 2 >> put s++    get = getWord8 >>= \tag -> case tag of+        0 -> Ident         <$> get+        1 -> Call          <$> get <*> get+        2 -> StringLiteral <$> get+        _ -> error $+            "Hakyll.Web.Tamplte.Internal: Error reading cached template"+++-------------------------------------------------------------------------------- readTemplate :: String -> Template readTemplate input = case P.parse template "" input of     Left err -> error $ "Cannot parse template: " ++ show err@@ -84,7 +128,7 @@ -------------------------------------------------------------------------------- template :: P.Parser Template template = Template <$>-    (P.many1 $ chunk <|> escaped <|> conditional <|> for <|> partial <|> key)+    (P.many1 $ chunk <|> escaped <|> conditional <|> for <|> partial <|> expr)   --------------------------------------------------------------------------------@@ -93,6 +137,20 @@   --------------------------------------------------------------------------------+expr :: P.Parser TemplateElement+expr = P.try $ do+    void $ P.char '$'+    e <- expr'+    void $ P.char '$'+    return $ Expr e+++--------------------------------------------------------------------------------+expr' :: P.Parser TemplateExpr+expr' = stringLiteral <|> call <|> ident+++-------------------------------------------------------------------------------- escaped :: P.Parser TemplateElement escaped = Escaped <$ (P.try $ P.string "$$") @@ -101,50 +159,63 @@ conditional :: P.Parser TemplateElement conditional = P.try $ do     void $ P.string "$if("-    i <- metadataKey+    e <- expr'     void $ P.string ")$"     thenBranch <- template     elseBranch <- P.optionMaybe $ P.try (P.string "$else$") >> template     void $ P.string "$endif$"-    return $ If i thenBranch elseBranch+    return $ If e thenBranch elseBranch   -------------------------------------------------------------------------------- for :: P.Parser TemplateElement for = P.try $ do     void $ P.string "$for("-    i <- metadataKey+    e <- expr'     void $ P.string ")$"     body <- template     sep  <- P.optionMaybe $ P.try (P.string "$sep$") >> template     void $ P.string "$endfor$"-    return $ For i body sep+    return $ For e body sep   -------------------------------------------------------------------------------- partial :: P.Parser TemplateElement partial = P.try $ do     void $ P.string "$partial("-    i <- stringLiteral+    e <- expr'     void $ P.string ")$"-    return $ Partial i+    return $ Partial e   ---------------------------------------------------------------------------------key :: P.Parser TemplateElement-key = P.try $ do-    void $ P.char '$'-    k <- metadataKey-    void $ P.char '$'-    return $ Key k+ident :: P.Parser TemplateExpr+ident = P.try $ Ident <$> key   ---------------------------------------------------------------------------------stringLiteral :: P.Parser String+call :: P.Parser TemplateExpr+call = P.try $ do+    f <- key+    void $ P.char '('+    P.spaces+    as <- P.sepBy expr' (P.spaces >> P.char ',' >> P.spaces)+    P.spaces+    void $ P.char ')'+    return $ Call f as+++--------------------------------------------------------------------------------+stringLiteral :: P.Parser TemplateExpr stringLiteral = do     void $ P.char '\"'     str <- P.many $ do         x <- P.noneOf "\""         if x == '\\' then P.anyChar else return x     void $ P.char '\"'-    return str+    return $ StringLiteral str+++--------------------------------------------------------------------------------+key :: P.Parser TemplateKey+key = TemplateKey <$> metadataKey
tests/Hakyll/Web/Template/Context/Tests.hs view
@@ -51,7 +51,7 @@ testContextDone store provider identifier key context =     testCompilerDone store provider identifier $ do         item <- getResourceBody-        cf   <- unContext context key item+        cf   <- unContext context key [] item         case cf of             StringField str -> return str             ListField _ _   -> error $
tests/Hakyll/Web/Template/Tests.hs view
@@ -26,9 +26,20 @@  -------------------------------------------------------------------------------- tests :: Test-tests = testGroup "Hakyll.Core.Template.Tests"-    [ testCase "case01"                case01-    , testCase "applyJoinTemplateList" testApplyJoinTemplateList+tests = testGroup "Hakyll.Core.Template.Tests" $ concat+    [ [ testCase "case01"                case01+      , testCase "applyJoinTemplateList" testApplyJoinTemplateList+      ]++    , fromAssertions "readTemplate"+        [ Template [Chunk "Hello ", Expr (Call "guest" [])]+            @=?  readTemplate "Hello $guest()$"+        , Template+            [If (Call "a" [StringLiteral "bar"])+                (Template [Chunk "foo"])+                Nothing]+            @=?  readTemplate "$if(a(\"bar\"))$foo$endif$"+        ]     ]  @@ -76,4 +87,4 @@   where     i1  = Item "item1" "Hello"     i2  = Item "item2" "World"-    tpl = Template [Chunk "<b>", Key "body", Chunk "</b>"]+    tpl = Template [Chunk "<b>", Expr (Ident "body"), Chunk "</b>"]
tests/data/template.html view
@@ -1,7 +1,8 @@ <div>     I'm so rich I have $$3. -    $rev foo$+    $rev("foo")$+    $rev(rev("foo"))$      $if(body)$     I have body
tests/data/template.html.out view
@@ -2,6 +2,7 @@     I'm so rich I have $3.      oof+    foo           I have body