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,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