feedparser 1.1.1 → 1.2.0

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/Manifest.txt +36 -7
  3. data/README.md +145 -10
  4. data/Rakefile +1 -1
  5. data/lib/feedparser.rb +3 -0
  6. data/lib/feedparser/author.rb +39 -0
  7. data/lib/feedparser/builder/atom.rb +64 -17
  8. data/lib/feedparser/builder/json.rb +46 -10
  9. data/lib/feedparser/builder/rss.rb +94 -15
  10. data/lib/feedparser/feed.rb +30 -6
  11. data/lib/feedparser/generator.rb +34 -0
  12. data/lib/feedparser/item.rb +31 -6
  13. data/lib/feedparser/tag.rb +23 -0
  14. data/lib/feedparser/version.rb +2 -2
  15. data/test/feeds/books/nostarch.rss +125 -0
  16. data/test/feeds/books/oreilly.feedburner.atom +387 -0
  17. data/test/feeds/books/pragprog.rss +148 -0
  18. data/test/feeds/byparker.json +4 -4
  19. data/test/feeds/daringfireball.atom +8 -1
  20. data/test/feeds/daringfireball.json +28 -0
  21. data/test/feeds/googlegroups.atom +2 -2
  22. data/test/feeds/googlegroups2.atom +1 -1
  23. data/test/feeds/headius.atom +6 -5
  24. data/test/feeds/inessential.json +13 -4
  25. data/test/feeds/jsonfeed.json +8 -3
  26. data/test/feeds/{lambdatheultimate.rss2 → lambdatheultimate.rss} +0 -0
  27. data/test/feeds/{learnenough.atom → learnenough.feedburner.atom} +12 -9
  28. data/test/feeds/news/nytimes-blogs-bits.rss +333 -0
  29. data/test/feeds/news/nytimes-paul-krugman.rss +60 -0
  30. data/test/feeds/news/nytimes-tech.rss +653 -0
  31. data/test/feeds/news/nytimes-thomas-l-friedman.rss +80 -0
  32. data/test/feeds/news/nytimes.rss +607 -0
  33. data/test/feeds/news/washingtonpost-blogs-innovations.rss +183 -0
  34. data/test/feeds/news/washingtonpost-politics.rss +35 -0
  35. data/test/feeds/news/washingtonpost-world.rss +29 -0
  36. data/test/feeds/ongoing.atom +1619 -0
  37. data/test/feeds/osm/blog.openstreetmap.rss +252 -0
  38. data/test/feeds/osm/blogs.openstreetmap.rss +585 -0
  39. data/test/feeds/osm/mapbox.rss +1883 -0
  40. data/test/feeds/{railstutorial.atom → railstutorial.feedburner.atom} +28 -27
  41. data/test/feeds/{rubyflow.rss2 → rubyflow.feedburner.rss} +7 -3
  42. data/test/feeds/{rubymine.rss2 → rubymine.feedburner.rss} +5 -6
  43. data/test/feeds/scripting.rss +881 -0
  44. data/test/feeds/{sitepoint.rss2 → sitepoint.rss} +8 -9
  45. data/test/feeds/spec/atom/author.atom +48 -0
  46. data/test/feeds/spec/atom/authors.atom +70 -0
  47. data/test/feeds/spec/atom/categories.atom +66 -0
  48. data/test/feeds/spec/json/microblog.json +11 -2
  49. data/test/feeds/spec/json/tags.json +33 -0
  50. data/test/feeds/spec/rss/author.rss +41 -0
  51. data/test/feeds/spec/rss/categories.rss +64 -0
  52. data/test/feeds/spec/rss/creator.rss +38 -0
  53. data/test/feeds/{xkcd.rss2 → xkcd.rss} +0 -0
  54. data/test/helper.rb +21 -16
  55. data/test/test_atom.rb +1 -1
  56. data/test/test_atom_live.rb +1 -1
  57. data/test/test_authors.rb +26 -0
  58. data/test/test_books.rb +25 -0
  59. data/test/test_feeds.rb +4 -2
  60. data/test/test_rss.rb +4 -4
  61. data/test/test_tags.rb +25 -0
  62. metadata +39 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b6333596837d069834ffd82fe303bc4d11eea956
4
- data.tar.gz: 8d53dd07e144f4d0c87a1c02373df25826514579
3
+ metadata.gz: 520ebca7dbff20c3347536869aa6dcfd87d68ddc
4
+ data.tar.gz: 5378e9fc3d8038ed61d085999fcb7d1ab3e1f041
5
5
  SHA512:
6
- metadata.gz: 119e6107807ae4c7781379d2e04e255d9906fafef5bbf44a57557a4bfc02fb64f647bce77e9cbad3e7546da5a852775db96ee11e4fb51be7936cf02b03d82463
7
- data.tar.gz: fac5a2f23e61173b65b0d52711651b02b4d5d7585a52eed12416acc96256167468fa92b31b837888e1e1d09cec347ce1554be56c9078958711e2f246aaeec57f
6
+ metadata.gz: 40cc695312a0007da9e569fd05dd35d6621e08367248191eea645c77a93ed5e64c58c0febd9b9d5762177751b3e9c712adbcd52c1ec951e9125c085719f37734
7
+ data.tar.gz: 96fb8f2c92a83447cc5598b667a3a5036d66c93305b3a624a9f6081e4489b43f5bf37b51cc61959f0ad1a621bd6d1c456a514a1c501e7112179f00d6f1c55cfb
@@ -3,13 +3,19 @@ Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
5
  lib/feedparser.rb
6
+ lib/feedparser/author.rb
6
7
  lib/feedparser/builder/atom.rb
7
8
  lib/feedparser/builder/json.rb
8
9
  lib/feedparser/builder/rss.rb
9
10
  lib/feedparser/feed.rb
11
+ lib/feedparser/generator.rb
10
12
  lib/feedparser/item.rb
11
13
  lib/feedparser/parser.rb
14
+ lib/feedparser/tag.rb
12
15
  lib/feedparser/version.rb
16
+ test/feeds/books/nostarch.rss
17
+ test/feeds/books/oreilly.feedburner.atom
18
+ test/feeds/books/pragprog.rss
13
19
  test/feeds/byparker.json
14
20
  test/feeds/daringfireball.atom
15
21
  test/feeds/daringfireball.json
@@ -19,22 +25,45 @@ test/feeds/headius.atom
19
25
  test/feeds/inessential.json
20
26
  test/feeds/intertwingly.atom
21
27
  test/feeds/jsonfeed.json
22
- test/feeds/lambdatheultimate.rss2
23
- test/feeds/learnenough.atom
24
- test/feeds/railstutorial.atom
25
- test/feeds/rubyflow.rss2
26
- test/feeds/rubymine.rss2
28
+ test/feeds/lambdatheultimate.rss
29
+ test/feeds/learnenough.feedburner.atom
30
+ test/feeds/news/nytimes-blogs-bits.rss
31
+ test/feeds/news/nytimes-paul-krugman.rss
32
+ test/feeds/news/nytimes-tech.rss
33
+ test/feeds/news/nytimes-thomas-l-friedman.rss
34
+ test/feeds/news/nytimes.rss
35
+ test/feeds/news/washingtonpost-blogs-innovations.rss
36
+ test/feeds/news/washingtonpost-politics.rss
37
+ test/feeds/news/washingtonpost-world.rss
38
+ test/feeds/ongoing.atom
39
+ test/feeds/osm/blog.openstreetmap.rss
40
+ test/feeds/osm/blogs.openstreetmap.rss
41
+ test/feeds/osm/mapbox.rss
42
+ test/feeds/railstutorial.feedburner.atom
43
+ test/feeds/rubyflow.feedburner.rss
44
+ test/feeds/rubymine.feedburner.rss
27
45
  test/feeds/rubyonrails.atom
28
- test/feeds/sitepoint.rss2
46
+ test/feeds/scripting.rss
47
+ test/feeds/sitepoint.rss
48
+ test/feeds/spec/atom/author.atom
49
+ test/feeds/spec/atom/authors.atom
50
+ test/feeds/spec/atom/categories.atom
29
51
  test/feeds/spec/json/example.json
30
52
  test/feeds/spec/json/microblog.json
53
+ test/feeds/spec/json/tags.json
54
+ test/feeds/spec/rss/author.rss
55
+ test/feeds/spec/rss/categories.rss
56
+ test/feeds/spec/rss/creator.rss
31
57
  test/feeds/xkcd.atom
32
- test/feeds/xkcd.rss2
58
+ test/feeds/xkcd.rss
33
59
  test/helper.rb
34
60
  test/test_atom.rb
35
61
  test/test_atom_live.rb
62
+ test/test_authors.rb
63
+ test/test_books.rb
36
64
  test/test_dates.rb
