syndication 0.6 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -139,7 +139,8 @@ module Syndication
139
139
  'http://purl.org/rss/1.0/modules/content/' => 'content',
140
140
  'http://www.itunes.com/DTDs/Podcast-1.0.dtd' => 'itunes',
141
141
  'http://www.w3.org/1999/xhtml' => 'xhtml',
142
- 'http://schemas.google.com/g/2005' => 'gd'
142
+ 'http://schemas.google.com/g/2005' => 'gd',
143
+ 'http://rssnamespace.org/feedburner/ext/1.0' => 'feedburner'
143
144
  }
144
145
 
145
146
  # Create a new AbstractParser. The optional argument consists of text to
@@ -272,11 +273,16 @@ module Syndication
272
273
 
273
274
  # Supposed to be called when REXML finds a CDATA-encoded piece of text.
274
275
  def cdata(s)
275
- # We re-encode, because (a) the API for RSS content module provides both
276
- # encoded and decoded results to the user, and (b) REXML doesn't always
277
- # seem to pass CDATA via this callback method.
276
+ # For content_encoded we re-encode, because (a) the API for RSS content
277
+ # module provides both encoded and decoded results to the user, and
278
+ # (b) REXML doesn't always seem to pass CDATA via this callback method.
279
+ # For other elements, we keep the text decoded.
278
280
  if @textstack.last
279
- @textstack.last << "<![CDATA[#{s}]]>"
281
+ if @tagstack.last == 'content:encoded'
282
+ @textstack.last << "<![CDATA[#{s}]]>"
283
+ else
284
+ @textstack.last << s
285
+ end
280
286
  end
281
287
  end
282
288
  end
@@ -0,0 +1,18 @@
1
+
2
+ module Syndication
3
+
4
+ module Feedburner
5
+ module Item
6
+ # The original URL, before feedburner rewrote it for tracking purposes
7
+ attr_accessor :feedburner_origlink
8
+ end
9
+
10
+ end
11
+
12
+ module RSS
13
+ class Item
14
+ include Feedburner::Item
15
+ end
16
+ end
17
+
18
+ end
data/rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
5
5
  require 'rake/testtask'
6
6
  require 'rubygems'
7
7
 
8
- PKG_VERSION = "0.6"
8
+ PKG_VERSION = "0.6.1"
9
9
 
10
10
  desc "Create HTML documentation from RDOC"
11
11
  Rake::RDocTask.new do |rd|
@@ -36,7 +36,7 @@ spec = Gem::Specification.new do |s|
36
36
  end
37
37
  s.require_path = "lib"
38
38
  s.test_files = ["test/atomtest.rb", "test/rsstest.rb", "test/google.rb",
39
- "test/tagsouptest.rb"]
39
+ "test/tagsouptest.rb", "test/feedburntest.rb"]
40
40
  s.has_rdoc = true
41
41
  s.extra_rdoc_files = ["README", "IMPLEMENTATION", "CHANGES", "DEVELOPER"]
42
42
  end
