packages feed

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 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--[![feed](https://img.shields.io/hackage/v/feed.svg)](http://hackage.haskell.org/package/feed)-[![Build Status](https://travis-ci.org/bergmark/feed.svg?branch=master)](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">&lt;div&gt;&lt;p&gt;This is the entry content.&lt;/p&gt;&lt;/div&gt;</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">&lt;div&gt;&lt;p&gt;This is the entry content.&lt;/p&gt;&lt;/div&gt;</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>