rss 0.2.7

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 (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"