module Text.Atom.Conduit.Render
(
renderAtomFeed
, renderAtomEntry
, renderAtomContent
, renderAtomSource
, renderAtomGenerator
, renderAtomLink
, renderAtomCategory
, renderAtomPerson
, renderAtomText
) where
import Text.Atom.Lens
import Text.Atom.Types
import Control.Monad
import Data.Conduit
import Data.Monoid
import Data.NonNull
import Data.Text as Text
import Data.Text.Encoding
import Data.Time.Clock
import Data.Time.LocalTime
import Data.Time.RFC3339
import Data.XML.Types
import Lens.Simple
import Text.XML.Stream.Render
import URI.ByteString
renderAtomFeed :: (Monad m) => AtomFeed -> Source m Event
renderAtomFeed f = atomTag "feed" (attr "xmlns" "http://www.w3.org/2005/Atom") $ do
forM_ (f^.feedAuthorsL) $ renderAtomPerson "author"
forM_ (f^.feedCategoriesL) renderAtomCategory
forM_ (f^.feedContributorsL) $ renderAtomPerson "contributor"
forM_ (f^.feedEntriesL) renderAtomEntry
forM_ (f^.feedGeneratorL) renderAtomGenerator
forM_ (feedIcon f) $ atomTag "icon" mempty . content . decodeUtf8 . withAtomURI serializeURIRef'
atomTag "id" mempty . content $ f^.feedIdL
forM_ (f^.feedLinksL) renderAtomLink
forM_ (feedLogo f) $ atomTag "logo" mempty . content . decodeUtf8 . withAtomURI serializeURIRef'
forM_ (f^.feedRightsL) $ renderAtomText "rights"
forM_ (f^.feedSubtitleL) $ renderAtomText "subtitle"
renderAtomText "title" $ f^.feedTitleL
dateTag "updated" $ f^.feedUpdatedL
renderAtomEntry :: (Monad m) => AtomEntry -> Source m Event
renderAtomEntry e = atomTag "entry" mempty $ do
forM_ (e^.entryAuthorsL) $ renderAtomPerson "author"
forM_ (e^.entryCategoriesL) renderAtomCategory
forM_ (e^.entryContentL) renderAtomContent
forM_ (e^.entryContributorsL) $ renderAtomPerson "contributor"
atomTag "id" mempty . content $ e^.entryIdL
forM_ (e^.entryLinksL) renderAtomLink
forM_ (e^.entryPublishedL) $ dateTag "published"
forM_ (e^.entryRightsL) $ renderAtomText "rights"
forM_ (e^.entrySourceL) renderAtomSource
forM_ (e^.entrySummaryL) $ renderAtomText "summary"
renderAtomText "title" (e^.entryTitleL)
dateTag "updated" (e^.entryUpdatedL)
renderAtomContent :: (Monad m) => AtomContent -> Source m Event
renderAtomContent (AtomContentInlineXHTML t) = atomTag "content" (attr "type" "xhtml")
. tag "{http://www.w3.org/1999/xhtml}div" mempty $ content t
renderAtomContent (AtomContentOutOfLine ctype uri) = atomTag "content" (nonEmptyAttr "type" ctype <> attr "src" (decodeUtf8 $ withAtomURI serializeURIRef' uri)) $ return ()
renderAtomContent (AtomContentInlineText TypeHTML t) = atomTag "content" (attr "type" "html") $ content t
renderAtomContent (AtomContentInlineText TypeText t) = atomTag "content" mempty $ content t
renderAtomContent (AtomContentInlineOther ctype t) = atomTag "content" (attr "type" ctype) $ content t
renderAtomSource :: (Monad m) => AtomSource -> Source m Event
renderAtomSource s = atomTag "source" mempty $ do
forM_ (s^.sourceAuthorsL) $ renderAtomPerson "author"
forM_ (s^.sourceCategoriesL) renderAtomCategory
forM_ (s^.sourceContributorsL) $ renderAtomPerson "contributor"
forM_ (s^.sourceGeneratorL) renderAtomGenerator
forM_ (sourceIcon s) $ atomTag "icon" mempty . content . decodeUtf8 . withAtomURI serializeURIRef'
unless (Text.null $ s^.sourceIdL) . atomTag "id" mempty . content $ s^.sourceIdL
forM_ (s^.sourceLinksL) renderAtomLink
forM_ (sourceLogo s) $ atomTag "logo" mempty . content . decodeUtf8 . withAtomURI serializeURIRef'
forM_ (s^.sourceRightsL) $ renderAtomText "rights"
forM_ (s^.sourceSubtitleL) $ renderAtomText "subtitle"
forM_ (s^.sourceTitleL) $ renderAtomText "title"
forM_ (s^.sourceUpdatedL) $ dateTag "updated"
renderAtomGenerator :: (Monad m) => AtomGenerator -> Source m Event
renderAtomGenerator g = atomTag "generator" attributes . content . toNullable $ g^.generatorContentL
where attributes = optionalAttr "uri" (decodeUtf8 . withAtomURI serializeURIRef' <$> generatorUri g)
<> nonEmptyAttr "version" (g^.generatorVersionL)
renderAtomLink :: (Monad m) => AtomLink -> Source m Event
renderAtomLink l = atomTag "link" linkAttrs $ return ()
where linkAttrs = attr "href" (decodeUtf8 . withAtomURI serializeURIRef' $ linkHref l)
<> nonEmptyAttr "rel" (l^.linkRelL)
<> nonEmptyAttr "type" (l^.linkTypeL)
<> nonEmptyAttr "hreflang" (l^.linkLangL)
<> nonEmptyAttr "title" (l^.linkTitleL)
<> nonEmptyAttr "length" (l^.linkLengthL)
renderAtomCategory :: (Monad m) => AtomCategory -> Source m Event
renderAtomCategory c = atomTag "category" attributes $ return ()
where attributes = attr "term" (toNullable $ c^.categoryTermL)
<> nonEmptyAttr "scheme" (c^.categorySchemeL)
<> nonEmptyAttr "label" (c^.categoryLabelL)
renderAtomPerson :: (Monad m) => Text -> AtomPerson -> Source m Event
renderAtomPerson name p = atomTag name mempty $ do
atomTag "name" mempty . content . toNullable $ p^.personNameL
unless (Text.null $ p^.personEmailL) $ atomTag "email" mempty . content $ p^.personEmailL
forM_ (personUri p) $ atomTag "uri" mempty . content . decodeUtf8 . withAtomURI serializeURIRef'
renderAtomText :: (Monad m) => Text -> AtomText -> Source m Event
renderAtomText name (AtomXHTMLText t) = atomTag name (attr "type" "xhtml")
. tag "{http://www.w3.org/1999/xhtml}div" mempty $ content t
renderAtomText name (AtomPlainText TypeHTML t) = atomTag name (attr "type" "html") $ content t
renderAtomText name (AtomPlainText TypeText t) = atomTag name mempty $ content t
atomTag :: Monad m => Text -> Attributes -> Source m Event -> Source m Event
atomTag name = tag (Name name (Just "http://www.w3.org/2005/Atom") (Just "atom"))
dateTag :: (Monad m) => Text -> UTCTime -> Source m Event
dateTag name = atomTag name mempty . content . formatTimeRFC3339 . utcToZonedTime utc
nonEmptyAttr :: Name -> Text -> Attributes
nonEmptyAttr name value
| value == mempty = mempty
| otherwise = attr name value