rss 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +88 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/lib/rss.rb +92 -0
  11. data/lib/rss/0.9.rb +462 -0
  12. data/lib/rss/1.0.rb +485 -0
  13. data/lib/rss/2.0.rb +143 -0
  14. data/lib/rss/atom.rb +1025 -0
  15. data/lib/rss/content.rb +34 -0
  16. data/lib/rss/content/1.0.rb +10 -0
  17. data/lib/rss/content/2.0.rb +12 -0
  18. data/lib/rss/converter.rb +171 -0
  19. data/lib/rss/dublincore.rb +164 -0
  20. data/lib/rss/dublincore/1.0.rb +13 -0
  21. data/lib/rss/dublincore/2.0.rb +13 -0
  22. data/lib/rss/dublincore/atom.rb +17 -0
  23. data/lib/rss/image.rb +198 -0
  24. data/lib/rss/itunes.rb +413 -0
  25. data/lib/rss/maker.rb +79 -0
  26. data/lib/rss/maker/0.9.rb +509 -0
  27. data/lib/rss/maker/1.0.rb +436 -0
  28. data/lib/rss/maker/2.0.rb +224 -0
  29. data/lib/rss/maker/atom.rb +173 -0
  30. data/lib/rss/maker/base.rb +945 -0
  31. data/lib/rss/maker/content.rb +22 -0
  32. data/lib/rss/maker/dublincore.rb +122 -0
  33. data/lib/rss/maker/entry.rb +164 -0
  34. data/lib/rss/maker/feed.rb +427 -0
  35. data/lib/rss/maker/image.rb +112 -0
  36. data/lib/rss/maker/itunes.rb +243 -0
  37. data/lib/rss/maker/slash.rb +34 -0
  38. data/lib/rss/maker/syndication.rb +19 -0
  39. data/lib/rss/maker/taxonomy.rb +119 -0
  40. data/lib/rss/maker/trackback.rb +62 -0
  41. data/lib/rss/parser.rb +589 -0
  42. data/lib/rss/rexmlparser.rb +50 -0
  43. data/lib/rss/rss.rb +1346 -0
  44. data/lib/rss/slash.rb +52 -0
  45. data/lib/rss/syndication.rb +69 -0
  46. data/lib/rss/taxonomy.rb +148 -0
  47. data/lib/rss/trackback.rb +291 -0
  48. data/lib/rss/utils.rb +200 -0
  49. data/lib/rss/xml-stylesheet.rb +106 -0
  50. data/lib/rss/xml.rb +72 -0
  51. data/lib/rss/xmlparser.rb +95 -0
  52. data/lib/rss/xmlscanner.rb +122 -0
  53. data/rss.gemspec +38 -0
  54. metadata +138 -0
