scrapbook-0.3.2: src/ScrapBook/Feed/Atom/Internal.hs
---
-- |
-- Copy from: https://hackage.haskell.org/package/feed-1.0.0.0/docs/src/Text-Atom-Feed-Export.html
-- Custmize export XML
---
{-# LANGUAGE OverloadedStrings #-}
module ScrapBook.Feed.Atom.Internal
( xmlFeed
) where
import RIO
import qualified RIO.Text as T
import Data.XML.Types as XML
import Text.Atom.Feed
xmlFeed :: Feed -> XML.Element
xmlFeed f = ( atomNode "feed"
$ map NodeElement
$ [xmlTitle (feedTitle f)]
++ [xmlId (feedId f)]
++ [xmlUpdated (feedUpdated f)]
++ map xmlLink (feedLinks f)
++ map xmlAuthor (feedAuthors f)
++ map xmlCategory (feedCategories f)
++ map xmlContributor (feedContributors f)
++ mb xmlGenerator (feedGenerator f)
++ mb xmlIcon (feedIcon f)
++ mb xmlLogo (feedLogo f)
++ mb xmlRights (feedRights f)
++ mb xmlSubtitle (feedSubtitle f)
++ map xmlEntry (feedEntries f)
++ feedOther f
)
{ elementAttributes = [xmlnsAtom]
}
---
atomPrefix :: Maybe Text
atomPrefix = Nothing -- Just "atom"
atomThrPrefix :: Maybe Text
atomThrPrefix = Just "thr"
atomNS :: Text
atomNS = "http://www.w3.org/2005/Atom"
atomThreadNS :: Text
atomThreadNS = "http://purl.org/syndication/thread/1.0"
blankElement :: Name -> [Node] -> XML.Element
blankElement name = XML.Element name []
xmlnsAtom :: Attr
xmlnsAtom = (qn, [ContentText atomNS])
where
qn = case atomPrefix of
Nothing -> Name
{ nameLocalName = "xmlns"
, nameNamespace = Nothing
, namePrefix = Nothing
}
Just s -> Name
{ nameLocalName = s
, nameNamespace = Nothing -- XXX: is this ok?
, namePrefix = Just "xmlns"
}
atomName :: Text -> Name
atomName nc =
Name {nameLocalName = nc, nameNamespace = Nothing, namePrefix = atomPrefix}
atomAttr :: Text -> Text -> Attr
atomAttr x y = (atomName x, [ContentText y])
atomNode :: Text -> [Node] -> XML.Element
atomNode x = blankElement (atomName x)
atomLeaf :: Text -> Text -> XML.Element
atomLeaf tag txt = blankElement (atomName tag) [NodeContent $ ContentText txt]
atomThreadName :: Text -> Name
atomThreadName nc = Name
{ nameLocalName = nc
, nameNamespace = Just atomThreadNS
, namePrefix = atomThrPrefix
}
atomThreadAttr :: Text -> Text -> Attr
atomThreadAttr x y = (atomThreadName x, [ContentText y])
atomThreadNode :: Text -> [Node] -> XML.Element
atomThreadNode x = blankElement (atomThreadName x)
atomThreadLeaf :: Text -> Text -> XML.Element
atomThreadLeaf tag txt =
blankElement (atomThreadName tag) [NodeContent $ ContentText txt]
--------------------------------------------------------------------------------
xmlEntry :: Entry -> XML.Element
xmlEntry e = ( atomNode "entry"
$ map NodeElement
$ [xmlId (entryId e)]
++ [xmlTitle (entryTitle e)]
++ [xmlUpdated (entryUpdated e)]
++ map xmlAuthor (entryAuthors e)
++ map xmlCategory (entryCategories e)
++ mb xmlContent (entryContent e)
++ map xmlContributor (entryContributor e)
++ map xmlLink (entryLinks e)
++ mb xmlPublished (entryPublished e)
++ mb xmlRights (entryRights e)
++ mb xmlSource (entrySource e)
++ mb xmlSummary (entrySummary e)
++ mb xmlInReplyTo (entryInReplyTo e)
++ mb xmlInReplyTotal (entryInReplyTotal e)
++ entryOther e
)
{ elementAttributes = entryAttrs e
}
xmlContent :: EntryContent -> XML.Element
xmlContent cont = case cont of
TextContent t ->
(atomLeaf "content" t) { elementAttributes = [atomAttr "type" "text"] }
HTMLContent t ->
(atomLeaf "content" t) { elementAttributes = [atomAttr "type" "html"] }
XHTMLContent x -> (atomNode "content" [NodeElement x])
{ elementAttributes = [atomAttr "type" "xhtml"]
}
MixedContent mbTy cs ->
(atomNode "content" cs) { elementAttributes = mb (atomAttr "type") mbTy }
ExternalContent mbTy src -> (atomNode "content" [])
{ elementAttributes = atomAttr "src" src : mb (atomAttr "type") mbTy
}
xmlCategory :: Category -> XML.Element
xmlCategory c = (atomNode "category" (map NodeElement (catOther c)))
{ elementAttributes = [atomAttr "term" (catTerm c)]
++ mb (atomAttr "scheme") (catScheme c)
++ mb (atomAttr "label") (catLabel c)
}
xmlLink :: Link -> XML.Element
xmlLink l = (atomNode "link" (map NodeElement (linkOther l)))
{ elementAttributes = [atomAttr "href" (linkHref l)]
++ mb (atomAttr "rel" . either id id) (linkRel l)
++ mb (atomAttr "type") (linkType l)
++ mb (atomAttr "hreflang") (linkHrefLang l)
++ mb (atomAttr "title") (linkTitle l)
++ mb (atomAttr "length") (linkLength l)
++ linkAttrs l
}
xmlSource :: Source -> Element
xmlSource s =
atomNode "source"
$ map NodeElement
$ sourceOther s
++ map xmlAuthor (sourceAuthors s)
++ map xmlCategory (sourceCategories s)
++ mb xmlGenerator (sourceGenerator s)
++ mb xmlIcon (sourceIcon s)
++ mb xmlId (sourceId s)
++ map xmlLink (sourceLinks s)
++ mb xmlLogo (sourceLogo s)
++ mb xmlRights (sourceRights s)
++ mb xmlSubtitle (sourceSubtitle s)
++ mb xmlTitle (sourceTitle s)
++ mb xmlUpdated (sourceUpdated s)
xmlGenerator :: Generator -> Element
xmlGenerator g = (atomLeaf "generator" (genText g))
{ elementAttributes = mb (atomAttr "uri") (genURI g)
++ mb (atomAttr "version") (genVersion g)
}
xmlAuthor :: Person -> XML.Element
xmlAuthor p = atomNode "author" (xmlPerson p)
xmlContributor :: Person -> XML.Element
xmlContributor c = atomNode "contributor" (xmlPerson c)
xmlPerson :: Person -> [XML.Node]
xmlPerson p =
map NodeElement
$ [atomLeaf "name" (personName p)]
++ mb (atomLeaf "uri") (personURI p)
++ mb (atomLeaf "email") (personEmail p)
++ personOther p
xmlInReplyTo :: InReplyTo -> XML.Element
xmlInReplyTo irt = (atomThreadNode "in-reply-to" (replyToContent irt))
{ elementAttributes = mb (atomThreadAttr "ref") (Just $ replyToRef irt)
++ mb (atomThreadAttr "href") (replyToHRef irt)
++ mb (atomThreadAttr "type") (replyToType irt)
++ mb (atomThreadAttr "source") (replyToSource irt)
++ replyToOther irt
}
xmlInReplyTotal :: InReplyTotal -> XML.Element
xmlInReplyTotal irt = (atomThreadLeaf "total" (T.pack $ show $ replyToTotal irt))
{ elementAttributes = replyToTotalOther irt
}
xmlId :: Text -> XML.Element
xmlId = atomLeaf "id"
xmlIcon :: URI -> XML.Element
xmlIcon = atomLeaf "icon"
xmlLogo :: URI -> XML.Element
xmlLogo = atomLeaf "logo"
xmlUpdated :: Date -> XML.Element
xmlUpdated = atomLeaf "updated"
xmlPublished :: Date -> XML.Element
xmlPublished = atomLeaf "published"
xmlRights :: TextContent -> XML.Element
xmlRights = xmlTextContent "rights"
xmlTitle :: TextContent -> XML.Element
xmlTitle = xmlTextContent "title"
xmlSubtitle :: TextContent -> XML.Element
xmlSubtitle = xmlTextContent "subtitle"
xmlSummary :: TextContent -> XML.Element
xmlSummary = xmlTextContent "summary"
xmlTextContent :: Text -> TextContent -> XML.Element
xmlTextContent tg t = case t of
TextString s ->
(atomLeaf tg s) { elementAttributes = [atomAttr "type" "text"] }
HTMLString s ->
(atomLeaf tg s) { elementAttributes = [atomAttr "type" "html"] }
XHTMLString e -> (atomNode tg [XML.NodeElement e])
{ elementAttributes = [atomAttr "type" "xhtml"]
}
--------------------------------------------------------------------------------
mb :: (a -> b) -> Maybe a -> [b]
mb _ Nothing = []
mb f (Just x) = [f x]