diff options
author | kou <kou@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-12-08 12:58:36 +0000 |
---|---|---|
committer | kou <kou@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-12-08 12:58:36 +0000 |
commit | bcf72db844b54492aca33b068711992bd73caccf (patch) | |
tree | a54da3329420c04614c460c3b45388951a790aa2 /lib/rss/rss.rb | |
parent | 67c5b057e692b39c801aea811c6b75b40c4b8c22 (diff) |
* lib/rss, test/rss, sample/rss: backported from CVS HEAD.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@7509 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rss/rss.rb')
-rw-r--r-- | lib/rss/rss.rb | 256 |
1 files changed, 217 insertions, 39 deletions
diff --git a/lib/rss/rss.rb b/lib/rss/rss.rb index b6afa24b93..11fe6d6dd1 100644 --- a/lib/rss/rss.rb +++ b/lib/rss/rss.rb @@ -58,7 +58,7 @@ require "rss/xml-stylesheet" module RSS - VERSION = "0.1.0" + VERSION = "0.1.2" URI = "http://purl.org/rss/1.0/" @@ -144,6 +144,15 @@ module RSS end end + class NotSetError < Error + attr_reader :name, :variables + def initialize(name, variables) + @name = name + @variables = variables + super("required variables of #{@name} are not set: #{@variables.join(', ')}") + end + end + module BaseModel include Utils @@ -164,17 +173,20 @@ EOC end alias_method(:install_have_attribute_element, :install_have_child_element) - def install_have_children_element(name, postfix="s") - add_have_children_element(name) - - def_children_accessor(name, postfix) - install_element(name, postfix) do |n, elem_name| + def install_have_children_element(name, plural_name=nil) + plural_name ||= "#{name}s" + add_have_children_element(name, plural_name) + add_plural_form(name, plural_name) + + def_children_accessor(name, plural_name) + install_element(name, "s") do |n, elem_name| <<-EOC - rv = '' + rv = [] @#{n}.each do |x| - rv << "\#{x.to_s(convert, indent)}" + value = "\#{x.to_s(convert, indent)}" + rv << value if /\\A\\s*\\z/ !~ value end - rv + rv.join("\n") EOC end end @@ -289,9 +301,9 @@ EOC end end - def def_children_accessor(accessor_name, postfix="s") + def def_children_accessor(accessor_name, plural_name) module_eval(<<-EOC, *get_file_and_line_from_caller(2)) - def #{accessor_name}#{postfix} + def #{plural_name} @#{accessor_name} end @@ -302,8 +314,12 @@ EOC @#{accessor_name}.send("[]", *args) end end - + def #{accessor_name}=(*args) + warn("Warning:\#{caller.first.sub(/:in `.*'\z/, '')}: " \ + "Don't use `#{accessor_name} = XXX'/`set_#{accessor_name}(XXX)'. " \ + "Those APIs are not sense of Ruby. " \ + "Use `#{plural_name} << XXX' instead of them.") if args.size == 1 @#{accessor_name}.push(args[0]) else @@ -314,6 +330,22 @@ EOC EOC end + def def_content_only_to_s + module_eval(<<-EOC, *get_file_and_line_from_caller(2)) + def to_s(convert=true, indent=calc_indent) + if @content + rv = tag(indent) do |next_indent| + h(@content) + end + rv = @converter.convert(rv) if convert and @converter + rv + else + "" + end + end +EOC + end + end class Element @@ -329,7 +361,8 @@ EOC klass.module_eval(<<-EOC) public - @tag_name = name.split(/::/).last.downcase + @tag_name = name.split(/::/).last + @tag_name[0,1] = @tag_name[0,1].downcase @indent_size = name.split(/::/).size - 2 @@must_call_validators = {} @@ -373,6 +406,7 @@ EOC def self.content_setup attr_writer :content convert_attr_reader :content + def_content_only_to_s @@have_content = true end @@ -386,8 +420,8 @@ EOC @@have_children_elements end - def self.add_have_children_element(variable_name) - @@have_children_elements << variable_name + def self.add_have_children_element(variable_name, plural_name) + @@have_children_elements << [variable_name, plural_name] end @@need_initialize_variables = [] @@ -400,6 +434,16 @@ EOC @@need_initialize_variables end + @@plural_forms = {} + + def self.add_plural_form(singular, plural) + @@plural_forms[singular] = plural + end + + def self.plural_forms + @@plural_forms + end + EOC end @@ -440,6 +484,14 @@ EOC self.class.tag_name end + def full_name + tag_name + end + + def indent_size + self.class.indent_size + end + def converter=(converter) @converter = converter children.each do |child| @@ -457,6 +509,15 @@ EOC __validate(tags, false) end + def setup_maker(maker) + target = maker_target(maker) + unless target.nil? + setup_maker_attributes(target) + setup_maker_element(target) + setup_maker_elements(target) + end + end + private def initialize_variables self.class.need_initialize_variables.each do |variable_name| @@ -467,11 +528,111 @@ EOC end def initialize_have_children_elements - self.class.have_children_elements.each do |variable_name| + self.class.have_children_elements.each do |variable_name, plural_name| instance_eval("@#{variable_name} = []") end end + def tag(indent, additional_attrs=[], &block) + next_indent = indent + INDENT + + attrs = collect_attrs + return "" if attrs.nil? + + attrs += additional_attrs + start_tag = make_start_tag(indent, next_indent, attrs) + + if block + content = block.call(next_indent) + else + content = [] + end + + if content.is_a?(String) + content = [content] + start_tag << ">" + end_tag = "</#{full_name}>" + else + content = content.reject{|x| x.empty?} + if content.empty? + end_tag = "/>" + else + start_tag << ">\n" + end_tag = "\n#{indent}</#{full_name}>" + end + end + + start_tag + content.join("\n") + end_tag + end + + def make_start_tag(indent, next_indent, attrs) + start_tag = ["#{indent}<#{full_name}"] + unless attrs.empty? + start_tag << attrs.collect do |key, value| + %Q[#{h key}="#{h value}"] + end.join("\n#{next_indent}") + end + start_tag.join(" ") + end + + def collect_attrs + _attrs.collect do |name, required, alias_name| + value = __send__(alias_name || name) + return nil if required and value.nil? + [name, value] + end.reject do |name, value| + value.nil? + end + end + + def tag_name_with_prefix(prefix) + "#{prefix}:#{tag_name}" + end + + def calc_indent + INDENT * (self.class.indent_size) + end + + def maker_target(maker) + nil + end + + def setup_maker_attributes(target) + end + + def setup_maker_element(target) + self.class.need_initialize_variables.each do |var| + setter = "#{var}=" + if target.respond_to?(setter) + target.__send__(setter, __send__(var)) + end + end + end + + def setup_maker_elements(parent) + self.class.have_children_elements.each do |name, plural_name| + real_name = name.sub(/^[^_]+_/, '') + if parent.respond_to?(plural_name) + target = parent.__send__(plural_name) + __send__(plural_name).each do |elem| + elem.__send__("setup_maker", target) + end + end + end + end + + def set_next_element(prefix, tag_name, next_element) + klass = next_element.class + prefix = "" + prefix << "#{klass.required_prefix}_" if klass.required_prefix + if self.class.plural_forms.has_key?(tag_name) + ary = __send__("#{prefix}#{self.class.plural_forms[tag_name]}") + ary << next_element + else + __send__("#{prefix}#{tag_name}=", next_element) + end + end + # not String class children. def children [] @@ -507,23 +668,23 @@ EOC end def validate_attribute - _attrs.each do |a_name, required| - if required and send(a_name).nil? - raise MissingAttributeError.new(self.class.tag_name, a_name) + _attrs.each do |a_name, required, alias_name| + if required and __send__(alias_name || a_name).nil? + raise MissingAttributeError.new(tag_name, a_name) end end end def other_element(convert, indent='') - rv = '' + rv = [] private_methods.each do |meth| if /\A([^_]+)_[^_]+_elements?\z/ =~ meth and self.class::NSPOOL.has_key?($1) - res = send(meth, convert) - rv << "#{indent}#{res}\n" if /\A\s*\z/ !~ res + res = __send__(meth, convert) + rv << "#{indent}#{res}" if /\A\s*\z/ !~ res end end - rv + rv.join("\n") end def _validate(tags, model=self.class.model) @@ -626,19 +787,12 @@ EOC rv end - private - def calc_indent - INDENT * (self.class.indent_size) - end - - def remove_empty_newline(string) - string.gsub(/^\s*$(?:\r?\n?)/, '') - end - end module RootElementMixin + include XMLStyleSheetMixin + attr_reader :output_encoding def initialize(rss_version, version=nil, encoding=nil, standalone=nil) @@ -655,26 +809,50 @@ EOC self.converter = Converter.new(@output_encoding, @encoding) end + def setup_maker(maker) + maker.version = version + maker.encoding = encoding + maker.standalone = standalone + + xml_stylesheets.each do |xss| + xss.setup_maker(maker) + end + + setup_maker_elements(maker) + end + private + def tag(indent, attrs, &block) + rv = xmldecl + xml_stylesheet_pi + rv << super(indent, attrs, &block) + rv + end + def xmldecl rv = %Q[<?xml version="#{@version}"] if @output_encoding or @encoding rv << %Q[ encoding="#{@output_encoding or @encoding}"] end - rv << %Q[ standalone="#{@standalone}"] if @standalone - rv << '?>' + rv << %Q[ standalone="yes"] if @standalone + rv << "?>\n" rv end - def ns_declaration(indent) - rv = '' - self.class::NSPOOL.each do |prefix, uri| + def ns_declarations + self.class::NSPOOL.collect do |prefix, uri| prefix = ":#{prefix}" unless prefix.empty? - rv << %Q|\n#{indent}xmlns#{prefix}="#{html_escape(uri)}"| + ["xmlns#{prefix}", uri] end - rv end + def setup_maker_elements(maker) + channel.setup_maker(maker) if channel + image.setup_maker(maker) if image + textinput.setup_maker(maker) if textinput + items.each do |item| + item.setup_maker(maker) + end + end end end |