@@ -0,0 +1,413 @@
1
+ # frozen_string_literal: false
2
+ require 'rss/2.0'
3
+
4
+ module RSS
5
+ # The prefix for the iTunes XML namespace.
6
+ ITUNES_PREFIX = 'itunes'
7
+ # The URI of the iTunes specification.
8
+ ITUNES_URI = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
9
+
10
+ Rss.install_ns(ITUNES_PREFIX, ITUNES_URI)
11
+
12
+ module ITunesModelUtils
13
+ include Utils
14
+
15
+ def def_class_accessor(klass, name, type, *args)
16
+ normalized_name = name.gsub(/-/, "_")
17
+ full_name = "#{ITUNES_PREFIX}_#{normalized_name}"
18
+ klass_name = "ITunes#{Utils.to_class_name(normalized_name)}"
19
+
20
+ case type
21
+ when :element, :attribute
22
+ klass::ELEMENTS << full_name
23
+ def_element_class_accessor(klass, name, full_name, klass_name, *args)
24
+ when :elements
25
+ klass::ELEMENTS << full_name
26
+ def_elements_class_accessor(klass, name, full_name, klass_name, *args)
27
+ else
28
+ klass.install_must_call_validator(ITUNES_PREFIX, ITUNES_URI)
29
+ klass.install_text_element(normalized_name, ITUNES_URI, "?",
30
+ full_name, type, name)
31
+ end
32
+ end
33
+
34
+ def def_element_class_accessor(klass, name, full_name, klass_name,
35
+ recommended_attribute_name=nil)
36
+ klass.install_have_child_element(name, ITUNES_PREFIX, "?", full_name)
37
+ end
38
+
39
+ def def_elements_class_accessor(klass, name, full_name, klass_name,
40
+ plural_name, recommended_attribute_name=nil)
41
+ full_plural_name = "#{ITUNES_PREFIX}_#{plural_name}"
42
+ klass.install_have_children_element(name, ITUNES_PREFIX, "*",
43
+ full_name, full_plural_name)
44
+ end
45
+ end
46
+
47
+ module ITunesBaseModel
48
+ extend ITunesModelUtils
49
+
50
+ ELEMENTS = []
51
+
52
+ ELEMENT_INFOS = [["author"],
53
+ ["block", :yes_other],
54
+ ["explicit", :explicit_clean_other],
55
+ ["keywords", :csv],
56
+ ["subtitle"],
57
+ ["summary"]]
58
+ end
59
+
60
+ module ITunesChannelModel
61
+ extend BaseModel
62
+ extend ITunesModelUtils
63
+ include ITunesBaseModel
64
+
65
+ ELEMENTS = []
66
+
67
+ class << self
68
+ def append_features(klass)
69
+ super
70
+
71
+ return if klass.instance_of?(Module)
72
+ ELEMENT_INFOS.each do |name, type, *additional_infos|
73
+ def_class_accessor(klass, name, type, *additional_infos)
74
+ end
75
+ end
76
+ end
77
+
78
+ ELEMENT_INFOS = [
79
+ ["category", :elements, "categories", "text"],
80
+ ["image", :attribute, "href"],
81
+ ["owner", :element],
82
+ ["new-feed-url"],
83
+ ] + ITunesBaseModel::ELEMENT_INFOS
84
+
85
+ class ITunesCategory < Element
86
+ include RSS09
87
+
88
+ @tag_name = "category"
89
+
90
+ class << self
91
+ def required_prefix
92
+ ITUNES_PREFIX
93
+ end
94
+
95
+ def required_uri
96
+ ITUNES_URI
97
+ end
98
+ end
99
+
100
+ [
101
+ ["text", "", true]
102
+ ].each do |name, uri, required|
103
+ install_get_attribute(name, uri, required)
104
+ end
105
+
106
+ ITunesCategory = self
107
+ install_have_children_element("category", ITUNES_URI, "*",
108
+ "#{ITUNES_PREFIX}_category",
109
+ "#{ITUNES_PREFIX}_categories")
110
+
111
+ def initialize(*args)
112
+ if Utils.element_initialize_arguments?(args)
113
+ super
114
+ else
115
+ super()
116
+ self.text = args[0]
117
+ end
118
+ end
119
+
120
+ def full_name
121
+ tag_name_with_prefix(ITUNES_PREFIX)
122
+ end
123
+
124
+ private
125
+ def maker_target(categories)
126
+ if text or !itunes_categories.empty?
127
+ categories.new_category
128
+ else
129
+ nil
130
+ end
131
+ end
132
+
133
+ def setup_maker_attributes(category)
134
+ category.text = text if text
135
+ end
136
+
137
+ def setup_maker_elements(category)
138
+ super(category)
139
+ itunes_categories.each do |sub_category|
140
+ sub_category.setup_maker(category)
141
+ end
142
+ end
143
+ end
144
+
145
+ class ITunesImage < Element
146
+ include RSS09
147
+
148
+ @tag_name = "image"
149
+
150
+ class << self
151
+ def required_prefix
152
+ ITUNES_PREFIX
153
+ end
154
+
155
+ def required_uri
156
+ ITUNES_URI
157
+ end
158
+ end
159
+
160
+ [
161
+ ["href", "", true]
162
+ ].each do |name, uri, required|
163
+ install_get_attribute(name, uri, required)
164
+ end
165
+
166
+ def initialize(*args)
167
+ if Utils.element_initialize_arguments?(args)
168
+ super
169
+ else
170
+ super()
171
+ self.href = args[0]
172
+ end
173
+ end
174
+
175
+ def full_name
176
+ tag_name_with_prefix(ITUNES_PREFIX)
177
+ end
178
+
179
+ private
180
+ def maker_target(target)
181
+ if href
182
+ target.itunes_image {|image| image}
183
+ else
184
+ nil
185
+ end
186
+ end
187
+
188
+ def setup_maker_attributes(image)
189
+ image.href = href
190
+ end
191
+ end
192
+
193
+ class ITunesOwner < Element
194
+ include RSS09
195
+
196
+ @tag_name = "owner"
197
+
198
+ class << self
199
+ def required_prefix
200
+ ITUNES_PREFIX
201
+ end
202
+
203
+ def required_uri
204
+ ITUNES_URI
205
+ end
206
+ end
207
+
208
+ install_must_call_validator(ITUNES_PREFIX, ITUNES_URI)
209
+ [
210
+ ["name"],
211
+ ["email"],
212
+ ].each do |name,|
213
+ ITunesBaseModel::ELEMENT_INFOS << name
214
+ install_text_element(name, ITUNES_URI, nil, "#{ITUNES_PREFIX}_#{name}")
215
+ end
216
+
217
+ def initialize(*args)
218
+ if Utils.element_initialize_arguments?(args)
219
+ super
220
+ else
221
+ super()
222
+ self.itunes_name = args[0]
223
+ self.itunes_email = args[1]
224
+ end
225
+ end
226
+
227
+ def full_name
228
+ tag_name_with_prefix(ITUNES_PREFIX)
229
+ end
230
+
231
+ private
232
+ def maker_target(target)
233
+ target.itunes_owner
234
+ end
235
+
236
+ def setup_maker_element(owner)
237
+ super(owner)
238
+ owner.itunes_name = itunes_name
239
+ owner.itunes_email = itunes_email
240
+ end
241
+ end
242
+ end
243
+
244
+ module ITunesItemModel
245
+ extend BaseModel
246
+ extend ITunesModelUtils
247
+ include ITunesBaseModel
248
+
249
+ class << self
250
+ def append_features(klass)
251
+ super
252
+
253
+ return if klass.instance_of?(Module)
254
+ ELEMENT_INFOS.each do |name, type|
255
+ def_class_accessor(klass, name, type)
256
+ end
257
+ end
258
+ end
259
+
260
+ ELEMENT_INFOS = ITunesBaseModel::ELEMENT_INFOS +
261
+ [["duration", :element, "content"]]
262
+
263
+ class ITunesDuration < Element
264
+ include RSS09
265
+
266
+ @tag_name = "duration"
267
+
268
+ class << self
269
+ def required_prefix
270
+ ITUNES_PREFIX
271
+ end
272
+
273
+ def required_uri
274
+ ITUNES_URI
275
+ end
276
+
277
+ def parse(duration, do_validate=true)
278
+ if do_validate and /\A(?:
279
+ \d?\d:[0-5]\d:[0-5]\d|
280
+ [0-5]?\d:[0-5]\d
281
+ )\z/x !~ duration
282
+ raise ArgumentError,
283
+ "must be one of HH:MM:SS, H:MM:SS, MM::SS, M:SS: " +
284
+ duration.inspect
285
+ end
286
+
287
+ components = duration.split(':')
288
+ components[3..-1] = nil if components.size > 3
289
+
290
+ components.unshift("00") until components.size == 3
291
+
292
+ components.collect do |component|
293
+ component.to_i
294
+ end
295
+ end
296
+
297
+ def construct(hour, minute, second)
298
+ components = [minute, second]
299
+ if components.include?(nil)
300
+ nil
301
+ else
302
+ components.unshift(hour) if hour and hour > 0
303
+ components.collect do |component|
304
+ "%02d" % component
305
+ end.join(":")
306
+ end
307
+ end
308
+ end
309
+
310
+ content_setup
311
+ alias_method(:value, :content)
312
+ remove_method(:content=)
313
+
314
+ attr_reader :hour, :minute, :second
315
+ def initialize(*args)
316
+ if Utils.element_initialize_arguments?(args)
317
+ super
318
+ else
319
+ super()
320
+ args = args[0] if args.size == 1 and args[0].is_a?(Array)
321
+ if args.size == 1
322
+ self.content = args[0]
323
+ elsif args.size > 3
324
+ raise ArgumentError,
325
+ "must be (do_validate, params), (content), " +
326
+ "(minute, second), ([minute, second]), " +
327
+ "(hour, minute, second) or ([hour, minute, second]): " +
328
+ args.inspect
329
+ else
330
+ @second, @minute, @hour = args.reverse
331
+ update_content
332
+ end
333
+ end
334
+ end
335
+
336
+ def content=(value)
337
+ if value.nil?
338
+ @content = nil
339
+ elsif value.is_a?(self.class)
340
+ self.content = value.content
341
+ else
342
+ begin
343
+ @hour, @minute, @second = self.class.parse(value, @do_validate)
344
+ rescue ArgumentError
345
+ raise NotAvailableValueError.new(tag_name, value)
346
+ end
347
+ @content = value
348
+ end
349
+ end
350
+ alias_method(:value=, :content=)
351
+
352
+ def hour=(hour)
353
+ @hour = @do_validate ? Integer(hour) : hour.to_i
354
+ update_content
355
+ hour
356
+ end
357
+
358
+ def minute=(minute)
359
+ @minute = @do_validate ? Integer(minute) : minute.to_i
360
+ update_content
361
+ minute
362
+ end
363
+
364
+ def second=(second)
365
+ @second = @do_validate ? Integer(second) : second.to_i
366
+ update_content
367
+ second
368
+ end
369
+
370
+ def full_name
371
+ tag_name_with_prefix(ITUNES_PREFIX)
372
+ end
373
+
374
+ private
375
+ def update_content
376
+ @content = self.class.construct(hour, minute, second)
377
+ end
378
+
379
+ def maker_target(target)
380
+ if @content
381
+ target.itunes_duration {|duration| duration}
382
+ else
383
+ nil
384
+ end
385
+ end
386
+
387
+ def setup_maker_element(duration)
388
+ super(duration)
389
+ duration.content = @content
390
+ end
391
+ end
392
+ end
393
+
394
+ class Rss
395
+ class Channel
396
+ include ITunesChannelModel
397
+ class Item; include ITunesItemModel; end
398
+ end
399
+ end
400
+
401
+ element_infos =
402
+ ITunesChannelModel::ELEMENT_INFOS + ITunesItemModel::ELEMENT_INFOS
403
+ element_infos.each do |name, type|
404
+ case type
405
+ when :element, :elements, :attribute
406
+ class_name = Utils.to_class_name(name)
407
+ BaseListener.install_class_name(ITUNES_URI, name, "ITunes#{class_name}")
408
+ else
409
+ accessor_base = "#{ITUNES_PREFIX}_#{name.gsub(/-/, '_')}"
410
+ BaseListener.install_get_text_element(ITUNES_URI, name, accessor_base)
411
+ end
412
+ end
413
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: false
2
+ require_relative "rss"
3
+
4
+ module RSS
5
+ ##
6
+ #
7
+ # Provides a set of builders for various RSS objects
8
+ #
9
+ # * Feeds
10
+ # * RSS 0.91
11
+ # * RSS 1.0
12
+ # * RSS 2.0
13
+ # * Atom 1.0
14
+ #
15
+ # * Elements
16
+ # * Atom::Entry
17
+
18
+ module Maker
19
+
20
+ # Collection of supported makers
21
+ MAKERS = {}
22
+
23
+ class << self
24
+ # Builder for an RSS object
25
+ # Creates an object of the type passed in +args+
26
+ #
27
+ # Executes the +block+ to populate elements of the created RSS object
28
+ def make(version, &block)
29
+ self[version].make(&block)
30
+ end
31
+
32
+ # Returns the maker for the +version+
33
+ def [](version)
34
+ maker_info = maker(version)
35
+ raise UnsupportedMakerVersionError.new(version) if maker_info.nil?
36
+ maker_info[:maker]
37
+ end
38
+
39
+ # Adds a maker to the set of supported makers
40
+ def add_maker(version, normalized_version, maker)
41
+ MAKERS[version] = {:maker => maker, :version => normalized_version}
42
+ end
43
+
44
+ # Returns collection of supported maker versions
45
+ def versions
46
+ MAKERS.keys.uniq.sort
47
+ end
48
+
49
+ # Returns collection of supported makers
50
+ def makers
51
+ MAKERS.values.collect { |info| info[:maker] }.uniq
52
+ end
53
+
54
+ # Returns true if the version is supported
55
+ def supported?(version)
56
+ versions.include?(version)
57
+ end
58
+
59
+ private
60
+ # Can I remove this method?
61
+ def maker(version)
62
+ MAKERS[version]
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ require_relative "maker/1.0"
69
+ require_relative "maker/2.0"
70
+ require_relative "maker/feed"
71
+ require_relative "maker/entry"
72
+ require_relative "maker/content"
73
+ require_relative "maker/dublincore"
74
+ require_relative "maker/slash"
75
+ require_relative "maker/syndication"
76
+ require_relative "maker/taxonomy"
77
+ require_relative "maker/trackback"
78
+ require_relative "maker/image"
79
+ require_relative "maker/itunes"