feed 1.2.0.1 → 1.3.0.0
raw patch · 11 files changed
+95/−170 lines, 11 filesdep +sybnew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies added: syb
API changes (from Hackage documentation)
- Text.Atom.Feed: HTMLContent :: Element -> EntryContent
+ Text.Atom.Feed: HTMLContent :: Text -> EntryContent
Files
- CHANGELOG.md +3/−0
- README.lhs +1/−159
- README.md +1/−1
- feed.cabal +3/−1
- src/Text/Atom/Feed.hs +1/−1
- src/Text/Atom/Feed/Export.hs +1/−1
- src/Text/Atom/Feed/Import.hs +1/−5
- tests/Example/CreateAtom.hs +1/−1
- tests/ImportExport.hs +46/−0
- tests/Main.hs +2/−1
- tests/files/import_export_atom.xml +35/−0
CHANGELOG.md view
@@ -1,3 +1,6 @@+#### 1.3.0.0+* Reverted changes to `EntryContent` that came in 1.2.0.0. Thanks to Tomas Janousek.+ #### 1.2.0.1 * Get rid of xmlns:ns and ns:-prefixed attributes that confused some applications, thanks to Tomas Janousek.
README.lhs view
@@ -1,159 +1,1 @@-# Feed--[](http://hackage.haskell.org/package/feed)-[](https://travis-ci.org/bergmark/feed)--## Goal--Interfacing with *RSS* (v 0.9x, 2.x, 1.0) + *Atom* feeds.--- Parsers-- Pretty Printers-- Querying--To help working with the multiple feed formats we've ended up with-this set of modules providing parsers, pretty printers and some utility-code for querying and just generally working with a concrete-representation of feeds in Haskell.--For basic reading and editing of feeds, consult the documentation of-the Text.Feed.* hierarchy.--## Usage--Building an Atom feed is similar to building an RSS feed, but we'll-arbitrarily pick Atom here:--We'd like to generate the XML for a minimal working example.-Constructing our base `Feed` can use the smart constructor called `nullFeed`:--*This is a pattern the library maintains for smart constructors. If you want the-minimum viable 'X', use the 'nullX' constructor.*---```haskell-{-# LANGUAGE OverloadedStrings #-}--module Main where--import Prelude.Compat hiding (take)--import Data.Text-import Data.XML.Types as XML-import qualified Data.Text.Lazy as Lazy-import qualified Text.Atom.Feed as Atom-import qualified Text.Atom.Feed.Export as Export (textFeed)--myFeed :: Atom.Feed-myFeed = Atom.nullFeed- "http://example.com/atom.xml" -- ^ id- (Atom.TextString "Example Website") -- ^ title- "2017-08-01" -- ^ last updated-```--Now we can export the feed to `Text`.--```haskell-renderFeed :: Atom.Feed -> Maybe Lazy.Text-renderFeed = Export.textFeed-```--```-> renderFeed myFeed-<?xml version="1.0" encoding="UTF-8"?>-<feed xmlns="http://www.w3.org/2005/Atom">- <title type="text">Example Website</title>- <id>http://example.com/atom.xml</id>- <updated>2017-08-01</updated>-</feed>-```--The `TextContent` sum type allows us to specify which type of text we're providing.--```haskell-data TextContent- = TextString Text- | HTMLString Text- | XHTMLString XML.Element- deriving (Show)-```--A feed isn't very useful without some content though, so we'll need to build up an `Entry`.--```haskell-data Post- = Post- { _postedOn :: Text- , _url :: Text- , _content :: Text- }--examplePosts :: [Post]-examplePosts =- [ Post "2000-02-02T18:30:00Z" "http://example.com/2" "Bar."- , Post "2000-01-01T18:30:00Z" "http://example.com/1" "Foo."- ]-```--Our `Post` data type will need to be converted into an `Entry` in order to use it in the top level `Feed`. The required fields for an entry are an url "id" from which an entry's presence can be validated, a title for the entry, and a posting date. In this example we'll also add authors, link, and the entries actual content, since we have all of this available in the `Post` provided.--```haskell-toEntry :: Post -> Atom.Entry-toEntry (Post date url content) =- (Atom.nullEntry- url -- The ID field. Must be a link to validate.- (Atom.TextString (take 20 content)) -- Title- date)- { Atom.entryAuthors = [Atom.nullPerson {Atom.personName = "J. Smith"}]- , Atom.entryLinks = [Atom.nullLink url]- , Atom.entryContent = Just (Atom.TextContent content)- }-```--From the base feed we created earlier, we can add further details (`Link` and `Entry` content) as well as map our `toEntry` function over the posts we'd like to include in the feed.--```haskell-feed :: Atom.Feed-feed =- myFeed { Atom.feedEntries = fmap toEntry examplePosts- , Atom.feedLinks = [Atom.nullLink "http://example.com/"]- }-```--```-> renderFeed feed-<?xml version="1.0" encoding="UTF-8"?>-<feed xmlns="http://www.w3.org/2005/Atom">- <title type="text">Example Website</title>- <id>http://example.com/atom.xml</id>- <updated>2017-08-01</updated>- <link href="http://example.com/"/>- <entry>- <id>http://example.com/2</id>- <title type="text">Bar.</title>- <updated>2000-02-02T18:30:00Z</updated>- <author>- <name>J. Smith</name>- </author>- <content type="text">Bar.</content>- <link href="http://example.com/2"/>- </entry>- <entry>- <id>http://example.com/1</id>- <title type="text">Foo.</title>- <updated>2000-01-01T18:30:00Z</updated>- <author>- <name>J. Smith</name>- </author>- <content type="text">Foo.</content>- <link href="http://example.com/1"/>- </entry>-</feed>-```-See [here](https://github.com/bergmark/feed/blob/master/tests/Example/CreateAtom.hs) for this content as an uninterrupted running example.--```haskell--- Dummy main needed to compile this file with markdown-unlit-main :: IO ()-main = return ()-```+README.md
README.md view
@@ -106,7 +106,7 @@ date) { Atom.entryAuthors = [Atom.nullPerson {Atom.personName = "J. Smith"}] , Atom.entryLinks = [Atom.nullLink url]- , Atom.entryContent = Just (Atom.TextContent content)+ , Atom.entryContent = Just (Atom.HTMLContent content) } ```
feed.cabal view
@@ -1,5 +1,5 @@ name: feed-version: 1.2.0.1+version: 1.3.0.0 license: BSD3 license-file: LICENSE category: Text@@ -101,6 +101,7 @@ Paths_feed Example Example.CreateAtom+ ImportExport Text.Atom.Tests Text.Feed.Util.Tests Text.RSS.Equals@@ -114,6 +115,7 @@ , HUnit >= 1.2 && < 1.7 , feed , old-time >= 1 && < 1.2+ , syb , test-framework == 0.8.* , test-framework-hunit == 0.3.* , text < 1.3
src/Text/Atom/Feed.hs view
@@ -93,7 +93,7 @@ data EntryContent = TextContent Text- | HTMLContent XML.Element+ | HTMLContent Text | XHTMLContent XML.Element | MixedContent (Maybe Text) [XML.Node]
src/Text/Atom/Feed/Export.hs view
@@ -173,7 +173,7 @@ xmlContent cont = case cont of TextContent t -> (atomLeaf "content" t) {elementAttributes = [atomAttr "type" "text"]}- HTMLContent x -> (atomNode "content" [NodeElement x]) {elementAttributes = [atomAttr "type" "html"]}+ 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}
src/Text/Atom/Feed/Import.hs view
@@ -253,11 +253,7 @@ case pAttr "type" e of Nothing -> return (TextContent (elementTexts e)) Just "text" -> return (TextContent (elementTexts e))- Just "html" -> - case children e of- [] -> return (TextContent "")- [c] -> return (HTMLContent c)- _ -> Nothing+ Just "html" -> return (HTMLContent (elementTexts e)) Just "xhtml" -> case children e of [] -> return (TextContent "")
tests/Example/CreateAtom.hs view
@@ -35,7 +35,7 @@ date) { Atom.entryAuthors = [Atom.nullPerson {Atom.personName = "J. Smith"}] , Atom.entryLinks = [Atom.nullLink url]- , Atom.entryContent = Just (Atom.TextContent content)+ , Atom.entryContent = Just (Atom.HTMLContent content) } feed :: [Post] -> Atom.Feed
+ tests/ImportExport.hs view
@@ -0,0 +1,46 @@+module ImportExport+ ( importExportTests+ ) where++import Prelude.Compat++import Data.Generics (everywhere, mkT)+import Data.Text (strip)+import Test.Framework (Test, testGroup)+import Test.Framework.Providers.HUnit (testCase)+import Test.HUnit ((@=?))+import qualified Data.Text.Lazy.IO as T+import qualified Data.XML.Types as XML+import qualified Text.XML as C++import Text.Feed.Export (xmlFeed)+import Text.Feed.Import (readAtom)+import Text.Feed.Types (Feed)+import Text.RSS.Utils (elementToDoc)++import Paths_feed++importExportTests :: Test+importExportTests = testGroup "ImportExport"+ [ testImportExport readAtom "tests/files/import_export_atom.xml"+ ]++testImportExport :: (XML.Element -> Maybe Feed) -> FilePath -> Test+testImportExport readFeed fileName = testCase fileName $ do+ input <- T.readFile =<< getDataFileName fileName+ let inputXml = C.parseText_ C.def input+ let Just feed = readFeed $ C.toXMLElement $ C.documentRoot inputXml+ let Just outputXml = elementToDoc $ xmlFeed feed+ let output = C.renderText C.def outputXml+ let input' = C.renderText C.def $ stripXmlWhitespace inputXml+ input' @=? output++stripXmlWhitespace :: C.Document -> C.Document+stripXmlWhitespace = everywhere (mkT stripWhitespaceNodes)+ where+ stripWhitespaceNodes e =+ e { C.elementNodes = filter (not . isWhite) (C.elementNodes e) }++ isWhite (C.NodeContent t) = strip t == ""+ isWhite (C.NodeComment _) = True+ isWhite _ = False
tests/Main.hs view
@@ -5,10 +5,11 @@ import Prelude.Compat import Example (exampleTests)+import ImportExport (importExportTests) import Test.Framework (defaultMain) import Text.Atom.Tests (atomTests) import Text.Feed.Util.Tests (feedUtilTests) import Text.RSS.Tests (rssTests) main :: IO ()-main = defaultMain [rssTests, atomTests, feedUtilTests, exampleTests]+main = defaultMain [rssTests, atomTests, feedUtilTests, exampleTests, importExportTests]
+ tests/files/import_export_atom.xml view
@@ -0,0 +1,35 @@+<?xml version="1.0" encoding="UTF-8"?>+<feed xmlns="http://www.w3.org/2005/Atom">+ <title type="text">Example Feed</title>+ <id>urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af6</id>+ <updated>2003-12-13T18:30:02Z</updated>+ <link href="http://example.org/feed/" rel="self"/>+ <link href="http://example.org/"/>+ <subtitle type="text">A subtitle.</subtitle>+ <entry>+ <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>+ <title type="text">Atom-Powered Robots Run Amok</title>+ <updated>2003-12-13T18:30:00Z</updated>+ <author>+ <name>John Doe</name>+ <email>johndoe@example.com</email>+ </author>+ <content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>This is the entry content.</p></div></content>+ <link href="http://example.org/2003/12/13/atom03"/>+ <link href="http://example.org/2003/12/13/atom03.html" rel="alternate" type="text/html"/>+ <link href="http://example.org/2003/12/13/atom03/edit" rel="edit"/>+ <summary type="html"><div><p>This is the entry content.</p></div></summary>+ </entry>+ <entry>+ <id>urn:uuid:f5ae72c9-b02e-42bc-957e-bbfe60b2c4a9</id>+ <title type="text">Robot-Powered Atoms Run Amok</title>+ <updated>2003-12-13T19:00:00Z</updated>+ <author>+ <name>John Doe</name>+ <email>johndoe@example.com</email>+ </author>+ <content type="html"><div><p>This is the entry content.</p></div></content>+ <link href="http://example.org/2003/12/13/atom04"/>+ <summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>This is the entry content.</p></div></summary>+ </entry>+</feed>