@@ -0,0 +1,79 @@
1
+ # Copyright � mathew <meta@pobox.com> 2006.
2
+ # Licensed under the same terms as Ruby.
3
+
4
+ require 'syndication/rss'
5
+ require 'test/unit'
6
+ require 'syndication/dublincore'
7
+ require 'syndication/content'
8
+ require 'syndication/podcast'
9
+ require 'syndication/feedburner'
10
+
11
+ module Syndication
12
+
13
+ # This class contains the unit tests for the Syndication module.
14
+ class Tests < Test::Unit::TestCase
15
+
16
+ # A set of minimal assertions that can be applied to every well-formed parsed
17
+ # feed.
18
+ def baseline_rss_assertions(feed)
19
+ assert_not_nil(feed)
20
+ assert_kind_of(Syndication::RSS::Feed, feed)
21
+ loi = feed.items
22
+ assert_not_nil(loi)
23
+ assert_kind_of(Array, loi)
24
+ assert(loi.length >= 1)
25
+ assert_not_nil(loi[0])
26
+ assert_not_nil(loi[0].description)
27
+ end
28
+
29
+ def test_feedburner
30
+ xml = <<-EOF
31
+ <?xml version="1.0" encoding="UTF-8"?>
32
+ <?xml-stylesheet href="http://feeds.sfgate.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?>
33
+ <?xml-stylesheet href="http://feeds.sfgate.com/~d/styles/itemcontent.css" type="text/css" media="screen"?>
34
+ <rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
35
+ <channel>
36
+ <title>SFGate: Top News Stories</title>
37
+ <link>http://www.sfgate.com/</link>
38
+ <description>Top news stories. From SFGate.com: the Bay Area's home page, online home of the San Francisco Chronicle and much more.</description>
39
+ <language>en-us</language>
40
+ <copyright>Copyright 2006 Hearst Communications, Inc.</copyright>
41
+ <managingEditor>ed@sfgate.com (SFGate Editorial staff)</managingEditor>
42
+ <webMaster>support@sfgate.com (SFGate technical support)</webMaster>
43
+ <lastBuildDate>Sun, 09 Jul 2006 14:21:10 PDT</lastBuildDate>
44
+ <category>News</category>
45
+ <category>Newspapers</category>
46
+ <category>San Francisco</category>
47
+ <category>San Francisco Bay Area</category>
48
+ <docs>http://blogs.law.harvard.edu/tech/rss</docs>
49
+ <image>
50
+ <url>http://www.sfgate.com/templates/types/syndication/pages/rss/graphics/sfgate_logo.png</url>
51
+ <title>SFGate: Top News Stories</title>
52
+ <link>http://www.sfgate.com/</link>
53
+ </image>
54
+ <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://www.sfgate.com/rss/feeds/news.xml" type="application/rss+xml" /><feedburner:browserFriendly>This is an RSS feed, but with the headlines made visible. Choose one of the buttons to add this feed to your favorite RSS reader.</feedburner:browserFriendly>
55
+ <item>
56
+ <title><![CDATA[Italy Beats France for 4th World Cup Title]]></title>
57
+ <link>http://feeds.sfgate.com/sfgate/rss/feeds/news?m=4300</link>
58
+ <description>Italy let France do nearly anything it wanted Sunday, except win the World Cup. That belongs to the Azzurri, 5-3 in a shootout after a 1-1 draw. Outplayed for an hour and into extra time, the Italians won it after French captain Zinedine Zidane was...&lt;img src="http://feeds.sfgate.com/sfgate/rss/feeds/news?g=4300"/&gt;</description>
59
+ <author><![CDATA[By BARRY WILNER, AP Sports Writer]]></author>
60
+ <pubDate>Sun, 09 Jul 2006 14:14:59 PDT</pubDate>
61
+
62
+ <guid isPermaLink="false">/n/a/2006/07/09/sports/s134544D82.DTL</guid>
63
+ <feedburner:origLink>http://www.sfgate.com/cgi-bin/article.cgi?f=/n/a/2006/07/09/sports/s134544D82.DTL&amp;feed=rss.news</feedburner:origLink>
64
+ </item>
65
+ </channel>
66
+ </rss>
67
+ EOF
68
+ f = Syndication::RSS::Parser.new.parse(xml)
69
+ il = f.items
70
+ assert_not_nil(il)
71
+ assert(il.length == 1)
72
+ i = il.first
73
+ assert_not_nil(i.feedburner_origlink)
74
+ assert(i.feedburner_origlink == "http://www.sfgate.com/cgi-bin/article.cgi?f=/n/a/2006/07/09/sports/s134544D82.DTL&feed=rss.news")
75
+ end
76
+
77
+ end
78
+
79
+ end
data/test/rsstest.rb CHANGED
@@ -117,7 +117,6 @@ class Tests < Test::Unit::TestCase
117
117
  <link>http://www.example.com</link>
118
118
  <width>42</width>
119
119
  <height>23</height>
120
- <description>The Example Logo</description>
121
120
  </image>
122
121
  <rating>(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))</rating>
123
122
  <textInput>
@@ -316,6 +315,108 @@ class Tests < Test::Unit::TestCase
316
315
  assert(i.itunes_duration == 232, "Duration computed incorrectly")
317
316
  end
318
317
 
