rss-conduit 0.4.3.0 → 0.4.3.1
raw patch · 3 files changed
+29/−41 lines, 3 filesdep +filepathdep +tasty-goldenPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: filepath, tasty-golden
API changes (from Hackage documentation)
- Text.RSS.Extensions.Syndication: instance GHC.Exception.Exception Text.RSS.Extensions.Syndication.SyndicationException
- Text.RSS.Types: instance GHC.Exception.Exception Text.RSS.Types.RssException
+ Text.RSS.Extensions.Content: data family RssItemExtension extensionTag :: *
+ Text.RSS.Extensions.DublinCore: data family RssItemExtension extensionTag :: *
+ Text.RSS.Extensions.Syndication: data family RssItemExtension extensionTag :: *
+ Text.RSS.Extensions.Syndication: instance GHC.Exception.Type.Exception Text.RSS.Extensions.Syndication.SyndicationException
+ Text.RSS.Types: data family RssItemExtensions (extensionTags :: [*]) :: *
+ Text.RSS.Types: instance GHC.Exception.Type.Exception Text.RSS.Types.RssException
- Text.RSS.Conduit.Parse: rssCloud :: (MonadThrow m) => ConduitM Event o m (Maybe RssCloud)
+ Text.RSS.Conduit.Parse: rssCloud :: MonadThrow m => ConduitM Event o m (Maybe RssCloud)
- Text.RSS.Conduit.Parse: rssImage :: (MonadThrow m) => ConduitM Event o m (Maybe RssImage)
+ Text.RSS.Conduit.Parse: rssImage :: MonadThrow m => ConduitM Event o m (Maybe RssImage)
- Text.RSS.Conduit.Render: renderRssCategory :: (Monad m) => RssCategory -> ConduitT () Event m ()
+ Text.RSS.Conduit.Render: renderRssCategory :: Monad m => RssCategory -> ConduitT () Event m ()
- Text.RSS.Conduit.Render: renderRssEnclosure :: (Monad m) => RssEnclosure -> ConduitT () Event m ()
+ Text.RSS.Conduit.Render: renderRssEnclosure :: Monad m => RssEnclosure -> ConduitT () Event m ()
- Text.RSS.Conduit.Render: renderRssGuid :: (Monad m) => RssGuid -> ConduitT () Event m ()
+ Text.RSS.Conduit.Render: renderRssGuid :: Monad m => RssGuid -> ConduitT () Event m ()
- Text.RSS.Conduit.Render: renderRssImage :: (Monad m) => RssImage -> ConduitT () Event m ()
+ Text.RSS.Conduit.Render: renderRssImage :: Monad m => RssImage -> ConduitT () Event m ()
- Text.RSS.Conduit.Render: renderRssSkipDays :: (Monad m) => Set Day -> ConduitT () Event m ()
+ Text.RSS.Conduit.Render: renderRssSkipDays :: Monad m => Set Day -> ConduitT () Event m ()
- Text.RSS.Conduit.Render: renderRssSkipHours :: (Monad m) => Set Hour -> ConduitT () Event m ()
+ Text.RSS.Conduit.Render: renderRssSkipHours :: Monad m => Set Hour -> ConduitT () Event m ()
- Text.RSS.Conduit.Render: renderRssSource :: (Monad m) => RssSource -> ConduitT () Event m ()
+ Text.RSS.Conduit.Render: renderRssSource :: Monad m => RssSource -> ConduitT () Event m ()
- Text.RSS.Conduit.Render: renderRssTextInput :: (Monad m) => RssTextInput -> ConduitT () Event m ()
+ Text.RSS.Conduit.Render: renderRssTextInput :: Monad m => RssTextInput -> ConduitT () Event m ()
- Text.RSS.Lens: categoryDomainL :: Functor f => Text -> f Text -> RssCategory -> f RssCategory
+ Text.RSS.Lens: categoryDomainL :: Functor f => (Text -> f Text) -> RssCategory -> f RssCategory
- Text.RSS.Lens: categoryNameL :: Functor f => Text -> f Text -> RssCategory -> f RssCategory
+ Text.RSS.Lens: categoryNameL :: Functor f => (Text -> f Text) -> RssCategory -> f RssCategory
- Text.RSS.Lens: channelCloudL :: Functor f => Maybe RssCloud -> f Maybe RssCloud -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelCloudL :: Functor f => (Maybe RssCloud -> f (Maybe RssCloud)) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelCopyrightL :: Functor f => Text -> f Text -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelCopyrightL :: Functor f => (Text -> f Text) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelDescriptionL :: Functor f => Text -> f Text -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelDescriptionL :: Functor f => (Text -> f Text) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelDocsL :: Functor f => Maybe RssURI -> f Maybe RssURI -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelDocsL :: Functor f => (Maybe RssURI -> f (Maybe RssURI)) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelExtensionsL :: Functor f => RssChannelExtensions extensions -> f RssChannelExtensions extensions -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelExtensionsL :: Functor f => (RssChannelExtensions extensions -> f (RssChannelExtensions extensions)) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelGeneratorL :: Functor f => Text -> f Text -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelGeneratorL :: Functor f => (Text -> f Text) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelImageL :: Functor f => Maybe RssImage -> f Maybe RssImage -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelImageL :: Functor f => (Maybe RssImage -> f (Maybe RssImage)) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelLanguageL :: Functor f => Text -> f Text -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelLanguageL :: Functor f => (Text -> f Text) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelLastBuildDateL :: Functor f => Maybe UTCTime -> f Maybe UTCTime -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelLastBuildDateL :: Functor f => (Maybe UTCTime -> f (Maybe UTCTime)) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelLinkL :: Functor f => RssURI -> f RssURI -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelLinkL :: Functor f => (RssURI -> f RssURI) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelManagingEditorL :: Functor f => Text -> f Text -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelManagingEditorL :: Functor f => (Text -> f Text) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelPubDateL :: Functor f => Maybe UTCTime -> f Maybe UTCTime -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelPubDateL :: Functor f => (Maybe UTCTime -> f (Maybe UTCTime)) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelRatingL :: Functor f => Text -> f Text -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelRatingL :: Functor f => (Text -> f Text) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelSkipDaysL :: Functor f => Set Day -> f Set Day -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelSkipDaysL :: Functor f => (Set Day -> f (Set Day)) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelSkipHoursL :: Functor f => Set Hour -> f Set Hour -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelSkipHoursL :: Functor f => (Set Hour -> f (Set Hour)) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelTextInputL :: Functor f => Maybe RssTextInput -> f Maybe RssTextInput -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelTextInputL :: Functor f => (Maybe RssTextInput -> f (Maybe RssTextInput)) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelTitleL :: Functor f => Text -> f Text -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelTitleL :: Functor f => (Text -> f Text) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelTtlL :: Functor f => Maybe Int -> f Maybe Int -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelTtlL :: Functor f => (Maybe Int -> f (Maybe Int)) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: channelWebmasterL :: Functor f => Text -> f Text -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: channelWebmasterL :: Functor f => (Text -> f Text) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: cloudProtocolL :: Functor f => CloudProtocol -> f CloudProtocol -> RssCloud -> f RssCloud
+ Text.RSS.Lens: cloudProtocolL :: Functor f => (CloudProtocol -> f CloudProtocol) -> RssCloud -> f RssCloud
- Text.RSS.Lens: cloudRegisterProcedureL :: Functor f => Text -> f Text -> RssCloud -> f RssCloud
+ Text.RSS.Lens: cloudRegisterProcedureL :: Functor f => (Text -> f Text) -> RssCloud -> f RssCloud
- Text.RSS.Lens: cloudUriL :: Functor f => RssURI -> f RssURI -> RssCloud -> f RssCloud
+ Text.RSS.Lens: cloudUriL :: Functor f => (RssURI -> f RssURI) -> RssCloud -> f RssCloud
- Text.RSS.Lens: documentVersionL :: Functor f => Version -> f Version -> RssDocument extensions -> f RssDocument extensions
+ Text.RSS.Lens: documentVersionL :: Functor f => (Version -> f Version) -> RssDocument extensions -> f (RssDocument extensions)
- Text.RSS.Lens: enclosureLengthL :: Functor f => Int -> f Int -> RssEnclosure -> f RssEnclosure
+ Text.RSS.Lens: enclosureLengthL :: Functor f => (Int -> f Int) -> RssEnclosure -> f RssEnclosure
- Text.RSS.Lens: enclosureTypeL :: Functor f => Text -> f Text -> RssEnclosure -> f RssEnclosure
+ Text.RSS.Lens: enclosureTypeL :: Functor f => (Text -> f Text) -> RssEnclosure -> f RssEnclosure
- Text.RSS.Lens: enclosureUrlL :: Functor f => RssURI -> f RssURI -> RssEnclosure -> f RssEnclosure
+ Text.RSS.Lens: enclosureUrlL :: Functor f => (RssURI -> f RssURI) -> RssEnclosure -> f RssEnclosure
- Text.RSS.Lens: imageDescriptionL :: Functor f => Text -> f Text -> RssImage -> f RssImage
+ Text.RSS.Lens: imageDescriptionL :: Functor f => (Text -> f Text) -> RssImage -> f RssImage
- Text.RSS.Lens: imageHeightL :: Functor f => Maybe Int -> f Maybe Int -> RssImage -> f RssImage
+ Text.RSS.Lens: imageHeightL :: Functor f => (Maybe Int -> f (Maybe Int)) -> RssImage -> f RssImage
- Text.RSS.Lens: imageLinkL :: Functor f => RssURI -> f RssURI -> RssImage -> f RssImage
+ Text.RSS.Lens: imageLinkL :: Functor f => (RssURI -> f RssURI) -> RssImage -> f RssImage
- Text.RSS.Lens: imageTitleL :: Functor f => Text -> f Text -> RssImage -> f RssImage
+ Text.RSS.Lens: imageTitleL :: Functor f => (Text -> f Text) -> RssImage -> f RssImage
- Text.RSS.Lens: imageUriL :: Functor f => RssURI -> f RssURI -> RssImage -> f RssImage
+ Text.RSS.Lens: imageUriL :: Functor f => (RssURI -> f RssURI) -> RssImage -> f RssImage
- Text.RSS.Lens: imageWidthL :: Functor f => Maybe Int -> f Maybe Int -> RssImage -> f RssImage
+ Text.RSS.Lens: imageWidthL :: Functor f => (Maybe Int -> f (Maybe Int)) -> RssImage -> f RssImage
- Text.RSS.Lens: itemAuthorL :: Functor f => Text -> f Text -> RssItem extensions -> f RssItem extensions
+ Text.RSS.Lens: itemAuthorL :: Functor f => (Text -> f Text) -> RssItem extensions -> f (RssItem extensions)
- Text.RSS.Lens: itemCommentsL :: Functor f => Maybe RssURI -> f Maybe RssURI -> RssItem extensions -> f RssItem extensions
+ Text.RSS.Lens: itemCommentsL :: Functor f => (Maybe RssURI -> f (Maybe RssURI)) -> RssItem extensions -> f (RssItem extensions)
- Text.RSS.Lens: itemDescriptionL :: Functor f => Text -> f Text -> RssItem extensions -> f RssItem extensions
+ Text.RSS.Lens: itemDescriptionL :: Functor f => (Text -> f Text) -> RssItem extensions -> f (RssItem extensions)
- Text.RSS.Lens: itemExtensionsL :: Functor f => RssItemExtensions extensions1 -> f RssItemExtensions extensions2 -> RssItem extensions1 -> f RssItem extensions2
+ Text.RSS.Lens: itemExtensionsL :: Functor f => (RssItemExtensions extensions1 -> f (RssItemExtensions extensions2)) -> RssItem extensions1 -> f (RssItem extensions2)
- Text.RSS.Lens: itemGuidL :: Functor f => Maybe RssGuid -> f Maybe RssGuid -> RssItem extensions -> f RssItem extensions
+ Text.RSS.Lens: itemGuidL :: Functor f => (Maybe RssGuid -> f (Maybe RssGuid)) -> RssItem extensions -> f (RssItem extensions)
- Text.RSS.Lens: itemLinkL :: Functor f => Maybe RssURI -> f Maybe RssURI -> RssItem extensions -> f RssItem extensions
+ Text.RSS.Lens: itemLinkL :: Functor f => (Maybe RssURI -> f (Maybe RssURI)) -> RssItem extensions -> f (RssItem extensions)
- Text.RSS.Lens: itemPubDateL :: Functor f => Maybe UTCTime -> f Maybe UTCTime -> RssItem extensions -> f RssItem extensions
+ Text.RSS.Lens: itemPubDateL :: Functor f => (Maybe UTCTime -> f (Maybe UTCTime)) -> RssItem extensions -> f (RssItem extensions)
- Text.RSS.Lens: itemSourceL :: Functor f => Maybe RssSource -> f Maybe RssSource -> RssItem extensions -> f RssItem extensions
+ Text.RSS.Lens: itemSourceL :: Functor f => (Maybe RssSource -> f (Maybe RssSource)) -> RssItem extensions -> f (RssItem extensions)
- Text.RSS.Lens: itemTitleL :: Functor f => Text -> f Text -> RssItem extensions -> f RssItem extensions
+ Text.RSS.Lens: itemTitleL :: Functor f => (Text -> f Text) -> RssItem extensions -> f (RssItem extensions)
- Text.RSS.Lens: sourceNameL :: Functor f => Text -> f Text -> RssSource -> f RssSource
+ Text.RSS.Lens: sourceNameL :: Functor f => (Text -> f Text) -> RssSource -> f RssSource
- Text.RSS.Lens: sourceUrlL :: Functor f => RssURI -> f RssURI -> RssSource -> f RssSource
+ Text.RSS.Lens: sourceUrlL :: Functor f => (RssURI -> f RssURI) -> RssSource -> f RssSource
- Text.RSS.Lens: textInputDescriptionL :: Functor f => Text -> f Text -> RssTextInput -> f RssTextInput
+ Text.RSS.Lens: textInputDescriptionL :: Functor f => (Text -> f Text) -> RssTextInput -> f RssTextInput
- Text.RSS.Lens: textInputLinkL :: Functor f => RssURI -> f RssURI -> RssTextInput -> f RssTextInput
+ Text.RSS.Lens: textInputLinkL :: Functor f => (RssURI -> f RssURI) -> RssTextInput -> f RssTextInput
- Text.RSS.Lens: textInputNameL :: Functor f => Text -> f Text -> RssTextInput -> f RssTextInput
+ Text.RSS.Lens: textInputNameL :: Functor f => (Text -> f Text) -> RssTextInput -> f RssTextInput
- Text.RSS.Lens: textInputTitleL :: Functor f => Text -> f Text -> RssTextInput -> f RssTextInput
+ Text.RSS.Lens: textInputTitleL :: Functor f => (Text -> f Text) -> RssTextInput -> f RssTextInput
- Text.RSS.Types: RssURI :: (URIRef a) -> RssURI
+ Text.RSS.Types: RssURI :: URIRef a -> RssURI
- Text.RSS1.Conduit.Parse: rss1Image :: (MonadThrow m) => ConduitM Event o m (Maybe RssImage)
+ Text.RSS1.Conduit.Parse: rss1Image :: MonadThrow m => ConduitM Event o m (Maybe RssImage)
Files
- rss-conduit.cabal +4/−2
- src/Text/RSS/Conduit/Parse.hs +2/−2
- test/Main.hs +23/−37
rss-conduit.cabal view
@@ -1,5 +1,5 @@ name: rss-conduit-version: 0.4.3.0+version: 0.4.3.1 cabal-version: >=1.10 build-type: Simple license: PublicDomain@@ -41,7 +41,7 @@ build-depends: atom-conduit >=0.5, base >=4.8 && <5,- conduit >= 1.2.8,+ conduit >= 1.3, conduit-combinators -any, containers -any, dublincore-xml-conduit -any,@@ -72,6 +72,7 @@ conduit-combinators -any, data-default -any, dublincore-xml-conduit -any,+ filepath -any, lens-simple -any, mono-traversable -any, QuickCheck -any,@@ -80,6 +81,7 @@ safe-exceptions -any, singletons -any, tasty -any,+ tasty-golden -any, tasty-hunit -any, tasty-quickcheck -any, time >=1.5,
src/Text/RSS/Conduit/Parse.hs view
@@ -82,8 +82,8 @@ asCloudProtocol t = throwM $ InvalidProtocol t -- | Like 'tagName' but ignores the namespace.-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)+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. tagDate :: (MonadThrow m) => NameMatcher a -> ConduitM Event o m (Maybe UTCTime)
test/Main.hs view
@@ -29,8 +29,10 @@ import Data.Default import Data.Maybe import Data.Singletons.Prelude.List+import Data.String import Data.Text (Text) import Data.Text.Encoding+import qualified Data.Text.Lazy.Encoding as Lazy import Data.Time.Calendar import Data.Time.LocalTime import Data.Version@@ -38,9 +40,11 @@ import Data.Void import Data.XML.Types import Lens.Simple+import System.FilePath import System.IO import System.Timeout import Test.Tasty+import Test.Tasty.Golden (findByExtension, goldenVsString) import Test.Tasty.HUnit import Test.Tasty.QuickCheck import Text.Atom.Conduit.Parse@@ -52,10 +56,13 @@ -- }}} main :: IO ()-main = defaultMain $ testGroup "Tests"- [ unitTests- , properties- ]+main = do+ goldenTests <- genGoldenTests+ defaultMain $ testGroup "Tests"+ [ unitTests+ , goldenTests+ , properties+ ] unitTests :: TestTree unitTests = testGroup "Unit tests"@@ -75,7 +82,6 @@ , rss2ItemCase2 , rss1ChannelItemsCase , rss1DocumentCase- , rss2DocumentCase , dublinCoreChannelCase , dublinCoreItemCase , contentItemCase@@ -84,6 +90,18 @@ , multipleExtensionsCase ] +genGoldenTests :: IO TestTree+genGoldenTests = do+ xmlFiles <- findByExtension [".xml"] "."++ 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+ parser = rssDocument :: MonadThrow m => ConduitM Event o m (Maybe (RssDocument '[]))++ return $ goldenVsString xmlFile goldenFile $ f xmlFile+ properties :: TestTree properties = testGroup "Properties" [ roundtripProperty "RssTextInput" renderRssTextInput rssTextInput@@ -388,38 +406,6 @@ imageLink = RssURI [uri|http://www.xml.com|] imageUri = RssURI [uri|http://xml.com/universal/images/xml_tiny.gif|] textInputLink = RssURI [uri|http://search.xml.com|]---rss2DocumentCase :: TestTree-rss2DocumentCase = testCase "<rss> element" $ do- Just result <- runResourceT . runConduit $ sourceList input .| XML.parseText' def .| rssDocument- result^.documentVersionL @?= Version [2] []- result^.channelTitleL @?= "RSS Title"- result^.channelDescriptionL @?= "This is an example of an RSS feed"- result^.channelLinkL @?= link- result^.channelTtlL @?= Just 1800- result^.channelExtensionsL @?= RssChannelExtensions RNil- length (result^..channelItemsL) @?= 1- where input = [ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"- , "<rss version=\"2.0\">"- , "<channel>"- , "<title>RSS Title</title>"- , "<description>This is an example of an RSS feed</description>"- , "<link>http://www.example.com/main.html</link>"- , "<lastBuildDate>Mon, 06 Sep 2010 00:01:00 +0000 </lastBuildDate>"- , "<pubDate>Sun, 06 Sep 2009 16:20:00 +0000</pubDate>"- , "<ttl>1800</ttl>"- , "<item>"- , "<title>Example entry</title>"- , "<description>Here is some text containing an interesting description.</description>"- , "<link>http://www.example.com/blog/post/1</link>"- , "<guid isPermaLink=\"true\">7bd204c6-1655-4c27-aeee-53f933c5395f</guid>"- , "<pubDate>Sun, 06 Sep 2009 16:20:00 +0000</pubDate>"- , "</item>"- , "</channel>"- , "</rss>"- ]- link = RssURI [uri|http://www.example.com/main.html|] dublinCoreChannelCase :: TestTree