{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleContexts #-} module RSS ( generate ) where import Article (Article(..)) import ArticlesList (ArticlesList(..), getArticles) import qualified ArticlesList (description) import Blog (Blog(urls), Renderer, URL(..)) import Collection (Collection(..), getAll) import qualified Collection (title) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Reader (MonadReader, ReaderT, asks) import Data.Text (Text) import Data.Map ((!)) import qualified Data.Text.Lazy.IO as TextIO (writeFile) import Data.Time (defaultTimeLocale, formatTime, rfc822DateFormat) import Data.Time.Clock.POSIX (posixSecondsToUTCTime) import Lucid (Attribute, HtmlT, Term, ToHtml(..), term, renderTextT) import Lucid.Base (makeAttribute) import Markdown (Markdown(..)) import Pretty ((.$)) import System.FilePath.Posix ((), (<.>)) prolog :: Monad m => HtmlT m () prolog = toHtmlRaw ("" :: String) version_ :: Text -> Attribute version_ = makeAttribute "version" xmlns_content_ :: Text -> Attribute xmlns_content_ = makeAttribute "xmlns:content" xmlns_atom_ :: Text -> Attribute xmlns_atom_ = makeAttribute "xmlns:atom" rss_ :: Term arg result => arg -> result rss_ = term "rss" channel_ :: Term arg result => arg -> result channel_ = term "channel" title_ :: Term arg result => arg -> result title_ = term "title" link_ :: Term arg result => arg -> result link_ = term "link" description_ :: Term arg result => arg -> result description_ = term "description" item_ :: Term arg result => arg -> result item_ = term "item" pubDate_ :: Term arg result => arg -> result pubDate_ = term "pubDate" articleItem :: MonadReader Blog m => String -> Article -> HtmlT m () articleItem siteURL (Article (Markdown {path, metadata, title})) = item_ $ do title_ $ toHtml title link_ $ toHtml (siteURL path <.> "html") pubDate_ . toHtml . rfc822Date $ metadata ! "date" where rfc822Date = formatTime defaultTimeLocale rfc822DateFormat . posixSecondsToUTCTime . fromIntegral . (read :: String -> Int) feed :: Renderer m => String -> ArticlesList -> HtmlT m () feed siteURL al@(ArticlesList {collection}) = do prolog rss_ [version, content, atom] $ do channel_ $ do title_ . toHtml =<< Collection.title collection link_ . toHtml $ siteURL maybe "" (++ "/") (tag collection) description_ . toHtml =<< ArticlesList.description al mapM_ (articleItem siteURL) =<< getArticles al where version = version_ "2.0" content = xmlns_content_ "http://purl.org/rss/1.0/modules/content/" atom = xmlns_atom_ "http://www.w3.org/2005/Atom" generateCollection :: String -> Collection -> ReaderT Blog IO () generateCollection siteURL collection = renderTextT (feed siteURL $ ArticlesList {full = False, collection}) >>= liftIO . TextIO.writeFile (basePath collection "rss" <.> "xml") generate :: ReaderT Blog IO () generate = (asks $urls.$rss) >>= maybe (return ()) generateAll where generateAll siteURL = Collection.getAll >>= mapM_ (generateCollection siteURL)