packages feed

rss-conduit 0.6.0.0 → 0.6.0.1

raw patch · 3 files changed

+78/−31 lines, 3 filesdep ~timerepdep ~xml-conduitPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: timerep, xml-conduit

API changes (from Hackage documentation)

- Text.RSS.Lens: channelCategoriesL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) [RssCategory]
+ Text.RSS.Lens: channelCategoriesL :: forall extensions_aall. Lens' (RssDocument extensions_aall) [RssCategory]
- Text.RSS.Lens: channelCloudL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) (Maybe RssCloud)
+ Text.RSS.Lens: channelCloudL :: forall extensions_aall. Lens' (RssDocument extensions_aall) (Maybe RssCloud)
- Text.RSS.Lens: channelCopyrightL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) Text
+ Text.RSS.Lens: channelCopyrightL :: forall extensions_aall. Lens' (RssDocument extensions_aall) Text
- Text.RSS.Lens: channelDescriptionL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) Text
+ Text.RSS.Lens: channelDescriptionL :: forall extensions_aall. Lens' (RssDocument extensions_aall) Text
- Text.RSS.Lens: channelDocsL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) (Maybe RssURI)
+ Text.RSS.Lens: channelDocsL :: forall extensions_aall. Lens' (RssDocument extensions_aall) (Maybe RssURI)
- Text.RSS.Lens: channelExtensionsL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) (RssChannelExtension extensions_afpr)
+ Text.RSS.Lens: channelExtensionsL :: forall extensions_aall. Lens' (RssDocument extensions_aall) (RssChannelExtension extensions_aall)
- Text.RSS.Lens: channelGeneratorL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) Text
+ Text.RSS.Lens: channelGeneratorL :: forall extensions_aall. Lens' (RssDocument extensions_aall) Text
- Text.RSS.Lens: channelImageL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) (Maybe RssImage)
+ Text.RSS.Lens: channelImageL :: forall extensions_aall. Lens' (RssDocument extensions_aall) (Maybe RssImage)
- Text.RSS.Lens: channelItemsL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) [RssItem extensions_afpr]
+ Text.RSS.Lens: channelItemsL :: forall extensions_aall. Lens' (RssDocument extensions_aall) [RssItem extensions_aall]
- Text.RSS.Lens: channelLanguageL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) Text
+ Text.RSS.Lens: channelLanguageL :: forall extensions_aall. Lens' (RssDocument extensions_aall) Text
- Text.RSS.Lens: channelLastBuildDateL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) (Maybe UTCTime)
+ Text.RSS.Lens: channelLastBuildDateL :: forall extensions_aall. Lens' (RssDocument extensions_aall) (Maybe UTCTime)
- Text.RSS.Lens: channelLinkL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) RssURI
+ Text.RSS.Lens: channelLinkL :: forall extensions_aall. Lens' (RssDocument extensions_aall) RssURI
- Text.RSS.Lens: channelManagingEditorL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) Text
+ Text.RSS.Lens: channelManagingEditorL :: forall extensions_aall. Lens' (RssDocument extensions_aall) Text
- Text.RSS.Lens: channelPubDateL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) (Maybe UTCTime)
+ Text.RSS.Lens: channelPubDateL :: forall extensions_aall. Lens' (RssDocument extensions_aall) (Maybe UTCTime)
- Text.RSS.Lens: channelRatingL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) Text
+ Text.RSS.Lens: channelRatingL :: forall extensions_aall. Lens' (RssDocument extensions_aall) Text
- Text.RSS.Lens: channelSkipDaysL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) (Set Day)
+ Text.RSS.Lens: channelSkipDaysL :: forall extensions_aall. Lens' (RssDocument extensions_aall) (Set Day)
- Text.RSS.Lens: channelSkipHoursL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) (Set Hour)
+ Text.RSS.Lens: channelSkipHoursL :: forall extensions_aall. Lens' (RssDocument extensions_aall) (Set Hour)
- Text.RSS.Lens: channelTextInputL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) (Maybe RssTextInput)
+ Text.RSS.Lens: channelTextInputL :: forall extensions_aall. Lens' (RssDocument extensions_aall) (Maybe RssTextInput)
- Text.RSS.Lens: channelTitleL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) Text
+ Text.RSS.Lens: channelTitleL :: forall extensions_aall. Lens' (RssDocument extensions_aall) Text
- Text.RSS.Lens: channelTtlL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) (Maybe Int)
+ Text.RSS.Lens: channelTtlL :: forall extensions_aall. Lens' (RssDocument extensions_aall) (Maybe Int)
- Text.RSS.Lens: channelWebmasterL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) Text
+ Text.RSS.Lens: channelWebmasterL :: forall extensions_aall. Lens' (RssDocument extensions_aall) Text
- Text.RSS.Lens: documentVersionL :: forall extensions_afpr. Lens' (RssDocument extensions_afpr) Version
+ Text.RSS.Lens: documentVersionL :: forall extensions_aall. Lens' (RssDocument extensions_aall) Version
- Text.RSS.Lens: itemAuthorL :: forall extensions_aftx. Lens' (RssItem extensions_aftx) Text
+ Text.RSS.Lens: itemAuthorL :: forall extensions_aan8. Lens' (RssItem extensions_aan8) Text
- Text.RSS.Lens: itemCategoriesL :: forall extensions_aftx. Lens' (RssItem extensions_aftx) [RssCategory]
+ Text.RSS.Lens: itemCategoriesL :: forall extensions_aan8. Lens' (RssItem extensions_aan8) [RssCategory]
- Text.RSS.Lens: itemCommentsL :: forall extensions_aftx. Lens' (RssItem extensions_aftx) (Maybe RssURI)
+ Text.RSS.Lens: itemCommentsL :: forall extensions_aan8. Lens' (RssItem extensions_aan8) (Maybe RssURI)
- Text.RSS.Lens: itemDescriptionL :: forall extensions_aftx. Lens' (RssItem extensions_aftx) Text
+ Text.RSS.Lens: itemDescriptionL :: forall extensions_aan8. Lens' (RssItem extensions_aan8) Text
- Text.RSS.Lens: itemEnclosureL :: forall extensions_aftx. Lens' (RssItem extensions_aftx) [RssEnclosure]
+ Text.RSS.Lens: itemEnclosureL :: forall extensions_aan8. Lens' (RssItem extensions_aan8) [RssEnclosure]
- Text.RSS.Lens: itemExtensionsL :: forall extensions_aftx extensions_azY8. Lens (RssItem extensions_aftx) (RssItem extensions_azY8) (RssItemExtension extensions_aftx) (RssItemExtension extensions_azY8)
+ Text.RSS.Lens: itemExtensionsL :: forall extensions_aan8 extensions_asP5. Lens (RssItem extensions_aan8) (RssItem extensions_asP5) (RssItemExtension extensions_aan8) (RssItemExtension extensions_asP5)
- Text.RSS.Lens: itemGuidL :: forall extensions_aftx. Lens' (RssItem extensions_aftx) (Maybe RssGuid)
+ Text.RSS.Lens: itemGuidL :: forall extensions_aan8. Lens' (RssItem extensions_aan8) (Maybe RssGuid)
- Text.RSS.Lens: itemLinkL :: forall extensions_aftx. Lens' (RssItem extensions_aftx) (Maybe RssURI)
+ Text.RSS.Lens: itemLinkL :: forall extensions_aan8. Lens' (RssItem extensions_aan8) (Maybe RssURI)
- Text.RSS.Lens: itemPubDateL :: forall extensions_aftx. Lens' (RssItem extensions_aftx) (Maybe UTCTime)
+ Text.RSS.Lens: itemPubDateL :: forall extensions_aan8. Lens' (RssItem extensions_aan8) (Maybe UTCTime)
- Text.RSS.Lens: itemSourceL :: forall extensions_aftx. Lens' (RssItem extensions_aftx) (Maybe RssSource)
+ Text.RSS.Lens: itemSourceL :: forall extensions_aan8. Lens' (RssItem extensions_aan8) (Maybe RssSource)
- Text.RSS.Lens: itemTitleL :: forall extensions_aftx. Lens' (RssItem extensions_aftx) Text
+ Text.RSS.Lens: itemTitleL :: forall extensions_aan8. Lens' (RssItem extensions_aan8) Text

