diff options
Diffstat (limited to 'src/Hakyll')
-rw-r--r-- | src/Hakyll/Core/Compiler.hs | 1 | ||||
-rw-r--r-- | src/Hakyll/Core/Compiler/Require.hs | 13 | ||||
-rw-r--r-- | src/Hakyll/Web/Feed.hs | 163 | ||||
-rw-r--r-- | src/Hakyll/Web/Template/Context.hs | 11 |
4 files changed, 100 insertions, 88 deletions
diff --git a/src/Hakyll/Core/Compiler.hs b/src/Hakyll/Core/Compiler.hs index a5c7a41..ccd056f 100644 --- a/src/Hakyll/Core/Compiler.hs +++ b/src/Hakyll/Core/Compiler.hs @@ -12,6 +12,7 @@ module Hakyll.Core.Compiler , getResourceLBS , getResourceWith , require + , requireBody , requireAll , cached , unsafeCompiler diff --git a/src/Hakyll/Core/Compiler/Require.hs b/src/Hakyll/Core/Compiler/Require.hs index 861c1f1..a7c47ce 100644 --- a/src/Hakyll/Core/Compiler/Require.hs +++ b/src/Hakyll/Core/Compiler/Require.hs @@ -2,6 +2,7 @@ module Hakyll.Core.Compiler.Require ( save , require + , requireBody , requireAll ) where @@ -17,6 +18,7 @@ import Hakyll.Core.Compiler.Internal import Hakyll.Core.Dependencies import Hakyll.Core.Identifier import Hakyll.Core.Identifier.Pattern +import Hakyll.Core.Item import Hakyll.Core.Store (Store) import qualified Hakyll.Core.Store as Store @@ -27,7 +29,7 @@ save store identifier x = Store.set store (key identifier) x -------------------------------------------------------------------------------- -require :: (Binary a, Typeable a) => Identifier -> Compiler a +require :: (Binary a, Typeable a) => Identifier -> Compiler (Item a) require id' = do store <- compilerStore <$> compilerAsk @@ -37,7 +39,7 @@ require id' = do case result of Store.NotFound -> compilerThrow notFound Store.WrongType e r -> compilerThrow $ wrongType e r - Store.Found x -> return x + Store.Found x -> return $ Item id' x where notFound = "Hakyll.Core.Compiler.Require.require: " ++ show id' ++ " was " ++ @@ -50,7 +52,12 @@ require id' = do -------------------------------------------------------------------------------- -requireAll :: (Binary a, Typeable a) => Pattern -> Compiler [a] +requireBody :: (Binary a, Typeable a) => Identifier -> Compiler a +requireBody = fmap itemBody . require + + +-------------------------------------------------------------------------------- +requireAll :: (Binary a, Typeable a) => Pattern -> Compiler [Item a] requireAll pattern = do universe <- compilerUniverse <$> compilerAsk let matching = filterMatches pattern universe diff --git a/src/Hakyll/Web/Feed.hs b/src/Hakyll/Web/Feed.hs index 2cb3292..c0a6213 100644 --- a/src/Hakyll/Web/Feed.hs +++ b/src/Hakyll/Web/Feed.hs @@ -1,11 +1,11 @@ --- TODO: port +-------------------------------------------------------------------------------- -- | A Module that allows easy rendering of RSS feeds. -- -- The main rendering functions (@renderRss@, @renderAtom@) all assume that -- you pass the list of items so that the most recent entry in the feed is the -- first item in the list. -- --- Also note that the pages should have (at least) the following fields to +-- Also note that the context should have (at least) the following fields to -- produce a correct feed: -- -- - @$title$@: Title of the item @@ -15,29 +15,33 @@ -- - @$url$@: URL to the item - this is usually set automatically. -- -- In addition, the posts should be named according to the rules for --- 'Hakyll.Page.Metadata.renderDateField'. --- +-- 'Hakyll.Web.Template.Context.dateField' module Hakyll.Web.Feed ( FeedConfiguration (..) , renderRss , renderAtom ) where -import Prelude hiding (id) -import Control.Category (id) -import Control.Arrow ((>>>), arr, (&&&)) -import Control.Monad ((<=<)) -import Data.Maybe (fromMaybe, listToMaybe) -import Hakyll.Core.Compiler -import Hakyll.Web.Page -import Hakyll.Web.Page.Metadata -import Hakyll.Web.Template -import Hakyll.Web.Template.Read.Hakyll (readTemplate) -import Hakyll.Web.Urls +-------------------------------------------------------------------------------- +import Control.Monad (forM, (<=<)) +import Data.Monoid (mconcat) + + +-------------------------------------------------------------------------------- +import Hakyll.Core.Compiler +import Hakyll.Core.Compiler.Internal +import Hakyll.Core.Item +import Hakyll.Web.Template +import Hakyll.Web.Template.Context +import Hakyll.Web.Template.Read.Hakyll (readTemplate) -import Paths_hakyll +-------------------------------------------------------------------------------- +import Paths_hakyll + + +-------------------------------------------------------------------------------- -- | This is a data structure to keep the configuration of a feed. data FeedConfiguration = FeedConfiguration { -- | Title of the feed. @@ -52,83 +56,74 @@ data FeedConfiguration = FeedConfiguration feedRoot :: String } deriving (Show, Eq) --- | This is an auxiliary function to create a listing that is, in fact, a feed. --- The items should be sorted on date. The @$updated@ field should be set for --- each item. --- -createFeed :: Template -- ^ Feed template - -> Template -- ^ Item template - -> String -- ^ URL of the feed - -> FeedConfiguration -- ^ Feed configuration - -> [Page String] -- ^ Items to include - -> String -- ^ Resulting feed -createFeed feedTemplate itemTemplate url configuration items = - pageBody $ applyTemplateToPage feedTemplate - $ trySetField "updated" updated - $ trySetField "title" (feedTitle configuration) - $ trySetField "description" (feedDescription configuration) - $ trySetField "authorName" (feedAuthorName configuration) - $ trySetField "authorEmail" (feedAuthorEmail configuration) - $ trySetField "root" (feedRoot configuration) - $ trySetField "url" url - $ fromBody body - where - -- Preprocess items - items' = flip map items $ applyTemplateToPage itemTemplate - . trySetField "root" (feedRoot configuration) - - -- Body: concatenated items - body = concat $ map pageBody items' - - -- Take the first updated, which should be the most recent - updated = fromMaybe "Unknown" $ do - p <- listToMaybe items - return $ getField "updated" p - +-------------------------------------------------------------------------------- -- | Abstract function to render any feed. --- -renderFeed :: FilePath -- ^ Feed template - -> FilePath -- ^ Item template - -> FeedConfiguration -- ^ Feed configuration - -> Compiler [Page String] String -- ^ Feed compiler -renderFeed feedTemplate itemTemplate configuration = - id &&& getRoute >>> renderFeed' - where - -- Arrow rendering the feed from the items and the URL - renderFeed' = unsafeCompiler $ \(items, url) -> do - feedTemplate' <- loadTemplate feedTemplate - itemTemplate' <- loadTemplate itemTemplate - let url' = toUrl $ fromMaybe noUrl url - return $ createFeed feedTemplate' itemTemplate' url' configuration items +renderFeed :: FilePath -- ^ Feed template + -> FilePath -- ^ 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 <- compilerUnsafeIO $ loadTemplate feedPath + itemTpl <- compilerUnsafeIO $ loadTemplate itemPath + items' <- forM items $ applyTemplate itemTpl itemContext' + body <- makeItem $ concat $ map itemBody items' + applyTemplate feedTpl feedContext body + where -- Auxiliary: load a template from a datafile loadTemplate = fmap readTemplate . readFile <=< getDataFileName - -- URL is required to have a valid field - noUrl = error "Hakyll.Web.Feed.renderFeed: no route specified" + itemContext' = mconcat + [ constField "root" (feedRoot config) + , itemContext + ] + + feedContext = mconcat + [ bodyField "body" + , constField "title" (feedTitle config) + , constField "description" (feedDescription config) + , constField "authorName" (feedAuthorName config) + , constField "authorEmail" (feedAuthorEmail config) + , constField "root" (feedRoot config) + , urlField "url" + , updatedField + , missingField + ] + + -- Take the first "updated" field from all items -- this should be the most + -- recent. + updatedField = field "updated" $ \_ -> case items of + [] -> return "Unknown" + (x : _) -> unContext itemContext' "updated" x + +-------------------------------------------------------------------------------- -- | Render an RSS feed with a number of items. --- -renderRss :: FeedConfiguration -- ^ Feed configuration - -> Compiler [Page String] String -- ^ Feed compiler -renderRss configuration = arr (map (addUpdated . renderDate)) - >>> renderFeed "templates/rss.xml" "templates/rss-item.xml" configuration - where - renderDate = renderDateField "published" "%a, %d %b %Y %H:%M:%S UT" - "No date found." +renderRss :: FeedConfiguration -- ^ Feed configuration + -> Context String -- ^ Item context + -> [Item String] -- ^ Feed items + -> Compiler (Item String) -- ^ Resulting feed +renderRss config context = renderFeed + "templates/rss.xml" "templates/rss-item.xml" config + (makeItemContext "%a, %d %b %Y %H:%M:%S UT" context) + +-------------------------------------------------------------------------------- -- | Render an Atom feed with a number of items. --- -renderAtom :: FeedConfiguration -- ^ Feed configuration - -> Compiler [Page String] String -- ^ Feed compiler -renderAtom configuration = arr (map (addUpdated . renderDate)) - >>> renderFeed "templates/atom.xml" "templates/atom-item.xml" configuration - where - renderDate = renderDateField "published" "%Y-%m-%dT%H:%M:%SZ" - "No date found." +renderAtom :: FeedConfiguration -- ^ Feed configuration + -> Context String -- ^ Item context + -> [Item String] -- ^ Feed items + -> Compiler (Item String) -- ^ Resulting feed +renderAtom config context = renderFeed + "templates/atom.xml" "templates/atom-item.xml" config + (makeItemContext "%Y-%m-%dT%H:%M:%SZ" context) + +-------------------------------------------------------------------------------- -- | Copies @$updated$@ from @$published$@ if it is not already set. --- -addUpdated :: Page a -> Page a -addUpdated page = trySetField "updated" (getField "published" page) page +makeItemContext :: String -> Context a -> Context a +makeItemContext fmt context = mconcat + [dateField "published" fmt, context, dateField "updated" fmt] diff --git a/src/Hakyll/Web/Template/Context.hs b/src/Hakyll/Web/Template/Context.hs index 269347b..fd9add9 100644 --- a/src/Hakyll/Web/Template/Context.hs +++ b/src/Hakyll/Web/Template/Context.hs @@ -3,6 +3,7 @@ module Hakyll.Web.Template.Context ( Context (..) , mapContext , field + , constField , defaultContext , bodyField @@ -15,6 +16,7 @@ module Hakyll.Web.Template.Context , dateFieldWith , modificationTimeField , modificationTimeFieldWith + , missingField ) where @@ -64,6 +66,11 @@ field key value = Context $ \k i -> if k == key then value i else empty -------------------------------------------------------------------------------- +constField :: String -> String -> Context a +constField key = field key . const . return + + +-------------------------------------------------------------------------------- defaultContext :: Context String defaultContext = bodyField "body" `mappend` @@ -194,4 +201,6 @@ modificationTimeFieldWith locale key fmt = field key $ \i -> do -------------------------------------------------------------------------------- missingField :: Context a -missingField = Context $ \k _ -> return $ "$" ++ k ++ "$" +missingField = Context $ \k i -> compilerThrow $ + "Missing field $" ++ k ++ "$ in context for item " ++ + show (itemIdentifier i) |