rubysl-rss 1.0.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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/README.md +29 -0
  7. data/Rakefile +1 -0
  8. data/lib/rss.rb +1 -0
  9. data/lib/rss/0.9.rb +428 -0
  10. data/lib/rss/1.0.rb +452 -0
  11. data/lib/rss/2.0.rb +111 -0
  12. data/lib/rss/atom.rb +749 -0
  13. data/lib/rss/content.rb +31 -0
  14. data/lib/rss/content/1.0.rb +10 -0
  15. data/lib/rss/content/2.0.rb +12 -0
  16. data/lib/rss/converter.rb +162 -0
  17. data/lib/rss/dublincore.rb +161 -0
  18. data/lib/rss/dublincore/1.0.rb +13 -0
  19. data/lib/rss/dublincore/2.0.rb +13 -0
  20. data/lib/rss/dublincore/atom.rb +17 -0
  21. data/lib/rss/image.rb +193 -0
  22. data/lib/rss/itunes.rb +410 -0
  23. data/lib/rss/maker.rb +44 -0
  24. data/lib/rss/maker/0.9.rb +467 -0
  25. data/lib/rss/maker/1.0.rb +434 -0
  26. data/lib/rss/maker/2.0.rb +223 -0
  27. data/lib/rss/maker/atom.rb +172 -0
  28. data/lib/rss/maker/base.rb +868 -0
  29. data/lib/rss/maker/content.rb +21 -0
  30. data/lib/rss/maker/dublincore.rb +124 -0
  31. data/lib/rss/maker/entry.rb +163 -0
  32. data/lib/rss/maker/feed.rb +429 -0
  33. data/lib/rss/maker/image.rb +111 -0
  34. data/lib/rss/maker/itunes.rb +242 -0
  35. data/lib/rss/maker/slash.rb +33 -0
  36. data/lib/rss/maker/syndication.rb +18 -0
  37. data/lib/rss/maker/taxonomy.rb +118 -0
  38. data/lib/rss/maker/trackback.rb +61 -0
  39. data/lib/rss/parser.rb +541 -0
  40. data/lib/rss/rexmlparser.rb +54 -0
  41. data/lib/rss/rss.rb +1312 -0
  42. data/lib/rss/slash.rb +49 -0
  43. data/lib/rss/syndication.rb +67 -0
  44. data/lib/rss/taxonomy.rb +145 -0
  45. data/lib/rss/trackback.rb +288 -0
  46. data/lib/rss/utils.rb +111 -0
  47. data/lib/rss/xml-stylesheet.rb +105 -0
  48. data/lib/rss/xml.rb +71 -0
  49. data/lib/rss/xmlparser.rb +93 -0
  50. data/lib/rss/xmlscanner.rb +121 -0
  51. data/lib/rubysl/rss.rb +2 -0
  52. data/lib/rubysl/rss/rss.rb +19 -0
  53. data/lib/rubysl/rss/version.rb +5 -0
  54. data/rubysl-rss.gemspec +23 -0
  55. metadata +153 -0