Files

rss-conduit.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: rss-conduit-version: 0.6.0.0+version: 0.6.0.1 build-type: Simple license: CC0-1.0 license-file: LICENSE@@ -57,9 +57,9 @@         text -any,         template-haskell -any,         time >=1.5,-        timerep >=2.0,+        timerep >=2.0.1,         uri-bytestring >=0.2,-        xml-conduit >=1.5,+        xml-conduit >=1.9,         xml-types -any     hs-source-dirs: src @@ -87,7 +87,7 @@         time >=1.5,         text -any,         uri-bytestring >=0.2,-        xml-conduit >=1.3,+        xml-conduit >=1.9,         xml-types -any     hs-source-dirs: test @@ -110,7 +110,7 @@         time >=1.5,         text -any,         uri-bytestring >=0.2,-        xml-conduit >=1.3,+        xml-conduit >=1.9,         xml-types -any     hs-source-dirs: test     other-modules:
src/Text/RSS/Conduit/Parse.hs view
@@ -39,6 +39,7 @@ import           Data.Text                    as Text import           Data.Text.Encoding import           Data.Time.Clock+import           Data.Time.Format import           Data.Time.LocalTime import           Data.Time.RFC3339 import           Data.Time.RFC822@@ -86,11 +87,20 @@ tagName' :: MonadThrow m => Text -> AttrParser a -> (a -> ConduitM Event o m b) -> ConduitM Event o m (Maybe b) tagName' t = tag' (matching $ \n -> nameLocalName n == t && isNothing (nameNamespace n)) --- | Tag which content is a date-time that follows RFC 3339 format.+-- | Tag which content is a date-time.+-- RSS specification demands that date-times are formatted according to RFC 822,+-- but this implementation is more lenient. tagDate :: (MonadThrow m) => NameMatcher a -> ConduitM Event o m (Maybe UTCTime)-tagDate name = tagIgnoreAttrs name $ fmap zonedTimeToUTC $ do+tagDate name = tagIgnoreAttrs name $ do   text <- content-  maybe (throw $ InvalidTime text) return $ parseTimeRFC822 text <|> parseTimeRFC3339 text+  maybe (throw $ InvalidTime text) return $+    rfc822Time text <|> rfc3339Time text <|> rfc3339Date text <|> customDate1 text <|> customDate2 text+  where rfc822Time t = zonedTimeToUTC <$> parseTimeRFC822 t+        rfc3339Time t = zonedTimeToUTC <$> parseTimeRFC3339 t+        rfc3339Date t = UTCTime <$> parseDateRFC3339 t <*> pure 0+        customDate1 t = parseTimeM True defaultTimeLocale "%F %T" (Text.unpack t)+        customDate2 t = parseTimeM True defaultTimeLocale "%F %R" (Text.unpack t)+  headRequiredC :: MonadThrow m => Text -> ConduitT a b m a headRequiredC e = maybe (throw $ MissingElement e) return =<< headC
test/Main.hs view
@@ -88,7 +88,7 @@   return $ testGroup "RSS golden tests" $ do     xmlFile <- xmlFiles     let goldenFile = addExtension xmlFile ".golden"-        f file = fmap (Lazy.encodeUtf8 . fromString . show) $ runResourceT $ runConduit $ sourceFile file .| Conduit.decodeUtf8C .| XML.parseText' def .| parser+        f file = fmap (Lazy.encodeUtf8 . fromString . show) $ runResourceT $ runConduit $ sourceFile file .| Conduit.decodeUtf8C .| XML.parseText def .| parser         parser = rssDocument :: MonadThrow m => ConduitM Event o m (Maybe (RssDocument NoExtensions))      return $ goldenVsString xmlFile goldenFile $ f xmlFile@@ -96,7 +96,7 @@  skipHoursCase :: TestTree skipHoursCase = testCase "<skipHours> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rssSkipHours+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssSkipHours   result @?= [Hour 0, Hour 9, Hour 18, Hour 21]   where input = [ "<skipHours>"                 , "<hour>21</hour>"@@ -109,7 +109,7 @@  skipDaysCase :: TestTree skipDaysCase = testCase "<skipDays> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rssSkipDays+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssSkipDays   result @?= [Monday, Saturday, Friday]   where input = [ "<skipDays>"                 , "<day>Monday</day>"@@ -121,7 +121,7 @@  rss1TextInputCase :: TestTree rss1TextInputCase = testCase "RSS1 <textinput> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rss1TextInput+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rss1TextInput   result^.textInputTitleL @?= "Search XML.com"   result^.textInputDescriptionL @?= "Search XML.com's XML collection"   result^.textInputNameL @?= "s"@@ -136,7 +136,7 @@  rss2TextInputCase :: TestTree rss2TextInputCase = testCase "RSS2 <textInput> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rssTextInput+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssTextInput   result^.textInputTitleL @?= "Title"   result^.textInputDescriptionL @?= "Description"   result^.textInputNameL @?= "Name"@@ -151,7 +151,7 @@  rss1ImageCase :: TestTree rss1ImageCase = testCase "RSS1 <image> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rss1Image+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rss1Image   result^.imageUriL @?= RssURI [uri|http://xml.com/universal/images/xml_tiny.gif|]   result^.imageTitleL @?= "XML.com"   result^.imageLinkL @?= RssURI [uri|http://www.xml.com|]@@ -166,7 +166,7 @@  rss2ImageCase :: TestTree rss2ImageCase = testCase "RSS2 <image> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rssImage+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssImage   result^.imageUriL @?= RssURI [uri|http://image.ext|]   result^.imageTitleL @?= "Title"   result^.imageLinkL @?= RssURI [uri|http://link.ext|]@@ -187,7 +187,7 @@  categoryCase :: TestTree categoryCase = testCase "<category> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rssCategory+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssCategory   result @?= RssCategory "Domain" "Name"   where input = [ "<category domain=\"Domain\">"                 , "Name"@@ -196,7 +196,7 @@  cloudCase :: TestTree cloudCase = testCase "<cloud> element" $ do-  result1:result2:_ <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| XML.many rssCloud+  result1:result2:_ <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| XML.many rssCloud   result1 @?= RssCloud uri "pingMe" ProtocolSoap   result2 @?= RssCloud uri "myCloud.rssPleaseNotify" ProtocolXmlRpc   where input = [ "<cloud domain=\"rpc.sys.com\" port=\"80\" path=\"/RPC2\" registerProcedure=\"pingMe\" protocol=\"soap\"/>"@@ -206,7 +206,7 @@  guidCase :: TestTree guidCase = testCase "<guid> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| XML.many rssGuid+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| XML.many rssGuid   result @?= [GuidUri uri, GuidText "1", GuidText "2"]   where input = [ "<guid isPermaLink=\"true\">//guid.ext</guid>"                 , "<guid isPermaLink=\"false\">1</guid>"@@ -216,7 +216,7 @@  enclosureCase :: TestTree enclosureCase = testCase "<enclosure> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rssEnclosure+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssEnclosure   result @?= RssEnclosure url 12216320 "audio/mpeg"   where input = [ "<enclosure url=\"http://www.scripting.com/mp3s/weatherReportSuite.mp3\" length=\"12216320\" type=\"audio/mpeg\" />"                 ]@@ -224,7 +224,7 @@  sourceCase :: TestTree sourceCase = testCase "<source> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rssSource+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssSource   result @?= RssSource url "Tomalak's Realm"   where input = [ "<source url=\"http://www.tomalak.org/links2.xml\">Tomalak's Realm</source>"                 ]@@ -232,7 +232,7 @@  rss1ItemCase :: TestTree rss1ItemCase = testCase "RSS1 <item> element" $ do-  Just result <- runResourceT $ runConduit $ sourceList input .| XML.parseText' def .| rss1Item+  Just result <- runResourceT $ runConduit $ sourceList input .| XML.parseText def .| rss1Item   result^.itemTitleL @?= "Processing Inclusions with XSLT"   result^.itemLinkL @?= Just link   result^.itemDescriptionL @?= "Processing document inclusions with general XML tools can be problematic. This article proposes a way of preserving inclusion information through SAX-based processing."@@ -254,7 +254,7 @@  rss2ItemCase1 :: TestTree rss2ItemCase1 = testCase "RSS2 <item> element 1" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rssItem+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssItem   result^.itemTitleL @?= "Example entry"   result^.itemLinkL @?= Just link   result^.itemDescriptionL @?= "Here is some text containing an interesting description."@@ -275,7 +275,7 @@  rss2ItemCase2 :: TestTree rss2ItemCase2 = testCase "RSS2 <item> element 2" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rssItem+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssItem   result^.itemTitleL @?= "Plop"   result^.itemLinkL @?= Nothing   result^.itemDescriptionL @?= ""@@ -291,10 +291,47 @@                 ]         link = RssURI [uri|http://www.example.com/blog/post/1|] +rss2ItemCase3 :: TestTree+rss2ItemCase3 = testCase "RSS2 <item> element 3" $ do+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssItem+  result^.itemExtensionsL @?= NoItemExtensions+  isJust (result^.itemPubDateL) @?= True+  where input = [ "<item>"+                , "<title>Plop</title>"+                , "<author>author@w3schools.com</author>"+                , "<pubDate>2018-07-13</pubDate>"+                , "</item>"+                ] +rss2ItemCase4 :: TestTree+rss2ItemCase4 = testCase "RSS2 <item> element 4" $ do+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssItem+  result^.itemExtensionsL @?= NoItemExtensions+  isJust (result^.itemPubDateL) @?= True+  where input = [ "<item>"+                , "<title>Plop</title>"+                , "<author>author@w3schools.com</author>"+                , "<pubDate>2018-07-13 00:00:00</pubDate>"+                , "</item>"+                ]++rss2ItemCase5 :: TestTree+rss2ItemCase5 = testCase "RSS2 <item> element 5" $ do+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rssItem+  result^.itemExtensionsL @?= NoItemExtensions+  isJust (result^.itemPubDateL) @?= True+  where input = [ "<item>"+                , "<title>Plop</title>"+                , "<author>author@w3schools.com</author>"+                , "<pubDate>2018-07-13 00:00</pubDate>"+                , "</item>"+                ]+++ rss1ChannelItemsCase :: TestTree rss1ChannelItemsCase = testCase "RSS1 <items> element" $ do-  result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| force "ERROR" rss1ChannelItems+  result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| force "ERROR" rss1ChannelItems   result @?= [resource1, resource2]   where input = [ "<items xmlns=\"http://purl.org/rss/1.0/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">"                 , "<rdf:Seq>"@@ -308,7 +345,7 @@  rss1DocumentCase :: TestTree rss1DocumentCase = testCase "<rdf> element" $ do-  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| rss1Document+  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| rss1Document   result^.documentVersionL @?= Version [1] []   result^.channelTitleL @?= "XML.com"   result^.channelDescriptionL @?= "XML.com features a rich mix of information and services for the XML community."@@ -367,7 +404,7 @@  dublinCoreChannelCase :: TestTree dublinCoreChannelCase = testCase "Dublin Core <channel> extension" $ do-  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| rssDocument+  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| rssDocument   result^.channelExtensionsL @?= DublinCoreChannel dublinCoreElement NoChannelExtensions   where input = [ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"                 , "<rss xmlns:dc=\"http://purl.org/dc/elements/1.1/\" version=\"2.0\">"@@ -395,7 +432,7 @@  dublinCoreItemCase :: TestTree dublinCoreItemCase = testCase "Dublin Core <item> extension" $ do-  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| rssItem+  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| rssItem   result^.itemExtensionsL @?= DublinCoreItem dublinCoreElement NoItemExtensions   where input = [ "<item xmlns:dc=\"http://purl.org/dc/elements/1.1/\">"                 , "<title>Example entry</title>"@@ -422,7 +459,7 @@  contentItemCase :: TestTree contentItemCase = testCase "Content <item> extension" $ do-  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| rssItem+  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| rssItem   result^.itemExtensionsL @?= ContentItem "<p>What a <em>beautiful</em> day!</p>" NoItemExtensions   where input = [ "<item xmlns:content=\"http://purl.org/rss/1.0/modules/content/\">"                 , "<title>Example entry</title>"@@ -432,7 +469,7 @@  syndicationChannelCase :: TestTree syndicationChannelCase = testCase "Syndication <channel> extension" $ do-  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| rssDocument+  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| rssDocument   result^.channelExtensionsL @?= SyndicationChannel syndicationInfo NoChannelExtensions   where input = [ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"                 , "<rss xmlns:sy=\"http://purl.org/rss/1.0/modules/syndication/\" version=\"2.0\">"@@ -454,7 +491,7 @@  atomChannelCase :: TestTree atomChannelCase = testCase "Atom <channel> extension" $ do-  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| rssDocument+  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| rssDocument   result^.channelExtensionsL @?= AtomChannel (Just link) NoChannelExtensions   where input = [ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"                 , "<rss xmlns:atom=\"http://www.w3.org/2005/Atom\" version=\"2.0\">"@@ -470,7 +507,7 @@  multipleExtensionsCase :: TestTree multipleExtensionsCase = testCase "Multiple extensions" $ do-  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| rssItem+  Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText def .| rssItem   result^.itemExtensionsL @?= ContentItem "<p>What a <em>beautiful</em> day!</p>" (AtomItem (Just link) NoItemExtensions)   where input = [ "<item xmlns:content=\"http://purl.org/rss/1.0/modules/content/\""                 , " xmlns:atom=\"http://www.w3.org/2005/Atom\">"