123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- {-# LANGUAGE QuasiQuotes #-}
- {-# LANGUAGE RecordWildCards #-}
- {-# LANGUAGE OverloadedStrings #-}
- {-# LANGUAGE CPP #-}
- {-# LANGUAGE GeneralizedNewtypeDeriving #-}
- -------------------------------------------------------------------------------
- --
- -- Module : Yesod.RssFeed
- -- Copyright : Patrick Brisbin
- -- License : as-is
- --
- -- Maintainer : Patrick Brisbin <me@pbrisbin.com>
- -- Stability : Stable
- -- Portability : Portable
- --
- -------------------------------------------------------------------------------
- module Yesod.RssFeed
- ( rssFeed
- , rssFeedText
- , rssLink
- , RepRss (..)
- , module Yesod.FeedTypes
- ) where
- import Yesod.Core
- import Yesod.FeedTypes
- import qualified Data.ByteString.Char8 as S8
- import Data.Text (Text, pack)
- import Data.Text.Lazy (toStrict)
- import Text.XML
- import Text.Blaze.Html.Renderer.Text (renderHtml)
- import qualified Data.Map as Map
- newtype RepRss = RepRss Content
- deriving ToContent
- instance HasContentType RepRss where
- getContentType _ = typeRss
- instance ToTypedContent RepRss where
- toTypedContent = TypedContent typeRss . toContent
- -- | Generate the feed
- rssFeed :: MonadHandler m => Feed (Route (HandlerSite m)) -> m RepRss
- rssFeed feed = do
- render <- getUrlRender
- return $ RepRss $ toContent $ renderLBS def $ template feed render
- -- | Same as @'rssFeed'@ but for @'Feed Text'@. Useful for cases where you are
- -- generating a feed of external links.
- rssFeedText :: MonadHandler m => Feed Text -> m RepRss
- rssFeedText feed = return $ RepRss $ toContent $ renderLBS def $ template feed id
- template :: Feed url -> (url -> Text) -> Document
- template Feed {..} render =
- Document (Prologue [] Nothing []) root []
- where
- root = Element "rss" (Map.singleton "version" "2.0") $ return $ NodeElement $ Element "channel" Map.empty $ map NodeElement
- $ Element "{http://www.w3.org/2005/Atom}link" (Map.fromList
- [ ("href", render feedLinkSelf)
- , ("rel", "self")
- , ("type", pack $ S8.unpack typeRss)
- ]) []
- : Element "title" Map.empty [NodeContent feedTitle]
- : Element "link" Map.empty [NodeContent $ render feedLinkHome]
- : Element "description" Map.empty [NodeContent $ toStrict $ renderHtml feedDescription]
- : Element "lastBuildDate" Map.empty [NodeContent $ formatRFC822 feedUpdated]
- : Element "language" Map.empty [NodeContent feedLanguage]
- : map (flip entryTemplate render) feedEntries
- ++
- case feedLogo of
- Nothing -> []
- Just (route, desc) -> [Element "image" Map.empty
- [ NodeElement $ Element "url" Map.empty [NodeContent $ render route]
- , NodeElement $ Element "title" Map.empty [NodeContent desc]
- , NodeElement $ Element "link" Map.empty [NodeContent $ render feedLinkHome]
- ]
- ]
- entryTemplate :: FeedEntry url -> (url -> Text) -> Element
- entryTemplate FeedEntry {..} render = Element "item" Map.empty $ map NodeElement $
- [ Element "title" Map.empty [NodeContent feedEntryTitle]
- , Element "link" Map.empty [NodeContent $ render feedEntryLink]
- , Element "guid" Map.empty [NodeContent $ render feedEntryLink]
- , Element "pubDate" Map.empty [NodeContent $ formatRFC822 feedEntryUpdated]
- , Element "description" Map.empty [NodeContent $ toStrict $ renderHtml feedEntryContent]
- ]
- ++
- case feedEntryEnclosure of
- Nothing -> []
- Just (EntryEnclosure{..}) -> [
- Element "enclosure"
- (Map.fromList [("type", enclosedMimeType)
- ,("length", pack $ show enclosedSize)
- ,("url", render enclosedUrl)]) []]
- -- | Generates a link tag in the head of a widget.
- rssLink :: MonadWidget m
- => Route (HandlerSite m)
- -> Text -- ^ title
- -> m ()
- rssLink r title = toWidgetHead [hamlet|
- <link href=@{r} type=#{S8.unpack typeRss} rel="alternate" title=#{title}>
- |]
|