318
+ # Test a well-formed RSS2 feed with every element possible and more than
319
+ # one item, with all kinds of stuff CDATA escaped.
320
+ def test_rss2_wf_full_cdata
321
+ xml = <<-EOF
322
+ <rss version="2">
323
+ <channel>
324
+ <title><![CDATA[Example Feed]]></title>
325
+ <link>http://www.example.com/</link>
326
+ <description><![CDATA[This is merely an example.]]></description>
327
+ <language>en-us</language>
328
+ <copyright>Copyright 2004 The Example Corporation.</copyright>
329
+ <managingEditor>editor@example.com</managingEditor>
330
+ <webMaster>webmaster@example.com</webMaster>
331
+ <pubDate>Sat, 07 Sep 2002 00:01:02 EDT</pubDate>
332
+ <lastBuildDate>Sat, 7 Sep 02 13:14:15 -0600</lastBuildDate>
333
+ <category>examples</category>
334
+ <category>boring</category>
335
+ <generator>vim of course</generator>
336
+ <docs>http://blogs.law.harvard.edu/tech/rss</docs>
337
+ <cloud domain="rpc.sys.com" port="80" path="/RPC2" registerProcedure="pingMe" protocol="soap"/>
338
+ <ttl>90</ttl>
339
+ <image>
340
+ <title><![CDATA[Example Inc]]></title>
341
+ <url>http://www.example.com/images/logo.jpg</url>
342
+ <link>http://www.example.com</link>
343
+ <width>42</width>
344
+ <height>23</height>
345
+ </image>
346
+ <rating>(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))</rating>
347
+ <textInput>
348
+ <title>Submit</title>
349
+ <description>Enter keywords</description>
350
+ <name>SearchKeywords</name>
351
+ <link>http://www.example.com/cgi-bin/search.pl</link>
352
+ </textInput>
353
+ <skipHours>
354
+ <hour>0</hour>
355
+ <hour>23</hour>
356
+ </skipHours>
357
+ <skipDays>
358
+ <day>Monday</day>
359
+ <day>Sunday</day>
360
+ </skipDays>
361
+ <item>
362
+ <title>Our stock price shot up</title>
363
+ <link>http://www.example.com/news/2.html</link>
364
+ <description>We were hyped in the press!</description>
365
+ </item>
366
+ <item>
367
+ <title><![CDATA[Unencoded < > and & are allowed.]]></title>
368
+ <link><![CDATA[http://www.example.com/news/1.html]]></link>
369
+ <description><![CDATA[If this was any less interesting, it would be amazing.]]></description>
370
+ <author><![CDATA[fred@example.com]]></author>
371
+ <pubDate>Sat, 07 Sep 2002 00:01:02 EDT</pubDate>
372
+ <category>dull</category>
373
+ <category>amazingly</category>
374
+ <comments>http://www.example.com/news/comments/1.html</comments>
375
+ <enclosure url="http://www.example.com/mp3/advertisement.mp3" length="123987" type="audio/mpeg" />
376
+ <guid>4asd98dgf9a74@example.com</guid>
377
+ <source url="http://www.example.com/news.xml">Example News</source>
378
+ </item>
379
+ </channel>
380
+ </rss>
381
+ EOF
382
+ f = Syndication::RSS::Parser.new.parse(xml)
383
+ baseline_rss_assertions(f)
384
+ for elem in %w(title link description language copyright managingeditor webmaster pubdate lastbuilddate category generator docs cloud ttl textinput rating skiphours skipdays)
385
+ assert_not_nil(f.channel.send(elem), "feed.channel.#{elem} is nil, it shouldn't be")
386
+ assert(f.channel.send(elem).to_s.length > 0)
387
+ end
388
+ # Check CDATA is decoded properly
389
+ assert(f.channel.title == 'Example Feed')
390
+ assert(f.channel.description == 'This is merely an example.')
391
+ items = f.items
392
+ assert(items.length == 2)
393
+ i = items.last
394
+ for elem in %w(title link description author pubdate category comments enclosure guid source)
395
+ assert_not_nil(i.send(elem), "feed.channel.item[1].#{elem} is nil, it shouldn't be")
396
+ end
397
+ cats = i.category
398
+ assert(i.title == 'Unencoded < > and & are allowed.')
399
+ assert(i.link == 'http://www.example.com/news/1.html')
400
+ assert(cats.length == 2)
401
+ assert(cats.first == 'dull')
402
+ assert(cats.last == 'amazingly')
403
+ assert(f.channel.skiphours.length == 2)
404
+ assert(f.channel.skiphours.first == 0)
405
+ assert(f.channel.skiphours.last == 23)
406
+ assert(f.channel.pubdate.kind_of?(DateTime))
407
+ assert(f.channel.lastbuilddate.kind_of?(DateTime))
408
+ assert(f.channel.pubdate.mday == 7)
409
+ assert(f.channel.pubdate.month == 9)
410
+ assert(f.channel.lastbuilddate.mday == 7)
411
+ assert(f.channel.lastbuilddate.month == 9)
412
+ c = f.channel
413
+ assert_not_nil(c)
414
+ assert_kind_of(Syndication::RSS::Channel, c)
415
+ assert_not_nil(c.title)
416
+ assert_not_nil(c.link)
417
+ assert_not_nil(c.description)
418
+ end
419
+
319
420
  end
320
421
 
321
422
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: syndication
5
5
  version: !ruby/object:Gem::Version
6
- version: "0.6"
7
- date: 2006-06-18 00:00:00 -05:00
6
+ version: 0.6.1
7
+ date: 2006-07-17 00:00:00 -05:00
8
8
  summary: A web syndication parser for Atom and RSS with a uniform API
9
9
  require_paths:
10
10
  - lib
@@ -38,6 +38,8 @@ files:
38
38
  - lib/syndication/rss.rb
39
39
  - lib/syndication/syndication.rb
40
40
  - lib/syndication/atom.rb
41
+ - lib/syndication/feedburner.rb
42
+ - test/feedburntest.rb
41
43
  - test/tagsouptest.rb
42
44
  - test/google.rb
43
45
  - test/rsstest.rb
@@ -55,6 +57,7 @@ test_files:
55
57
  - test/rsstest.rb
56
58
  - test/google.rb
57
59
  - test/tagsouptest.rb
60
+ - test/feedburntest.rb
58
61
  rdoc_options: []
59
62
 
60
63
  extra_rdoc_files: