feedparser 1.1.1 → 1.2.0

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