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,111 @@
1
+ module RSS
2
+ module Utils
3
+ module_function
4
+
5
+ # Convert a name_with_underscores to CamelCase.
6
+ def to_class_name(name)
7
+ name.split(/[_\-]/).collect do |part|
8
+ "#{part[0, 1].upcase}#{part[1..-1]}"
9
+ end.join("")
10
+ end
11
+
12
+ def get_file_and_line_from_caller(i=0)
13
+ file, line, = caller[i].split(':')
14
+ line = line.to_i
15
+ line += 1 if i.zero?
16
+ [file, line]
17
+ end
18
+
19
+ # escape '&', '"', '<' and '>' for use in HTML.
20
+ def html_escape(s)
21
+ s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
22
+ end
23
+ alias h html_escape
24
+
25
+ # If +value+ is an instance of class +klass+, return it, else
26
+ # create a new instance of +klass+ with value +value+.
27
+ def new_with_value_if_need(klass, value)
28
+ if value.is_a?(klass)
29
+ value
30
+ else
31
+ klass.new(value)
32
+ end
33
+ end
34
+
35
+ def element_initialize_arguments?(args)
36
+ [true, false].include?(args[0]) and args[1].is_a?(Hash)
37
+ end
38
+
39
+ module YesCleanOther
40
+ module_function
41
+ def parse(value)
42
+ if [true, false, nil].include?(value)
43
+ value
44
+ else
45
+ case value.to_s
46
+ when /\Ayes\z/i
47
+ true
48
+ when /\Aclean\z/i
49
+ false
50
+ else
51
+ nil
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ module YesOther
58
+ module_function
59
+ def parse(value)
60
+ if [true, false].include?(value)
61
+ value
62
+ else
63
+ /\Ayes\z/i.match(value.to_s) ? true : false
64
+ end
65
+ end
66
+ end
67
+
68
+ module CSV
69
+ module_function
70
+ def parse(value, &block)
71
+ if value.is_a?(String)
72
+ value = value.strip.split(/\s*,\s*/)
73
+ value = value.collect(&block) if block_given?
74
+ value
75
+ else
76
+ value
77
+ end
78
+ end
79
+ end
80
+
81
+ module InheritedReader
82
+ def inherited_reader(constant_name)
83
+ base_class = inherited_base
84
+ result = base_class.const_get(constant_name)
85
+ found_base_class = false
86
+ ancestors.reverse_each do |klass|
87
+ if found_base_class
88
+ if klass.const_defined?(constant_name)
89
+ result = yield(result, klass.const_get(constant_name))
90
+ end
91
+ else
92
+ found_base_class = klass == base_class
93
+ end
94
+ end
95
+ result
96
+ end
97
+
98
+ def inherited_array_reader(constant_name)
99
+ inherited_reader(constant_name) do |result, current|
100
+ current + result
101
+ end
102
+ end
103
+
104
+ def inherited_hash_reader(constant_name)
105
+ inherited_reader(constant_name) do |result, current|
106
+ result.merge(current)
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,105 @@
1
+ require "rss/utils"
2
+
3
+ module RSS
4
+
5
+ module XMLStyleSheetMixin
6
+ attr_accessor :xml_stylesheets
7
+ def initialize(*args)
8
+ super
9
+ @xml_stylesheets = []
10
+ end
11
+
12
+ private
13
+ def xml_stylesheet_pi
14
+ xsss = @xml_stylesheets.collect do |xss|
15
+ pi = xss.to_s
16
+ pi = nil if /\A\s*\z/ =~ pi
17
+ pi
18
+ end.compact
19
+ xsss.push("") unless xsss.empty?
20
+ xsss.join("\n")
21
+ end
22
+ end
23
+
24
+ class XMLStyleSheet
25
+
26
+ include Utils
27
+
28
+ ATTRIBUTES = %w(href type title media charset alternate)
29
+
30
+ GUESS_TABLE = {
31
+ "xsl" => "text/xsl",
32
+ "css" => "text/css",
33
+ }
34
+
35
+ attr_accessor(*ATTRIBUTES)
36
+ attr_accessor(:do_validate)
37
+ def initialize(*attrs)
38
+ if attrs.size == 1 and
39
+ (attrs.first.is_a?(Hash) or attrs.first.is_a?(Array))
40
+ attrs = attrs.first
41
+ end
42
+ @do_validate = true
43
+ ATTRIBUTES.each do |attr|
44
+ __send__("#{attr}=", nil)
45
+ end
46
+ vars = ATTRIBUTES.dup
47
+ vars.unshift(:do_validate)
48
+ attrs.each do |name, value|
49
+ if vars.include?(name.to_s)
50
+ __send__("#{name}=", value)
51
+ end
52
+ end
53
+ end
54
+
55
+ def to_s
56
+ rv = ""
57
+ if @href
58
+ rv << %Q[<?xml-stylesheet]
59
+ ATTRIBUTES.each do |name|
60
+ if __send__(name)
61
+ rv << %Q[ #{name}="#{h __send__(name)}"]
62
+ end
63
+ end
64
+ rv << %Q[?>]
65
+ end
66
+ rv
67
+ end
68
+
69
+ remove_method(:href=)
70
+ def href=(value)
71
+ @href = value
72
+ if @href and @type.nil?
73
+ @type = guess_type(@href)
74
+ end
75
+ @href
76
+ end
77
+
78
+ remove_method(:alternate=)
79
+ def alternate=(value)
80
+ if value.nil? or /\A(?:yes|no)\z/ =~ value
81
+ @alternate = value
82
+ else
83
+ if @do_validate
84
+ args = ["?xml-stylesheet?", %Q[alternate="#{value}"]]
85
+ raise NotAvailableValueError.new(*args)
86
+ end
87
+ end
88
+ @alternate
89
+ end
90
+
91
+ def setup_maker(maker)
92
+ xss = maker.xml_stylesheets.new_xml_stylesheet
93
+ ATTRIBUTES.each do |attr|
94
+ xss.__send__("#{attr}=", __send__(attr))
95
+ end
96
+ end
97
+
98
+ private
99
+ def guess_type(filename)
100
+ /\.([^.]+)$/ =~ filename
101
+ GUESS_TABLE[$1]
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,71 @@
1
+ require "rss/utils"
2
+
3
+ module RSS
4
+ module XML
5
+ class Element
6
+ include Enumerable
7
+
8
+ attr_reader :name, :prefix, :uri, :attributes, :children
9
+ def initialize(name, prefix=nil, uri=nil, attributes={}, children=[])
10
+ @name = name
11
+ @prefix = prefix
12
+ @uri = uri
13
+ @attributes = attributes
14
+ if children.is_a?(String) or !children.respond_to?(:each)
15
+ @children = [children]
16
+ else
17
+ @children = children
18
+ end
19
+ end
20
+
21
+ def [](name)
22
+ @attributes[name]
23
+ end
24
+
25
+ def []=(name, value)
26
+ @attributes[name] = value
27
+ end
28
+
29
+ def <<(child)
30
+ @children << child
31
+ end
32
+
33
+ def each(&block)
34
+ @children.each(&block)
35
+ end
36
+
37
+ def ==(other)
38
+ other.kind_of?(self.class) and
39
+ @name == other.name and
40
+ @uri == other.uri and
41
+ @attributes == other.attributes and
42
+ @children == other.children
43
+ end
44
+
45
+ def to_s
46
+ rv = "<#{full_name}"
47
+ attributes.each do |key, value|
48
+ rv << " #{Utils.html_escape(key)}=\"#{Utils.html_escape(value)}\""
49
+ end
50
+ if children.empty?
51
+ rv << "/>"
52
+ else
53
+ rv << ">"
54
+ children.each do |child|
55
+ rv << child.to_s
56
+ end
57
+ rv << "</#{full_name}>"
58
+ end
59
+ rv
60
+ end
61
+
62
+ def full_name
63
+ if @prefix
64
+ "#{@prefix}:#{@name}"
65
+ else
66
+ @name
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,93 @@
1
+ begin
2
+ require "xml/parser"
3
+ rescue LoadError
4
+ require "xmlparser"
5
+ end
6
+
7
+ begin
8
+ require "xml/encoding-ja"
9
+ rescue LoadError
10
+ require "xmlencoding-ja"
11
+ if defined?(Kconv)
12
+ module XMLEncoding_ja
13
+ class SJISHandler
14
+ include Kconv
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ module XML
21
+ class Parser
22
+ unless defined?(Error)
23
+ Error = ::XMLParserError
24
+ end
25
+ end
26
+ end
27
+
28
+ module RSS
29
+
30
+ class REXMLLikeXMLParser < ::XML::Parser
31
+
32
+ include ::XML::Encoding_ja
33
+
34
+ def listener=(listener)
35
+ @listener = listener
36
+ end
37
+
38
+ def startElement(name, attrs)
39
+ @listener.tag_start(name, attrs)
40
+ end
41
+
42
+ def endElement(name)
43
+ @listener.tag_end(name)
44
+ end
45
+
46
+ def character(data)
47
+ @listener.text(data)
48
+ end
49
+
50
+ def xmlDecl(version, encoding, standalone)
51
+ @listener.xmldecl(version, encoding, standalone == 1)
52
+ end
53
+
54
+ def processingInstruction(target, content)
55
+ @listener.instruction(target, content)
56
+ end
57
+
58
+ end
59
+
60
+ class XMLParserParser < BaseParser
61
+
62
+ class << self
63
+ def listener
64
+ XMLParserListener
65
+ end
66
+ end
67
+
68
+ private
69
+ def _parse
70
+ begin
71
+ parser = REXMLLikeXMLParser.new
72
+ parser.listener = @listener
73
+ parser.parse(@rss)
74
+ rescue ::XML::Parser::Error => e
75
+ raise NotWellFormedError.new(parser.line){e.message}
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ class XMLParserListener < BaseListener
82
+
83
+ include ListenerMixin
84
+
85
+ def xmldecl(version, encoding, standalone)
86
+ super
87
+ # Encoding is converted to UTF-8 when XMLParser parses XML.
88
+ @encoding = 'UTF-8'
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,121 @@
1
+ require 'xmlscan/scanner'
2
+ require 'stringio'
3
+
4
+ module RSS
5
+
6
+ class XMLScanParser < BaseParser
7
+
8
+ class << self
9
+ def listener
10
+ XMLScanListener
11
+ end
12
+ end
13
+
14
+ private
15
+ def _parse
16
+ begin
17
+ if @rss.is_a?(String)
18
+ input = StringIO.new(@rss)
19
+ else
20
+ input = @rss
21
+ end
22
+ scanner = XMLScan::XMLScanner.new(@listener)
23
+ scanner.parse(input)
24
+ rescue XMLScan::Error => e
25
+ lineno = e.lineno || scanner.lineno || input.lineno
26
+ raise NotWellFormedError.new(lineno){e.message}
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ class XMLScanListener < BaseListener
33
+
34
+ include XMLScan::Visitor
35
+ include ListenerMixin
36
+
37
+ ENTITIES = {
38
+ 'lt' => '<',
39
+ 'gt' => '>',
40
+ 'amp' => '&',
41
+ 'quot' => '"',
42
+ 'apos' => '\''
43
+ }
44
+
45
+ def on_xmldecl_version(str)
46
+ @version = str
47
+ end
48
+
49
+ def on_xmldecl_encoding(str)
50
+ @encoding = str
51
+ end
52
+
53
+ def on_xmldecl_standalone(str)
54
+ @standalone = str
55
+ end
56
+
57
+ def on_xmldecl_end
58
+ xmldecl(@version, @encoding, @standalone == "yes")
59
+ end
60
+
61
+ alias_method(:on_pi, :instruction)
62
+ alias_method(:on_chardata, :text)
63
+ alias_method(:on_cdata, :text)
64
+
65
+ def on_etag(name)
66
+ tag_end(name)
67
+ end
68
+
69
+ def on_entityref(ref)
70
+ text(entity(ref))
71
+ end
72
+
73
+ def on_charref(code)
74
+ text([code].pack('U'))
75
+ end
76
+
77
+ alias_method(:on_charref_hex, :on_charref)
78
+
79
+ def on_stag(name)
80
+ @attrs = {}
81
+ end
82
+
83
+ def on_attribute(name)
84
+ @attrs[name] = @current_attr = ''
85
+ end
86
+
87
+ def on_attr_value(str)
88
+ @current_attr << str
89
+ end
90
+
91
+ def on_attr_entityref(ref)
92
+ @current_attr << entity(ref)
93
+ end
94
+
95
+ def on_attr_charref(code)
96
+ @current_attr << [code].pack('U')
97
+ end
98
+
99
+ alias_method(:on_attr_charref_hex, :on_attr_charref)
100
+
101
+ def on_stag_end(name)
102
+ tag_start(name, @attrs)
103
+ end
104
+
105
+ def on_stag_end_empty(name)
106
+ tag_start(name, @attrs)
107
+ tag_end(name)
108
+ end
109
+
110
+ private
111
+ def entity(ref)
112
+ ent = ENTITIES[ref]
113
+ if ent
114
+ ent
115
+ else
116
+ wellformed_error("undefined entity: #{ref}")
117
+ end
118
+ end
119
+ end
120
+
121
+ end