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,34 @@
1
+ # frozen_string_literal: false
2
+ require_relative "rss"
3
+
4
+ module RSS
5
+ # The prefix for the Content XML namespace.
6
+ CONTENT_PREFIX = 'content'
7
+ # The URI of the Content specification.
8
+ CONTENT_URI = "http://purl.org/rss/1.0/modules/content/"
9
+
10
+ module ContentModel
11
+ extend BaseModel
12
+
13
+ ELEMENTS = ["#{CONTENT_PREFIX}_encoded"]
14
+
15
+ def self.append_features(klass)
16
+ super
17
+
18
+ klass.install_must_call_validator(CONTENT_PREFIX, CONTENT_URI)
19
+ ELEMENTS.each do |full_name|
20
+ name = full_name[(CONTENT_PREFIX.size + 1)..-1]
21
+ klass.install_text_element(name, CONTENT_URI, "?", full_name)
22
+ end
23
+ end
24
+ end
25
+
26
+ prefix_size = CONTENT_PREFIX.size + 1
27
+ ContentModel::ELEMENTS.each do |full_name|
28
+ name = full_name[prefix_size..-1]
29
+ BaseListener.install_get_text_element(CONTENT_URI, name, full_name)
30
+ end
31
+ end
32
+
33
+ require 'rss/content/1.0'
34
+ require 'rss/content/2.0'
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: false
2
+ require 'rss/1.0'
3
+
4
+ module RSS
5
+ RDF.install_ns(CONTENT_PREFIX, CONTENT_URI)
6
+
7
+ class RDF
8
+ class Item; include ContentModel; end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: false
2
+ require "rss/2.0"
3
+
4
+ module RSS
5
+ Rss.install_ns(CONTENT_PREFIX, CONTENT_URI)
6
+
7
+ class Rss
8
+ class Channel
9
+ class Item; include ContentModel; end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: false
2
+ require_relative "utils"
3
+
4
+ module RSS
5
+
6
+ class Converter
7
+
8
+ include Utils
9
+
10
+ def initialize(to_enc, from_enc=nil)
11
+ if "".respond_to?(:encode)
12
+ @to_encoding = to_enc
13
+ return
14
+ end
15
+ normalized_to_enc = to_enc.downcase.gsub(/-/, '_')
16
+ from_enc ||= 'utf-8'
17
+ normalized_from_enc = from_enc.downcase.gsub(/-/, '_')
18
+ if normalized_to_enc == normalized_from_enc
19
+ def_same_enc()
20
+ else
21
+ def_diff_enc = "def_to_#{normalized_to_enc}_from_#{normalized_from_enc}"
22
+ if respond_to?(def_diff_enc)
23
+ __send__(def_diff_enc)
24
+ else
25
+ def_else_enc(to_enc, from_enc)
26
+ end
27
+ end
28
+ end
29
+
30
+ def convert(value)
31
+ if value.is_a?(String) and value.respond_to?(:encode)
32
+ value.encode(@to_encoding)
33
+ else
34
+ value
35
+ end
36
+ end
37
+
38
+ def def_convert(depth=0)
39
+ instance_eval(<<-EOC, *get_file_and_line_from_caller(depth))
40
+ def convert(value)
41
+ if value.kind_of?(String)
42
+ #{yield('value')}
43
+ else
44
+ value
45
+ end
46
+ end
47
+ EOC
48
+ end
49
+
50
+ def def_iconv_convert(to_enc, from_enc, depth=0)
51
+ begin
52
+ require "iconv"
53
+ @iconv = Iconv.new(to_enc, from_enc)
54
+ def_convert(depth+1) do |value|
55
+ <<-EOC
56
+ begin
57
+ @iconv.iconv(#{value})
58
+ rescue Iconv::Failure
59
+ raise ConversionError.new(#{value}, "#{to_enc}", "#{from_enc}")
60
+ end
61
+ EOC
62
+ end
63
+ rescue LoadError, ArgumentError, SystemCallError
64
+ raise UnknownConversionMethodError.new(to_enc, from_enc)
65
+ end
66
+ end
67
+
68
+ def def_else_enc(to_enc, from_enc)
69
+ def_iconv_convert(to_enc, from_enc, 0)
70
+ end
71
+
72
+ def def_same_enc()
73
+ def_convert do |value|
74
+ value
75
+ end
76
+ end
77
+
78
+ def def_uconv_convert_if_can(meth, to_enc, from_enc, nkf_arg)
79
+ begin
80
+ require "uconv"
81
+ def_convert(1) do |value|
82
+ <<-EOC
83
+ begin
84
+ Uconv.#{meth}(#{value})
85
+ rescue Uconv::Error
86
+ raise ConversionError.new(#{value}, "#{to_enc}", "#{from_enc}")
87
+ end
88
+ EOC
89
+ end
90
+ rescue LoadError
91
+ require 'nkf'
92
+ if NKF.const_defined?(:UTF8)
93
+ def_convert(1) do |value|
94
+ "NKF.nkf(#{nkf_arg.dump}, #{value})"
95
+ end
96
+ else
97
+ def_iconv_convert(to_enc, from_enc, 1)
98
+ end
99
+ end
100
+ end
101
+
102
+ def def_to_euc_jp_from_utf_8
103
+ def_uconv_convert_if_can('u8toeuc', 'EUC-JP', 'UTF-8', '-We')
104
+ end
105
+
106
+ def def_to_utf_8_from_euc_jp
107
+ def_uconv_convert_if_can('euctou8', 'UTF-8', 'EUC-JP', '-Ew')
108
+ end
109
+
110
+ def def_to_shift_jis_from_utf_8
111
+ def_uconv_convert_if_can('u8tosjis', 'Shift_JIS', 'UTF-8', '-Ws')
112
+ end
113
+
114
+ def def_to_utf_8_from_shift_jis
115
+ def_uconv_convert_if_can('sjistou8', 'UTF-8', 'Shift_JIS', '-Sw')
116
+ end
117
+
118
+ def def_to_euc_jp_from_shift_jis
119
+ require "nkf"
120
+ def_convert do |value|
121
+ "NKF.nkf('-Se', #{value})"
122
+ end
123
+ end
124
+
125
+ def def_to_shift_jis_from_euc_jp
126
+ require "nkf"
127
+ def_convert do |value|
128
+ "NKF.nkf('-Es', #{value})"
129
+ end
130
+ end
131
+
132
+ def def_to_euc_jp_from_iso_2022_jp
133
+ require "nkf"
134
+ def_convert do |value|
135
+ "NKF.nkf('-Je', #{value})"
136
+ end
137
+ end
138
+
139
+ def def_to_iso_2022_jp_from_euc_jp
140
+ require "nkf"
141
+ def_convert do |value|
142
+ "NKF.nkf('-Ej', #{value})"
143
+ end
144
+ end
145
+
146
+ def def_to_utf_8_from_iso_8859_1
147
+ def_convert do |value|
148
+ "#{value}.unpack('C*').pack('U*')"
149
+ end
150
+ end
151
+
152
+ def def_to_iso_8859_1_from_utf_8
153
+ def_convert do |value|
154
+ <<-EOC
155
+ array_utf8 = #{value}.unpack('U*')
156
+ array_enc = []
157
+ array_utf8.each do |num|
158
+ if num <= 0xFF
159
+ array_enc << num
160
+ else
161
+ array_enc.concat "&\#\#{num};".unpack('C*')
162
+ end
163
+ end
164
+ array_enc.pack('C*')
165
+ EOC
166
+ end
167
+ end
168
+
169
+ end
170
+
171
+ end
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: false
2
+ require_relative "rss"
3
+
4
+ module RSS
5
+ # The prefix for the Dublin Core XML namespace.
6
+ DC_PREFIX = 'dc'
7
+ # The URI of the Dublin Core specification.
8
+ DC_URI = "http://purl.org/dc/elements/1.1/"
9
+
10
+ module BaseDublinCoreModel
11
+ def append_features(klass)
12
+ super
13
+
14
+ return if klass.instance_of?(Module)
15
+ DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
16
+ plural = plural_name || "#{name}s"
17
+ full_name = "#{DC_PREFIX}_#{name}"
18
+ full_plural_name = "#{DC_PREFIX}_#{plural}"
19
+ klass_name = "DublinCore#{Utils.to_class_name(name)}"
20
+ klass.install_must_call_validator(DC_PREFIX, DC_URI)
21
+ klass.install_have_children_element(name, DC_URI, "*",
22
+ full_name, full_plural_name)
23
+ klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0))
24
+ remove_method :#{full_name}
25
+ remove_method :#{full_name}=
26
+ remove_method :set_#{full_name}
27
+
28
+ def #{full_name}
29
+ @#{full_name}.first and @#{full_name}.first.value
30
+ end
31
+
32
+ def #{full_name}=(new_value)
33
+ @#{full_name}[0] = Utils.new_with_value_if_need(#{klass_name}, new_value)
34
+ end
35
+ alias set_#{full_name} #{full_name}=
36
+ EOC
37
+ end
38
+ klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0))
39
+ if method_defined?(:date)
40
+ alias date_without_#{DC_PREFIX}_date= date=
41
+
42
+ def date=(value)
43
+ self.date_without_#{DC_PREFIX}_date = value
44
+ self.#{DC_PREFIX}_date = value
45
+ end
46
+ else
47
+ alias date #{DC_PREFIX}_date
48
+ alias date= #{DC_PREFIX}_date=
49
+ end
50
+
51
+ # For backward compatibility
52
+ alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list
53
+ EOC
54
+ end
55
+ end
56
+
57
+ module DublinCoreModel
58
+
59
+ extend BaseModel
60
+ extend BaseDublinCoreModel
61
+
62
+ TEXT_ELEMENTS = {
63
+ "title" => nil,
64
+ "description" => nil,
65
+ "creator" => nil,
66
+ "subject" => nil,
67
+ "publisher" => nil,
68
+ "contributor" => nil,
69
+ "type" => nil,
70
+ "format" => nil,
71
+ "identifier" => nil,
72
+ "source" => nil,
73
+ "language" => nil,
74
+ "relation" => nil,
75
+ "coverage" => nil,
76
+ "rights" => "rights_list"
77
+ }
78
+
79
+ DATE_ELEMENTS = {
80
+ "date" => "w3cdtf",
81
+ }
82
+
83
+ ELEMENT_NAME_INFOS = DublinCoreModel::TEXT_ELEMENTS.to_a
84
+ DublinCoreModel::DATE_ELEMENTS.each do |name, |
85
+ ELEMENT_NAME_INFOS << [name, nil]
86
+ end
87
+
88
+ ELEMENTS = TEXT_ELEMENTS.keys + DATE_ELEMENTS.keys
89
+
90
+ ELEMENTS.each do |name, plural_name|
91
+ module_eval(<<-EOC, *get_file_and_line_from_caller(0))
92
+ class DublinCore#{Utils.to_class_name(name)} < Element
93
+ include RSS10
94
+
95
+ content_setup
96
+
97
+ class << self
98
+ def required_prefix
99
+ DC_PREFIX
100
+ end
101
+
102
+ def required_uri
103
+ DC_URI
104
+ end
105
+ end
106
+
107
+ @tag_name = #{name.dump}
108
+
109
+ alias_method(:value, :content)
110
+ alias_method(:value=, :content=)
111
+
112
+ def initialize(*args)
113
+ if Utils.element_initialize_arguments?(args)
114
+ super
115
+ else
116
+ super()
117
+ self.content = args[0]
118
+ end
119
+ end
120
+
121
+ def full_name
122
+ tag_name_with_prefix(DC_PREFIX)
123
+ end
124
+
125
+ def maker_target(target)
126
+ target.new_#{name}
127
+ end
128
+
129
+ def setup_maker_attributes(#{name})
130
+ #{name}.content = content
131
+ end
132
+ end
133
+ EOC
134
+ end
135
+
136
+ DATE_ELEMENTS.each do |name, type|
137
+ tag_name = "#{DC_PREFIX}:#{name}"
138
+ module_eval(<<-EOC, *get_file_and_line_from_caller(0))
139
+ class DublinCore#{Utils.to_class_name(name)} < Element
140
+ remove_method(:content=)
141
+ remove_method(:value=)
142
+
143
+ date_writer("content", #{type.dump}, #{tag_name.dump})
144
+
145
+ alias_method(:value=, :content=)
146
+ end
147
+ EOC
148
+ end
149
+ end
150
+
151
+ # For backward compatibility
152
+ DublincoreModel = DublinCoreModel
153
+
154
+ DublinCoreModel::ELEMENTS.each do |name|
155
+ class_name = Utils.to_class_name(name)
156
+ BaseListener.install_class_name(DC_URI, name, "DublinCore#{class_name}")
157
+ end
158
+
159
+ DublinCoreModel::ELEMENTS.collect! {|name| "#{DC_PREFIX}_#{name}"}
160
+ end
161
+
162
+ require 'rss/dublincore/1.0'
163
+ require 'rss/dublincore/2.0'
164
+ require_relative 'dublincore/atom'
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: false
2
+ require "rss/1.0"
3
+
4
+ module RSS
5
+ RDF.install_ns(DC_PREFIX, DC_URI)
6
+
7
+ class RDF
8
+ class Channel; include DublinCoreModel; end
9
+ class Image; include DublinCoreModel; end
10
+ class Item; include DublinCoreModel; end
11
+ class Textinput; include DublinCoreModel; end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: false
2
+ require "rss/2.0"
3
+
4
+ module RSS
5
+ Rss.install_ns(DC_PREFIX, DC_URI)
6
+
7
+ class Rss
8
+ class Channel
9
+ include DublinCoreModel
10
+ class Item; include DublinCoreModel; end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: false
2
+ require_relative "../atom"
3
+
4
+ module RSS
5
+ module Atom
6
+ Feed.install_ns(DC_PREFIX, DC_URI)
7
+
8
+ class Feed
9
+ include DublinCoreModel
10
+ class Entry; include DublinCoreModel; end
11
+ end
12
+
13
+ class Entry
14
+ include DublinCoreModel
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,198 @@
1
+ # frozen_string_literal: false
2
+ require 'rss/1.0'
3
+ require_relative 'dublincore'
4
+
5
+ module RSS
6
+
7
+ # The prefix for the Image XML namespace.
8
+ IMAGE_PREFIX = 'image'
9
+ # The URI for the Image specification.
10
+ IMAGE_URI = 'http://purl.org/rss/1.0/modules/image/'
11
+
12
+ RDF.install_ns(IMAGE_PREFIX, IMAGE_URI)
13
+
14
+ # This constant holds strings which contain the names of
15
+ # image elements, with the appropriate prefix.
16
+ IMAGE_ELEMENTS = []
17
+
18
+ %w(item favicon).each do |name|
19
+ class_name = Utils.to_class_name(name)
20
+ BaseListener.install_class_name(IMAGE_URI, name, "Image#{class_name}")
21
+ IMAGE_ELEMENTS << "#{IMAGE_PREFIX}_#{name}"
22
+ end
23
+
24
+ module ImageModelUtils
25
+ def validate_one_tag_name(ignore_unknown_element, name, tags)
26
+ if !ignore_unknown_element
27
+ invalid = tags.find {|tag| tag != name}
28
+ raise UnknownTagError.new(invalid, IMAGE_URI) if invalid
29
+ end
30
+ raise TooMuchTagError.new(name, tag_name) if tags.size > 1
31
+ end
32
+ end
33
+
34
+ module ImageItemModel
35
+ include ImageModelUtils
36
+ extend BaseModel
37
+
38
+ def self.append_features(klass)
39
+ super
40
+
41
+ klass.install_have_child_element("item", IMAGE_URI, "?",
42
+ "#{IMAGE_PREFIX}_item")
43
+ klass.install_must_call_validator(IMAGE_PREFIX, IMAGE_URI)
44
+ end
45
+
46
+ class ImageItem < Element
47
+ include RSS10
48
+ include DublinCoreModel
49
+
50
+ @tag_name = "item"
51
+
52
+ class << self
53
+ def required_prefix
54
+ IMAGE_PREFIX
55
+ end
56
+
57
+ def required_uri
58
+ IMAGE_URI
59
+ end
60
+ end
61
+
62
+ install_must_call_validator(IMAGE_PREFIX, IMAGE_URI)
63
+
64
+ [
65
+ ["about", ::RSS::RDF::URI, true],
66
+ ["resource", ::RSS::RDF::URI, false],
67
+ ].each do |name, uri, required|
68
+ install_get_attribute(name, uri, required, nil, nil,
69
+ "#{::RSS::RDF::PREFIX}:#{name}")
70
+ end
71
+
72
+ %w(width height).each do |tag|
73
+ full_name = "#{IMAGE_PREFIX}_#{tag}"
74
+ disp_name = "#{IMAGE_PREFIX}:#{tag}"
75
+ install_text_element(tag, IMAGE_URI, "?",
76
+ full_name, :integer, disp_name)
77
+ BaseListener.install_get_text_element(IMAGE_URI, tag, full_name)
78
+ end
79
+
80
+ alias width= image_width=
81
+ alias width image_width
82
+ alias height= image_height=
83
+ alias height image_height
84
+
85
+ def initialize(*args)
86
+ if Utils.element_initialize_arguments?(args)
87
+ super
88
+ else
89
+ super()
90
+ self.about = args[0]
91
+ self.resource = args[1]
92
+ end
93
+ end
94
+
95
+ def full_name
96
+ tag_name_with_prefix(IMAGE_PREFIX)
97
+ end
98
+
99
+ private
100
+ def maker_target(target)
101
+ target.image_item
102
+ end
103
+
104
+ def setup_maker_attributes(item)
105
+ item.about = self.about
106
+ item.resource = self.resource
107
+ end
108
+ end
109
+ end
110
+
111
+ module ImageFaviconModel
112
+ include ImageModelUtils
113
+ extend BaseModel
114
+
115
+ def self.append_features(klass)
116
+ super
117
+
118
+ unless klass.class == Module
119
+ klass.install_have_child_element("favicon", IMAGE_URI, "?",
120
+ "#{IMAGE_PREFIX}_favicon")
121
+ klass.install_must_call_validator(IMAGE_PREFIX, IMAGE_URI)
122
+ end
123
+ end
124
+
125
+ class ImageFavicon < Element
126
+ include RSS10
127
+ include DublinCoreModel
128
+
129
+ @tag_name = "favicon"
130
+
131
+ class << self
132
+ def required_prefix
133
+ IMAGE_PREFIX
134
+ end
135
+
136
+ def required_uri
137
+ IMAGE_URI
138
+ end
139
+ end
140
+
141
+ [
142
+ ["about", ::RSS::RDF::URI, true, ::RSS::RDF::PREFIX],
143
+ ["size", IMAGE_URI, true, IMAGE_PREFIX],
144
+ ].each do |name, uri, required, prefix|
145
+ install_get_attribute(name, uri, required, nil, nil,
146
+ "#{prefix}:#{name}")
147
+ end
148
+
149
+ AVAILABLE_SIZES = %w(small medium large)
150
+ alias_method :set_size, :size=
151
+ private :set_size
152
+ def size=(new_value)
153
+ if @do_validate and !new_value.nil?
154
+ new_value = new_value.strip
155
+ unless AVAILABLE_SIZES.include?(new_value)
156
+ attr_name = "#{IMAGE_PREFIX}:size"
157
+ raise NotAvailableValueError.new(full_name, new_value, attr_name)
158
+ end
159
+ end
160
+ set_size(new_value)
161
+ end
162
+
163
+ alias image_size= size=
164
+ alias image_size size
165
+
166
+ def initialize(*args)
167
+ if Utils.element_initialize_arguments?(args)
168
+ super
169
+ else
170
+ super()
171
+ self.about = args[0]
172
+ self.size = args[1]
173
+ end
174
+ end
175
+
176
+ def full_name
177
+ tag_name_with_prefix(IMAGE_PREFIX)
178
+ end
179
+
180
+ private
181
+ def maker_target(target)
182
+ target.image_favicon
183
+ end
184
+
185
+ def setup_maker_attributes(favicon)
186
+ favicon.about = self.about
187
+ favicon.size = self.size
188
+ end
189
+ end
190
+
191
+ end
192
+
193
+ class RDF
194
+ class Channel; include ImageFaviconModel; end
195
+ class Item; include ImageItemModel; end
196
+ end
197
+
198
+ end