syndication 0.6 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: