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 Paths_hakyll
data FeedConfiguration = FeedConfiguration
{
feedTitle :: String
,
feedDescription :: String
,
feedAuthorName :: String
,
feedRoot :: String
} deriving (Show, Eq)
createFeed :: Template
-> Template
-> String
-> FeedConfiguration
-> [Page String]
-> String
createFeed feedTemplate itemTemplate url configuration items =
pageBody $ applyTemplate feedTemplate
$ trySetField "updated" updated
$ trySetField "title" (feedTitle configuration)
$ trySetField "description" (feedDescription configuration)
$ trySetField "authorName" (feedAuthorName configuration)
$ trySetField "root" (feedRoot configuration)
$ trySetField "url" url
$ fromBody body
where
items' = flip map items $ applyTemplate itemTemplate
. trySetField "root" (feedRoot configuration)
body = concat $ map pageBody items'
updated = fromMaybe "Unknown" $ do
p <- listToMaybe items
return $ getField "updated" p
renderFeed :: FilePath
-> FilePath
-> FeedConfiguration
-> Compiler [Page String] String
renderFeed feedTemplate itemTemplate configuration =
id &&& getRoute >>> renderFeed'
where
renderFeed' = unsafeCompiler $ \(items, url) -> do
feedTemplate' <- loadTemplate feedTemplate
itemTemplate' <- loadTemplate itemTemplate
let url' = toUrl $ fromMaybe noUrl url
return $ createFeed feedTemplate' itemTemplate' url' configuration items
loadTemplate = fmap readTemplate . readFile <=< getDataFileName
noUrl = error "Hakyll.Web.Feed.renderFeed: no route specified"
renderRss :: FeedConfiguration
-> Compiler [Page String] String
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."
renderAtom :: FeedConfiguration
-> Compiler [Page String] String
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."
addUpdated :: Page a -> Page a
addUpdated page = trySetField "updated" (getField "published" page) page