1-------------------------------------------------------------------- 2-- | 3-- Module : Text.Atom.Feed 4-- Copyright : (c) Galois, Inc. 2008, 5-- (c) Sigbjorn Finne 2009- 6-- License : BSD3 7-- 8-- Maintainer: Sigbjorn Finne <sof@forkIO.com> 9-- Stability : provisional 10-- Portability: portable 11-- 12-------------------------------------------------------------------- 13module Text.Atom.Feed 14 ( URI 15 , NCName 16 , Date 17 , MediaType 18 , Attr 19 , Feed(..) 20 , Entry(..) 21 , EntryContent(..) 22 , Category(..) 23 , Generator(..) 24 , Link(..) 25 , TextContent(..) 26 , txtToString 27 , Source(..) 28 , Person(..) 29 , InReplyTo(..) 30 , InReplyTotal(..) 31 , newCategory 32 , nullFeed 33 , nullEntry 34 , nullGenerator 35 , nullLink 36 , nullSource 37 , nullPerson 38 ) where 39 40import Prelude.Compat 41 42import Data.Text (Text, unpack) 43import Data.XML.Compat 44import Data.XML.Types as XML 45 46-- *Core types 47-- NOTE: In the future we may want to have more structured 48-- types for these. 49type URI = Text 50 51type NCName = Text 52 53type Date = Text 54 55type MediaType = Text 56 57data Feed = Feed 58 { feedId :: URI 59 , feedTitle :: TextContent 60 , feedUpdated :: Date 61 , feedAuthors :: [Person] 62 , feedCategories :: [Category] 63 , feedContributors :: [Person] 64 , feedGenerator :: Maybe Generator 65 , feedIcon :: Maybe URI 66 , feedLinks :: [Link] 67 , feedLogo :: Maybe URI 68 , feedRights :: Maybe TextContent 69 , feedSubtitle :: Maybe TextContent 70 , feedEntries :: [Entry] 71 , feedAttrs :: [Attr] 72 , feedOther :: [XML.Element] 73 } deriving (Show) 74 75data Entry = Entry 76 { entryId :: URI 77 , entryTitle :: TextContent 78 , entryUpdated :: Date 79 , entryAuthors :: [Person] 80 , entryCategories :: [Category] 81 , entryContent :: Maybe EntryContent 82 , entryContributor :: [Person] 83 , entryLinks :: [Link] 84 , entryPublished :: Maybe Date 85 , entryRights :: Maybe TextContent 86 , entrySource :: Maybe Source 87 , entrySummary :: Maybe TextContent 88 , entryInReplyTo :: Maybe InReplyTo 89 , entryInReplyTotal :: Maybe InReplyTotal 90 , entryAttrs :: [Attr] 91 , entryOther :: [XML.Element] 92 } deriving (Show) 93 94data EntryContent 95 = TextContent Text 96 | HTMLContent Text 97 | XHTMLContent XML.Element 98 | MixedContent (Maybe Text) 99 [XML.Node] 100 | ExternalContent (Maybe MediaType) 101 URI 102 deriving (Show) 103 104data Category = Category 105 { catTerm :: Text -- ^ the tag\/term of the category. 106 , catScheme :: Maybe URI -- ^ optional URL for identifying the categorization scheme. 107 , catLabel :: Maybe Text -- ^ human-readable label of the category 108 , catOther :: [XML.Element] -- ^ unknown elements, for extensibility. 109 } deriving (Show) 110 111data Generator = Generator 112 { genURI :: Maybe URI 113 , genVersion :: Maybe Text 114 , genText :: Text 115 } deriving (Eq, Show) 116 117data Link = Link 118 { linkHref :: URI 119 -- ToDo: make the switch over to using the Atom.Feed.Link relation type. 120 , linkRel :: Maybe (Either NCName URI) 121 , linkType :: Maybe MediaType 122 , linkHrefLang :: Maybe Text 123 , linkTitle :: Maybe Text 124 , linkLength :: Maybe Text 125 , linkAttrs :: [Attr] 126 , linkOther :: [XML.Element] 127 } deriving (Show) 128 129data TextContent 130 = TextString Text 131 | HTMLString Text 132 | XHTMLString XML.Element 133 deriving (Show) 134 135txtToString :: TextContent -> String 136txtToString (TextString s) = unpack s 137txtToString (HTMLString s) = unpack s 138txtToString (XHTMLString x) = show x 139 140data Source = Source 141 { sourceAuthors :: [Person] 142 , sourceCategories :: [Category] 143 , sourceGenerator :: Maybe Generator 144 , sourceIcon :: Maybe URI 145 , sourceId :: Maybe URI 146 , sourceLinks :: [Link] 147 , sourceLogo :: Maybe URI 148 , sourceRights :: Maybe TextContent 149 , sourceSubtitle :: Maybe TextContent 150 , sourceTitle :: Maybe TextContent 151 , sourceUpdated :: Maybe Date 152 , sourceOther :: [XML.Element] 153 } deriving (Show) 154 155data Person = Person 156 { personName :: Text 157 , personURI :: Maybe URI 158 , personEmail :: Maybe Text 159 , personOther :: [XML.Element] 160 } deriving (Show) 161 162data InReplyTo = InReplyTo 163 { replyToRef :: URI 164 , replyToHRef :: Maybe URI 165 , replyToType :: Maybe MediaType 166 , replyToSource :: Maybe URI 167 , replyToOther :: [Attr] 168 , replyToContent :: [Node] 169 } deriving (Show) 170 171data InReplyTotal = InReplyTotal 172 { replyToTotal :: Integer -- non-negative :) 173 , replyToTotalOther :: [Attr] 174 } deriving (Show) 175 176-- *Smart Constructors 177newCategory :: 178 Text -- ^catTerm 179 -> Category 180newCategory t = Category {catTerm = t, catScheme = Nothing, catLabel = Just t, catOther = []} 181 182nullFeed :: 183 URI -- ^feedId 184 -> TextContent -- ^feedTitle 185 -> Date -- ^feedUpdated 186 -> Feed 187nullFeed i t u = 188 Feed 189 { feedId = i 190 , feedTitle = t 191 , feedUpdated = u 192 , feedAuthors = [] 193 , feedCategories = [] 194 , feedContributors = [] 195 , feedGenerator = Nothing 196 , feedIcon = Nothing 197 , feedLinks = [] 198 , feedLogo = Nothing 199 , feedRights = Nothing 200 , feedSubtitle = Nothing 201 , feedEntries = [] 202 , feedAttrs = [] 203 , feedOther = [] 204 } 205 206nullEntry :: 207 URI -- ^entryId 208 -> TextContent -- ^entryTitle 209 -> Date -- ^entryUpdated 210 -> Entry 211nullEntry i t u = 212 Entry 213 { entryId = i 214 , entryTitle = t 215 , entryUpdated = u 216 , entryAuthors = [] 217 , entryCategories = [] 218 , entryContent = Nothing 219 , entryContributor = [] 220 , entryLinks = [] 221 , entryPublished = Nothing 222 , entryRights = Nothing 223 , entrySource = Nothing 224 , entrySummary = Nothing 225 , entryInReplyTo = Nothing 226 , entryInReplyTotal = Nothing 227 , entryAttrs = [] 228 , entryOther = [] 229 } 230 231nullGenerator :: 232 Text -- ^genText 233 -> Generator 234nullGenerator t = Generator {genURI = Nothing, genVersion = Nothing, genText = t} 235 236nullLink :: 237 URI -- ^linkHref 238 -> Link 239nullLink uri = 240 Link 241 { linkHref = uri 242 , linkRel = Nothing 243 , linkType = Nothing 244 , linkHrefLang = Nothing 245 , linkTitle = Nothing 246 , linkLength = Nothing 247 , linkAttrs = [] 248 , linkOther = [] 249 } 250 251nullSource :: Source 252nullSource = 253 Source 254 { sourceAuthors = [] 255 , sourceCategories = [] 256 , sourceGenerator = Nothing 257 , sourceIcon = Nothing 258 , sourceId = Nothing 259 , sourceLinks = [] 260 , sourceLogo = Nothing 261 , sourceRights = Nothing 262 , sourceSubtitle = Nothing 263 , sourceTitle = Nothing 264 , sourceUpdated = Nothing 265 , sourceOther = [] 266 } 267 268nullPerson :: Person 269nullPerson = Person {personName = "", personURI = Nothing, personEmail = Nothing, personOther = []} 270