@@ -0,0 +1,21 @@
1
+ require 'rss/content'
2
+ require 'rss/maker/1.0'
3
+ require 'rss/maker/2.0'
4
+
5
+ module RSS
6
+ module Maker
7
+ module ContentModel
8
+ def self.append_features(klass)
9
+ super
10
+
11
+ ::RSS::ContentModel::ELEMENTS.each do |name|
12
+ klass.def_other_element(name)
13
+ end
14
+ end
15
+ end
16
+
17
+ class ItemsBase
18
+ class ItemBase; include ContentModel; end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,124 @@
1
+ require 'rss/dublincore'
2
+ require 'rss/maker/1.0'
3
+
4
+ module RSS
5
+ module Maker
6
+ module DublinCoreModel
7
+ def self.append_features(klass)
8
+ super
9
+
10
+ ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
11
+ plural_name ||= "#{name}s"
12
+ full_name = "#{RSS::DC_PREFIX}_#{name}"
13
+ full_plural_name = "#{RSS::DC_PREFIX}_#{plural_name}"
14
+ klass_name = Utils.to_class_name(name)
15
+ plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
16
+ full_plural_klass_name = "self.class::#{plural_klass_name}"
17
+ full_klass_name = "#{full_plural_klass_name}::#{klass_name}"
18
+ klass.def_classed_elements(full_name, "value", plural_klass_name,
19
+ full_plural_name, name)
20
+ klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
21
+ def new_#{full_name}(value=nil)
22
+ _#{full_name} = #{full_plural_name}.new_#{name}
23
+ _#{full_name}.value = value
24
+ if block_given?
25
+ yield _#{full_name}
26
+ else
27
+ _#{full_name}
28
+ end
29
+ end
30
+ EOC
31
+ end
32
+
33
+ klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
34
+ # For backward compatibility
35
+ alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list
36
+ EOC
37
+ end
38
+
39
+ ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
40
+ plural_name ||= "#{name}s"
41
+ full_name ||= "#{DC_PREFIX}_#{name}"
42
+ full_plural_name ||= "#{DC_PREFIX}_#{plural_name}"
43
+ klass_name = Utils.to_class_name(name)
44
+ full_klass_name = "DublinCore#{klass_name}"
45
+ plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
46
+ module_eval(<<-EOC, __FILE__, __LINE__ + 1)
47
+ class #{plural_klass_name}Base < Base
48
+ def_array_element(#{name.dump}, #{full_plural_name.dump},
49
+ #{full_klass_name.dump})
50
+
51
+ class #{full_klass_name}Base < Base
52
+ attr_accessor :value
53
+ add_need_initialize_variable("value")
54
+ alias_method(:content, :value)
55
+ alias_method(:content=, :value=)
56
+
57
+ def have_required_values?
58
+ @value
59
+ end
60
+
61
+ def to_feed(feed, current)
62
+ if value and current.respond_to?(:#{full_name})
63
+ new_item = current.class::#{full_klass_name}.new(value)
64
+ current.#{full_plural_name} << new_item
65
+ end
66
+ end
67
+ end
68
+ #{klass_name}Base = #{full_klass_name}Base
69
+ end
70
+ EOC
71
+ end
72
+
73
+ def self.install_dublin_core(klass)
74
+ ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
75
+ plural_name ||= "#{name}s"
76
+ klass_name = Utils.to_class_name(name)
77
+ full_klass_name = "DublinCore#{klass_name}"
78
+ plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
79
+ klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
80
+ class #{plural_klass_name} < #{plural_klass_name}Base
81
+ class #{full_klass_name} < #{full_klass_name}Base
82
+ end
83
+ #{klass_name} = #{full_klass_name}
84
+ end
85
+ EOC
86
+ end
87
+ end
88
+ end
89
+
90
+ class ChannelBase
91
+ include DublinCoreModel
92
+ end
93
+
94
+ class ImageBase; include DublinCoreModel; end
95
+ class ItemsBase
96
+ class ItemBase
97
+ include DublinCoreModel
98
+ end
99
+ end
100
+ class TextinputBase; include DublinCoreModel; end
101
+
102
+ makers.each do |maker|
103
+ maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
104
+ class Channel
105
+ DublinCoreModel.install_dublin_core(self)
106
+ end
107
+
108
+ class Image
109
+ DublinCoreModel.install_dublin_core(self)
110
+ end
111
+
112
+ class Items
113
+ class Item
114
+ DublinCoreModel.install_dublin_core(self)
115
+ end
116
+ end
117
+
118
+ class Textinput
119
+ DublinCoreModel.install_dublin_core(self)
120
+ end
121
+ EOC
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,163 @@
1
+ require "rss/maker/atom"
2
+ require "rss/maker/feed"
3
+
4
+ module RSS
5
+ module Maker
6
+ module Atom
7
+ class Entry < RSSBase
8
+ def initialize(feed_version="1.0")
9
+ super
10
+ @feed_type = "atom"
11
+ @feed_subtype = "entry"
12
+ end
13
+
14
+ private
15
+ def make_feed
16
+ ::RSS::Atom::Entry.new(@version, @encoding, @standalone)
17
+ end
18
+
19
+ def setup_elements(entry)
20
+ setup_items(entry)
21
+ end
22
+
23
+ class Channel < ChannelBase
24
+ class SkipDays < SkipDaysBase
25
+ class Day < DayBase
26
+ end
27
+ end
28
+
29
+ class SkipHours < SkipHoursBase
30
+ class Hour < HourBase
31
+ end
32
+ end
33
+
34
+ class Cloud < CloudBase
35
+ end
36
+
37
+ Categories = Feed::Channel::Categories
38
+ Links = Feed::Channel::Links
39
+ Authors = Feed::Channel::Authors
40
+ Contributors = Feed::Channel::Contributors
41
+
42
+ class Generator < GeneratorBase
43
+ include AtomGenerator
44
+
45
+ def self.not_set_name
46
+ "maker.channel.generator"
47
+ end
48
+ end
49
+
50
+ Copyright = Feed::Channel::Copyright
51
+
52
+ class Description < DescriptionBase
53
+ end
54
+
55
+ Title = Feed::Channel::Title
56
+ end
57
+
58
+ class Image < ImageBase
59
+ end
60
+
61
+ class Items < ItemsBase
62
+ def to_feed(entry)
63
+ (normalize.first || Item.new(@maker)).to_feed(entry)
64
+ end
65
+
66
+ class Item < ItemBase
67
+ def to_feed(entry)
68
+ set_default_values do
69
+ setup_values(entry)
70
+ entry.dc_dates.clear
71
+ setup_other_elements(entry)
72
+ unless have_required_values?
73
+ raise NotSetError.new("maker.item", not_set_required_variables)
74
+ end
75
+ end
76
+ end
77
+
78
+ private
79
+ def required_variable_names
80
+ %w(id updated)
81
+ end
82
+
83
+ def variables
84
+ super + ["updated"]
85
+ end
86
+
87
+ def variable_is_set?
88
+ super or !authors.empty?
89
+ end
90
+
91
+ def not_set_required_variables
92
+ set_default_values do
93
+ vars = super
94
+ if authors.all? {|author| !author.have_required_values?}
95
+ vars << "author"
96
+ end
97
+ vars << "title" unless title {|t| t.have_required_values?}
98
+ vars
99
+ end
100
+ end
101
+
102
+ def _set_default_values(&block)
103
+ keep = {
104
+ :authors => authors.to_a.dup,
105
+ :contributors => contributors.to_a.dup,
106
+ :categories => categories.to_a.dup,
107
+ :id => id,
108
+ :links => links.to_a.dup,
109
+ :rights => @rights,
110
+ :title => @title,
111
+ :updated => updated,
112
+ }
113
+ authors.replace(@maker.channel.authors) if keep[:authors].empty?
114
+ if keep[:contributors].empty?
115
+ contributors.replace(@maker.channel.contributors)
116
+ end
117
+ if keep[:categories].empty?
118
+ categories.replace(@maker.channel.categories)
119
+ end
120
+ self.id ||= link || @maker.channel.id
121
+ links.replace(@maker.channel.links) if keep[:links].empty?
122
+ unless keep[:rights].variable_is_set?
123
+ @maker.channel.rights {|r| @rights = r}
124
+ end
125
+ unless keep[:title].variable_is_set?
126
+ @maker.channel.title {|t| @title = t}
127
+ end
128
+ self.updated ||= @maker.channel.updated
129
+ super(&block)
130
+ ensure
131
+ authors.replace(keep[:authors])
132
+ contributors.replace(keep[:contributors])
133
+ categories.replace(keep[:categories])
134
+ links.replace(keep[:links])
135
+ self.id = keep[:id]
136
+ @rights = keep[:rights]
137
+ @title = keep[:title]
138
+ self.updated = keep[:prev_updated]
139
+ end
140
+
141
+ Guid = Feed::Items::Item::Guid
142
+ Enclosure = Feed::Items::Item::Enclosure
143
+ Source = Feed::Items::Item::Source
144
+ Categories = Feed::Items::Item::Categories
145
+ Authors = Feed::Items::Item::Authors
146
+ Contributors = Feed::Items::Item::Contributors
147
+ Links = Feed::Items::Item::Links
148
+ Rights = Feed::Items::Item::Rights
149
+ Description = Feed::Items::Item::Description
150
+ Title = Feed::Items::Item::Title
151
+ Content = Feed::Items::Item::Content
152
+ end
153
+ end
154
+
155
+ class Textinput < TextinputBase
156
+ end
157
+ end
158
+ end
159
+
160
+ add_maker("atom:entry", "1.0", Atom::Entry)
161
+ add_maker("atom1.0:entry", "1.0", Atom::Entry)
162
+ end
163
+ end
@@ -0,0 +1,429 @@
1
+ require "rss/maker/atom"
2
+
3
+ module RSS
4
+ module Maker
5
+ module Atom
6
+ class Feed < RSSBase
7
+ def initialize(feed_version="1.0")
8
+ super
9
+ @feed_type = "atom"
10
+ @feed_subtype = "feed"
11
+ end
12
+
13
+ private
14
+ def make_feed
15
+ ::RSS::Atom::Feed.new(@version, @encoding, @standalone)
16
+ end
17
+
18
+ def setup_elements(feed)
19
+ setup_channel(feed)
20
+ setup_image(feed)
21
+ setup_items(feed)
22
+ end
23
+
24
+ class Channel < ChannelBase
25
+ def to_feed(feed)
26
+ set_default_values do
27
+ setup_values(feed)
28
+ feed.dc_dates.clear
29
+ setup_other_elements(feed)
30
+ if image_favicon.about
31
+ icon = feed.class::Icon.new
32
+ icon.content = image_favicon.about
33
+ feed.icon = icon
34
+ end
35
+ unless have_required_values?
36
+ raise NotSetError.new("maker.channel",
37
+ not_set_required_variables)
38
+ end
39
+ end
40
+ end
41
+
42
+ def have_required_values?
43
+ super and
44
+ (!authors.empty? or
45
+ @maker.items.any? {|item| !item.authors.empty?})
46
+ end
47
+
48
+ private
49
+ def required_variable_names
50
+ %w(id updated)
51
+ end
52
+
53
+ def variables
54
+ super + %w(id updated)
55
+ end
56
+
57
+ def variable_is_set?
58
+ super or !authors.empty?
59
+ end
60
+
61
+ def not_set_required_variables
62
+ vars = super
63
+ if authors.empty? and
64
+ @maker.items.all? {|item| item.author.to_s.empty?}
65
+ vars << "author"
66
+ end
67
+ vars << "title" unless title {|t| t.have_required_values?}
68
+ vars
69
+ end
70
+
71
+ def _set_default_values(&block)
72
+ keep = {
73
+ :id => id,
74
+ :updated => updated,
75
+ }
76
+ self.id ||= about
77
+ self.updated ||= dc_date
78
+ super(&block)
79
+ ensure
80
+ self.id = keep[:id]
81
+ self.updated = keep[:updated]
82
+ end
83
+
84
+ class SkipDays < SkipDaysBase
85
+ def to_feed(*args)
86
+ end
87
+
88
+ class Day < DayBase
89
+ end
90
+ end
91
+
92
+ class SkipHours < SkipHoursBase
93
+ def to_feed(*args)
94
+ end
95
+
96
+ class Hour < HourBase
97
+ end
98
+ end
99
+
100
+ class Cloud < CloudBase
101
+ def to_feed(*args)
102
+ end
103
+ end
104
+
105
+ class Categories < CategoriesBase
106
+ class Category < CategoryBase
107
+ include AtomCategory
108
+
109
+ def self.not_set_name
110
+ "maker.channel.category"
111
+ end
112
+ end
113
+ end
114
+
115
+ class Links < LinksBase
116
+ class Link < LinkBase
117
+ include AtomLink
118
+
119
+ def self.not_set_name
120
+ "maker.channel.link"
121
+ end
122
+ end
123
+ end
124
+
125
+ AtomPersons.def_atom_persons(self, "author", "maker.channel.author")
126
+ AtomPersons.def_atom_persons(self, "contributor",
127
+ "maker.channel.contributor")
128
+
129
+ class Generator < GeneratorBase
130
+ include AtomGenerator
131
+
132
+ def self.not_set_name
133
+ "maker.channel.generator"
134
+ end
135
+ end
136
+
137
+ AtomTextConstruct.def_atom_text_construct(self, "rights",
138
+ "maker.channel.copyright",
139
+ "Copyright")
140
+ AtomTextConstruct.def_atom_text_construct(self, "subtitle",
141
+ "maker.channel.description",
142
+ "Description")
143
+ AtomTextConstruct.def_atom_text_construct(self, "title",
144
+ "maker.channel.title")
145
+ end
146
+
147
+ class Image < ImageBase
148
+ def to_feed(feed)
149
+ logo = feed.class::Logo.new
150
+ class << logo
151
+ alias_method(:url=, :content=)
152
+ end
153
+ set = setup_values(logo)
154
+ class << logo
155
+ remove_method(:url=)
156
+ end
157
+ if set
158
+ feed.logo = logo
159
+ set_parent(logo, feed)
160
+ setup_other_elements(feed, logo)
161
+ elsif variable_is_set?
162
+ raise NotSetError.new("maker.image", not_set_required_variables)
163
+ end
164
+ end
165
+
166
+ private
167
+ def required_variable_names
168
+ %w(url)
169
+ end
170
+ end
171
+
172
+ class Items < ItemsBase
173
+ def to_feed(feed)
174
+ normalize.each do |item|
175
+ item.to_feed(feed)
176
+ end
177
+ setup_other_elements(feed, feed.entries)
178
+ end
179
+
180
+ class Item < ItemBase
181
+ def to_feed(feed)
182
+ set_default_values do
183
+ entry = feed.class::Entry.new
184
+ set = setup_values(entry)
185
+ setup_other_elements(feed, entry)
186
+ if set
187
+ feed.entries << entry
188
+ set_parent(entry, feed)
189
+ elsif variable_is_set?
190
+ raise NotSetError.new("maker.item", not_set_required_variables)
191
+ end
192
+ end
193
+ end
194
+
195
+ def have_required_values?
196
+ set_default_values do
197
+ super and title {|t| t.have_required_values?}
198
+ end
199
+ end
200
+
201
+ private
202
+ def required_variable_names
203
+ %w(id updated)
204
+ end
205
+
206
+ def variables
207
+ super + ["updated"]
208
+ end
209
+
210
+ def not_set_required_variables
211
+ vars = super
212
+ vars << "title" unless title {|t| t.have_required_values?}
213
+ vars
214
+ end
215
+
216
+ def _set_default_values(&block)
217
+ keep = {
218
+ :id => id,
219
+ :updated => updated,
220
+ }
221
+ self.id ||= link
222
+ self.updated ||= dc_date
223
+ super(&block)
224
+ ensure
225
+ self.id = keep[:id]
226
+ self.updated = keep[:updated]
227
+ end
228
+
229
+ class Guid < GuidBase
230
+ def to_feed(feed, current)
231
+ end
232
+ end
233
+
234
+ class Enclosure < EnclosureBase
235
+ def to_feed(feed, current)
236
+ end
237
+ end
238
+
239
+ class Source < SourceBase
240
+ def to_feed(feed, current)
241
+ source = current.class::Source.new
242
+ setup_values(source)
243
+ current.source = source
244
+ set_parent(source, current)
245
+ setup_other_elements(feed, source)
246
+ current.source = nil if source.to_s == "<source/>"
247
+ end
248
+
249
+ private
250
+ def required_variable_names
251
+ []
252
+ end
253
+
254
+ def variables
255
+ super + ["updated"]
256
+ end
257
+
258
+ AtomPersons.def_atom_persons(self, "author",
259
+ "maker.item.source.author")
260
+ AtomPersons.def_atom_persons(self, "contributor",
261
+ "maker.item.source.contributor")
262
+
263
+ class Categories < CategoriesBase
264
+ class Category < CategoryBase
265
+ include AtomCategory
266
+
267
+ def self.not_set_name
268
+ "maker.item.source.category"
269
+ end
270
+ end
271
+ end
272
+
273
+ class Generator < GeneratorBase
274
+ include AtomGenerator
275
+
276
+ def self.not_set_name
277
+ "maker.item.source.generator"
278
+ end
279
+ end
280
+
281
+ class Icon < IconBase
282
+ def to_feed(feed, current)
283
+ icon = current.class::Icon.new
284
+ class << icon
285
+ alias_method(:url=, :content=)
286
+ end
287
+ set = setup_values(icon)
288
+ class << icon
289
+ remove_method(:url=)
290
+ end
291
+ if set
292
+ current.icon = icon
293
+ set_parent(icon, current)
294
+ setup_other_elements(feed, icon)
295
+ elsif variable_is_set?
296
+ raise NotSetError.new("maker.item.source.icon",
297
+ not_set_required_variables)
298
+ end
299
+ end
300
+
301
+ private
302
+ def required_variable_names
303
+ %w(url)
304
+ end
305
+ end
306
+
307
+ class Links < LinksBase
308
+ class Link < LinkBase
309
+ include AtomLink
310
+
311
+ def self.not_set_name
312
+ "maker.item.source.link"
313
+ end
314
+ end
315
+ end
316
+
317
+ class Logo < LogoBase
318
+ include AtomLogo
319
+
320
+ def self.not_set_name
321
+ "maker.item.source.logo"
322
+ end
323
+ end
324
+
325
+ maker_name_base = "maker.item.source."
326
+ maker_name = "#{maker_name_base}rights"
327
+ AtomTextConstruct.def_atom_text_construct(self, "rights",
328
+ maker_name)
329
+ maker_name = "#{maker_name_base}subtitle"
330
+ AtomTextConstruct.def_atom_text_construct(self, "subtitle",
331
+ maker_name)
332
+ maker_name = "#{maker_name_base}title"
333
+ AtomTextConstruct.def_atom_text_construct(self, "title",
334
+ maker_name)
335
+ end
336
+
337
+ class Categories < CategoriesBase
338
+ class Category < CategoryBase
339
+ include AtomCategory
340
+
341
+ def self.not_set_name
342
+ "maker.item.category"
343
+ end
344
+ end
345
+ end
346
+
347
+ AtomPersons.def_atom_persons(self, "author", "maker.item.author")
348
+ AtomPersons.def_atom_persons(self, "contributor",
349
+ "maker.item.contributor")
350
+
351
+ class Links < LinksBase
352
+ class Link < LinkBase
353
+ include AtomLink
354
+
355
+ def self.not_set_name
356
+ "maker.item.link"
357
+ end
358
+ end
359
+ end
360
+
361
+ AtomTextConstruct.def_atom_text_construct(self, "rights",
362
+ "maker.item.rights")
363
+ AtomTextConstruct.def_atom_text_construct(self, "summary",
364
+ "maker.item.description",
365
+ "Description")
366
+ AtomTextConstruct.def_atom_text_construct(self, "title",
367
+ "maker.item.title")
368
+
369
+ class Content < ContentBase
370
+ def to_feed(feed, current)
371
+ content = current.class::Content.new
372
+ if setup_values(content)
373
+ content.src = nil if content.src and content.content
374
+ current.content = content
375
+ set_parent(content, current)
376
+ setup_other_elements(feed, content)
377
+ elsif variable_is_set?
378
+ raise NotSetError.new("maker.item.content",
379
+ not_set_required_variables)
380
+ end
381
+ end
382
+
383
+ alias_method(:xml, :xml_content)
384
+
385
+ private
386
+ def required_variable_names
387
+ if out_of_line?
388
+ %w(type)
389
+ elsif xml_type?
390
+ %w(xml_content)
391
+ else
392
+ %w(content)
393
+ end
394
+ end
395
+
396
+ def variables
397
+ if out_of_line?
398
+ super
399
+ elsif xml_type?
400
+ super + %w(xml)
401
+ else
402
+ super
403
+ end
404
+ end
405
+
406
+ def xml_type?
407
+ _type = type
408
+ return false if _type.nil?
409
+ _type == "xhtml" or
410
+ /(?:\+xml|\/xml)$/i =~ _type or
411
+ %w(text/xml-external-parsed-entity
412
+ application/xml-external-parsed-entity
413
+ application/xml-dtd).include?(_type.downcase)
414
+ end
415
+ end
416
+ end
417
+ end
418
+
419
+ class Textinput < TextinputBase
420
+ end
421
+ end
422
+ end
423
+
424
+ add_maker("atom", "1.0", Atom::Feed)
425
+ add_maker("atom:feed", "1.0", Atom::Feed)
426
+ add_maker("atom1.0", "1.0", Atom::Feed)
427
+ add_maker("atom1.0:feed", "1.0", Atom::Feed)
428
+ end
429
+ end