37
65
  test/test_feeds.rb
38
66
  test/test_json.rb
39
67
  test/test_rss.rb
40
68
  test/test_rss_live.rb
69
+ test/test_tags.rb
data/README.md CHANGED
@@ -11,14 +11,21 @@ feedparser gem - web feed parser and normalizer (Atom, RSS 2.0, JSON, etc.)
11
11
 
12
12
  ## What's News?
13
13
 
14
- May/2017: Added support for reading feeds in the new [JSON Feed](https://jsonfeed.org) format in - surprise, surprise - JSON.
14
+ May/2017: Added support for reading feeds in the new [JSON Feed](https://jsonfeed.org) format in - surprise, surprise - JSON.
15
+
16
+ ## What's a Web Feed?
17
+
18
+ See the [Awesome Feeds](https://github.com/statictimes/awesome-feeds) page ».
19
+
15
20
 
16
21
 
17
22
  ## Usage
18
23
 
24
+
19
25
  ### Structs
20
26
 
21
- Feed • Item
27
+ Feed • Item • Author • Tag • Generator
28
+
22
29
 
23
30
  ![](feed-models.png)
24
31
 
@@ -30,7 +37,7 @@ Note: uses question mark (`?`) for optional elements (otherwise assume required
30
37
 
31
38
  **Title 'n' Summary**
32
39
 
33
- Note: The Feed parser will remove all html tags and attributes from the title (RSS 2.0+Atom),
40
+ Note: The Feed parser will remove all html tags and attributes from the title (RSS 2.0+Atom),
34
41
  description (RSS 2.0) and subtitle (Atom) content and will unescape HTML entities e.g. `&` becomes & and so on - always
35
42
  resulting in plain vanilla text.
36
43
 
@@ -47,7 +54,7 @@ resulting in plain vanilla text.
47
54
  | `feed.updated` | `lastBuildDate`? | RFC-822 format | `updated` | ISO 801 format |
48
55
  | `feed.published` | `pubDate`? | RFC-822 format | - | |
49
56
 
50
- Note: Check - for RSS 2.0 set feed.updated to pubDate or lastBuildDate if only one present? if both present - map as above.
57
+ Note: Check - for RSS 2.0 set feed.updated to pubDate or lastBuildDate if only one present? if both present - map as above.
51
58
 
52
59
 
53
60
  RFC-822 date format e.g. Wed, 14 Jan 2015 19:48:57 +0100
@@ -74,12 +81,14 @@ class Feed
74
81
  end
75
82
  ```
76
83
 
84
+ (Source: [`lib/feedparser/feed.rb`](https://github.com/feedparser/feedparser/blob/master/lib/feedparser/feed.rb))
85
+
77
86
 
78
87
  ### `Item` Struct
79
88
 
80
89
  **Title 'n' Summary**
81
90
 
82
- Note: The Feed parser will remove all html tags and attributes from the title (RSS 2.0+Atom),
91
+ Note: The Feed parser will remove all html tags and attributes from the title (RSS 2.0+Atom),
83
92
  description (RSS 2.0) and summary (Atom) content
84
93
  and will unescape HTML entities e.g. `&` becomes & and so on - always
85
94
  resulting in plain vanilla text.
@@ -98,7 +107,7 @@ Note: The content element will assume html content.
98
107
 
99
108
  | Feed Struct | RSS 2.0 | Notes | Atom | Notes | JSON | Notes |
100
109
  | ------------------ | ----------------- | ----------- | ------------- | ----------- | ----------------- | ----------- |
101
- | `item.title` | `title` | plain text | `title` | plain text | `title`? | plain text |
110
+ | `item.title` | `title` | plain text | `title` | plain text | `title`? | plain text |
102
111
  | `item.summary` | `description` | plain text | `summary`? | plain text | -tbd- | |
103
112
  | `item.content` | `content`? | html | `content`? | html | `content_html (*)`| html |
104
113
 
@@ -129,6 +138,23 @@ class Item
129
138
  end
130
139
  ```
131
140
 
141
+ (Source: [`lib/feedparser/item.rb`](https://github.com/feedparser/feedparser/blob/master/lib/feedparser/item.rb))
142
+
143
+
144
+ ### `Author` Struct
145
+
146
+ (Source: [`lib/feedparser/author.rb`](https://github.com/feedparser/feedparser/blob/master/lib/feedparser/author.rb))
147
+
148
+
149
+ ### `Tag` Struct
150
+
151
+ (Source: [`lib/feedparser/tag.rb`](https://github.com/feedparser/feedparser/blob/master/lib/feedparser/tag.rb))
152
+
153
+ ### `Generator` Struct
154
+
155
+ (Source: [`lib/feedparser/generator.rb`](https://github.com/feedparser/feedparser/blob/master/lib/feedparser/generator.rb))
156
+
157
+
132
158
 
133
159
  ### Read Feed Example
134
160
 
@@ -136,22 +162,131 @@ end
136
162
  require 'open-uri'
137
163
  require 'feedparser'
138
164
 
139
- txt = open( 'http://openfootball.github.io/atom.xml' ).read
165
+ txt = open( 'http://openfootball.github.io/feed.xml' ).read
140
166
 
141
167
  feed = FeedParser::Parser.parse( txt )
142
- pp feed
168
+
169
+ puts feed.title
170
+ # => "football.db - Open Football Data"
171
+
172
+ puts feed.url
173
+ # => "http://openfootball.github.io/"
174
+
175
+ puts feed.items[0].title
176
+ # => "football.db - League Quick Starter Sample - Mauritius Premier League - Create Your Own Repo/League(s) from Scratch"
177
+
178
+ puts feed.items[0].url
179
+ # => "http://openfootball.github.io/2015/08/30/league-quick-starter.html"
180
+
181
+ puts feed.items[0].updated
182
+ # => Sun, 30 Aug 2015 00:00:00 +0000
183
+
184
+ puts feed.items[0].content
185
+ # => "Added a new quick starter sample using the Mauritius Premier League to get you started..."
186
+
187
+ ...
143
188
  ```
144
189
 
145
190
  or reading a feed in the new [JSON Feed](https://jsonfeed.org) format in - surprise, surprise - JSON;
146
191
  note: nothing changes :-)
147
192
 
148
193
  ```
149
- txt = open( 'https://jsonfeed.org/feed.json' ).read
194
+ txt = open( 'http://openfootball.github.io/feed.json' ).read
150
195
 
151
196
  feed = FeedParser::Parser.parse( txt )
152
- pp feed
197
+
198
+ puts feed.title
199
+ # => "football.db - Open Football Data"
200
+
201
+ puts feed.url
202
+ # => "http://openfootball.github.io/"
203
+
204
+ puts feed.items[0].title
205
+ # => "football.db - League Quick Starter Sample - Mauritius Premier League - Create Your Own Repo/League(s) from Scratch"
206
+
207
+ puts feed.items[0].url
208
+ # => "http://openfootball.github.io/2015/08/30/league-quick-starter.html"
209
+
210
+ puts feed.items[0].updated
211
+ # => Sun, 30 Aug 2015 00:00:00 +0000
212
+
213
+ puts feed.items[0].content_text
214
+ # => "Added a new quick starter sample using the Mauritius Premier League to get you started..."
215
+
216
+ ...
153
217
  ```
154
218
 
219
+ ## Samples
220
+
221
+ ### Feed Reader
222
+
223
+ _Planet Feed Reader in 20 Lines of Ruby_
224
+
225
+ `planet.rb`:
226
+
227
+ ``` ruby
228
+ require 'open-uri'
229
+ require 'feedparser'
230
+ require 'erb'
231
+
232
+ # step 1) read a list of web feeds
233
+
234
+ FEED_URLS = [
235
+ 'http://vienna-rb.at/atom.xml',
236
+ 'http://weblog.rubyonrails.org/feed/atom.xml',
237
+ 'http://www.ruby-lang.org/en/feeds/news.rss',
238
+ 'http://openfootball.github.io/feed.json',
239
+ ]
240
+
241
+ items = []
242
+
243
+ FEED_URLS.each do |url|
244
+ feed = FeedParser::Parser.parse( open( url ).read )
245
+ items += feed.items
246
+ end
247
+
248
+ # step 2) mix up all postings in a new page
249
+
250
+ FEED_ITEM_TEMPLATE = <<EOS
251
+ <% items.each do |item| %>
252
+ <div class="item">
253
+ <h2><a href="<%= item.url %>"><%= item.title %></a></h2>
254
+ <div><%= item.content %></div>
255
+ </div>
256
+ <% end %>
257
+ EOS
258
+
259
+ puts ERB.new( FEED_ITEM_TEMPLATE ).result
260
+ ```
261
+
262
+ Run the script:
263
+
264
+ ```
265
+ $ ruby ./planet.rb
266
+ ```
267
+
268
+ Prints:
269
+
270
+ ```
271
+ <div class="item">
272
+ <h2><a href="http://vienna-rb.at/blog/2017/11/06/picks/">Picks / what the vienna.rb team thinks is worth sharing this week</a></h2>
273
+ <div>
274
+ <h3>6/11 Picks!!</h3>
275
+ <p>In a series on this website we'll entertain YOU with our picks...
276
+ ...
277
+ ```
278
+
279
+ ## Real World Usage
280
+
281
+ See the Planet Pluto feed reader family:
282
+
283
+ - [Planet Pluto](https://github.com/feedreader) - static planet website generator
284
+ - [Planet Pluto Live](https://github.com/plutolive) - dynamic (live) planet web apps (using Sinatra, Rails, etc.)
285
+
286
+
287
+ Add your tools, scripts, apps here! Let us know.
288
+
289
+
155
290
 
156
291
  ## Install
157
292
 
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ Hoe.spec 'feedparser' do
8
8
  self.summary = 'feedparser - web feed parser and normalizer (RSS 2.0, Atom, JSON, etc.)'
9
9
  self.description = summary
10
10
 
11
- self.urls = ['https://github.com/feedreader/feedparser']
11
+ self.urls = ['https://github.com/feedparser/feedparser']
12
12
 
13
13
  self.author = 'Gerald Bauer'
14
14
  self.email = 'wwwmake@googlegroups.com'
@@ -26,6 +26,9 @@ require 'feedparser/builder/json'
26
26
 
27
27
  require 'feedparser/feed'
28
28
  require 'feedparser/item'
29
+ require 'feedparser/author'
30
+ require 'feedparser/tag'
31
+ require 'feedparser/generator'
29
32
  require 'feedparser/parser'
30
33
 
31
34
 
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+
3
+ module FeedParser
4
+
5
+ class Author
6
+
7
+ attr_accessor :name
8
+ attr_accessor :url
9
+ ## note: uri is an alias for url
10
+ alias :uri :url ## add atom alias for uri - why? why not?
11
+ alias :uri= :url=
12
+
13
+ def email?() @email.nil? == false; end
14
+ attr_accessor :email
15
+
16
+ def avatar?() @avatar.nil? == false; end
17
+ attr_accessor :avatar # todo/check: use avatar_url ?? used by json feed -check if always a url
18
+
19
+
20
+ ## todo: add role - why? why not?
21
+ ## e.g. add contributor (atom)
22
+ ## or managingEditor (rss) or webMaster (rss) - why? why not??
23
+
24
+ attr_accessor :text # note: holds "unparsed" text (content) line form dc:creator or rss:author
25
+
26
+
27
+ def to_s
28
+ ## note: to_s - allows to use just author in templates
29
+ ## will by default return name if present or as fallback "unparsed" text line
30
+ if @name ## not blank
31
+ @name
32
+ else
33
+ @text
34
+ end
35
+ end
36
+
37
+ end # class Author
38
+
39
+ end # module FeedParser
@@ -22,7 +22,7 @@ class AtomFeedBuilder
22
22
 
23
23
 
24
24
 
25
- def build_feed( atom_feed )
25
+ def build_feed( atom_feed ) ## fix/todo: rename atom_feed to atom or wire or xml or in ???
26
26
  feed = Feed.new
27
27
  feed.format = 'atom'
28
28
 
@@ -36,9 +36,8 @@ class AtomFeedBuilder
36
36
  atom_feed.links.each_with_index do |link,i|
37
37
  logger.debug " atom | feed.link[#{i+1}] rel=>#{link.rel}< : #{link.rel.class.name} type=>#{link.type}< href=>#{link.href}<"
38
38
 
39
- if link.rel == 'self'
39
+ if feed.feed_url.nil? && link.rel == 'self'
40
40
  feed.feed_url = link.href
41
- break
42
41
  end
43
42
  end
44
43
 
@@ -74,18 +73,19 @@ class AtomFeedBuilder
74
73
  end
75
74
 
76
75
 
77
- if atom_feed.updated
78
- feed.updated = handle_date( atom_feed.updated, 'feed.updated' )
76
+ if atom_feed.updated && atom_feed.updated.content ## note: content might be nil if <updated></updated> empty
77
+ feed.updated_local = handle_date( atom_feed.updated, 'feed.updated' )
78
+ feed.updated = feed.updated_local.utc
79
79
  end
80
80
 
81
81
  if atom_feed.generator
82
82
  ## Note: remove (strip) leading and trailing spaces and newlines
83
- feed.generator = atom_feed.generator.content.strip
83
+ feed.generator.name = atom_feed.generator.content.strip
84
84
  logger.debug " atom | feed.generator.content >#{atom_feed.generator.content}< : #{atom_feed.generator.content.class.name}"
85
85
 
86
86
  # pp atom_feed.generator
87
- feed.generator_version = atom_feed.generator.version
88
- feed.generator_uri = atom_feed.generator.uri
87
+ feed.generator.version = atom_feed.generator.version
88
+ feed.generator.url = atom_feed.generator.uri
89
89
  logger.debug " atom | feed.generator.version >#{atom_feed.generator.version}< : #{atom_feed.generator.version.class.name}"
90
90
  logger.debug " atom | feed.generator.uri >#{atom_feed.generator.uri}< : #{atom_feed.generator.uri.class.name}"
91
91
  end
@@ -95,17 +95,52 @@ class AtomFeedBuilder
95
95
  end
96
96
 
97
97
 
98
- items = []
98
+ ## check for authors
99
+ atom_feed.authors.each do |atom_author|
100
+ feed.authors << build_author( atom_author )
101
+ end
102
+
103
+ ## check for categories/tags
104
+ atom_feed.categories.each do |atom_cat|
105
+ feed.tags << build_tag( atom_cat )
106
+ end
107
+
108
+
99
109
  atom_feed.items.each do |atom_item|
100
- items << build_feed_item( atom_item )
110
+ feed.items << build_item( atom_item )
101
111
  end
102
- feed.items = items
103
112
 
104
113
  feed # return new feed
105
114
  end # method build_feed_from_atom
106
115
 
107
116
 
108
- def build_feed_item( atom_item )
117
+ def build_author( atom_author )
118
+ ## pp atom_author
119
+ author = Author.new
120
+
121
+ ## note: always strip leading n trailing spaces (from content)
122
+ author.name = atom_author.name.content.strip if atom_author.name
123
+ author.url = atom_author.uri.content.strip if atom_author.uri
124
+ author.email = atom_author.email.content.strip if atom_author.email
125
+
126
+ author
127
+ end # build_author
128
+
129
+
130
+ def build_tag( atom_cat )
131
+ ## pp atom_cat
132
+ tag = Tag.new
133
+
134
+ ## note: always strip leading n trailing spaces
135
+ ## and add if preset (not blank/empty e.g. not nil or "")
136
+ tag.name = atom_cat.term.strip if atom_cat.term && !atom_cat.term.empty?
137
+ tag.scheme = atom_cat.scheme.strip if atom_cat.scheme && !atom_cat.scheme.empty?
138
+
139
+ tag
140
+ end # build_tag
141
+
142
+
143
+ def build_item( atom_item )
109
144
  item = Item.new # Item.new
110
145
 
111
146
  item.title = handle_content( atom_item.title, 'item.title' )
@@ -136,12 +171,14 @@ class AtomFeedBuilder
136
171
  end
137
172
 
138
173
 
139
- if atom_item.updated
140
- item.updated = handle_date( atom_item.updated, 'item.updated' )
174
+ if atom_item.updated && atom_item.updated.content
175
+ item.updated_local = handle_date( atom_item.updated, 'item.updated' )
176
+ item.updated = item.updated_local.utc
141
177
  end
142
178
 
143
- if atom_item.published
144
- item.published = handle_date( atom_item.published, 'item.published' )
179
+ if atom_item.published && atom_item.published.content
180
+ item.published_local = handle_date( atom_item.published, 'item.published' )
181
+ item.published = item.published_local.utc
145
182
  end
146
183
 
147
184
 
@@ -156,8 +193,18 @@ class AtomFeedBuilder
156
193
  item.summary = handle_content( atom_item.summary, 'item.summary' )
157
194
  end
158
195
 
196
+ ## check for authors
197
+ atom_item.authors.each do |atom_author|
198
+ item.authors << build_author( atom_author )
199
+ end
200
+
201
+ ## check for categories/tags
202
+ atom_item.categories.each do |atom_cat|
203
+ item.tags << build_tag( atom_cat )
204
+ end
205
+
159
206
  item
160
- end # method build_feed_item
207
+ end # method build_item
161
208
 
162
209
 
163
210