mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	[#15206] [Fix GH-1976] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65505 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			462 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			462 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
# frozen_string_literal: false
 | 
						|
require_relative "parser"
 | 
						|
 | 
						|
module RSS
 | 
						|
 | 
						|
  ##
 | 
						|
  # = RSS 0.9 support
 | 
						|
  #
 | 
						|
  # RSS has three different versions. This module contains support for version
 | 
						|
  # 0.9.1[http://www.rssboard.org/rss-0-9-1-netscape].
 | 
						|
  #
 | 
						|
  # == Producing RSS 0.9
 | 
						|
  #
 | 
						|
  # Producing our own RSS feeds is easy as well. Let's make a very basic feed:
 | 
						|
  #
 | 
						|
  #  require "rss"
 | 
						|
  #
 | 
						|
  #  rss = RSS::Maker.make("0.91") do |maker|
 | 
						|
  #    maker.channel.language = "en"
 | 
						|
  #    maker.channel.author = "matz"
 | 
						|
  #    maker.channel.updated = Time.now.to_s
 | 
						|
  #    maker.channel.link = "http://www.ruby-lang.org/en/feeds/news.rss"
 | 
						|
  #    maker.channel.title = "Example Feed"
 | 
						|
  #    maker.channel.description = "A longer description of my feed."
 | 
						|
  #    maker.image.url = "http://www.ruby-lang.org/images/logo.gif"
 | 
						|
  #    maker.image.title = "An image"
 | 
						|
  #    maker.items.new_item do |item|
 | 
						|
  #      item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/"
 | 
						|
  #      item.title = "Ruby 1.9.2-p136 is released"
 | 
						|
  #      item.updated = Time.now.to_s
 | 
						|
  #    end
 | 
						|
  #  end
 | 
						|
  #
 | 
						|
  #  puts rss
 | 
						|
  #
 | 
						|
  # As you can see, this is a very Builder-like DSL. This code will spit out an
 | 
						|
  # RSS 0.9 feed with one item. If we needed a second item, we'd make another
 | 
						|
  # block with maker.items.new_item and build a second one.
 | 
						|
  module RSS09
 | 
						|
    NSPOOL = {}
 | 
						|
    ELEMENTS = []
 | 
						|
 | 
						|
    def self.append_features(klass)
 | 
						|
      super
 | 
						|
 | 
						|
      klass.install_must_call_validator('', "")
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  class Rss < Element
 | 
						|
 | 
						|
    include RSS09
 | 
						|
    include RootElementMixin
 | 
						|
 | 
						|
    %w(channel).each do |name|
 | 
						|
      install_have_child_element(name, "", nil)
 | 
						|
    end
 | 
						|
 | 
						|
    attr_writer :feed_version
 | 
						|
    alias_method(:rss_version, :feed_version)
 | 
						|
    alias_method(:rss_version=, :feed_version=)
 | 
						|
 | 
						|
    def initialize(feed_version, version=nil, encoding=nil, standalone=nil)
 | 
						|
      super
 | 
						|
      @feed_type = "rss"
 | 
						|
    end
 | 
						|
 | 
						|
    def items
 | 
						|
      if @channel
 | 
						|
        @channel.items
 | 
						|
      else
 | 
						|
        []
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    def image
 | 
						|
      if @channel
 | 
						|
        @channel.image
 | 
						|
      else
 | 
						|
        nil
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    def textinput
 | 
						|
      if @channel
 | 
						|
        @channel.textInput
 | 
						|
      else
 | 
						|
        nil
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    def setup_maker_elements(maker)
 | 
						|
      super
 | 
						|
      items.each do |item|
 | 
						|
        item.setup_maker(maker.items)
 | 
						|
      end
 | 
						|
      image.setup_maker(maker) if image
 | 
						|
      textinput.setup_maker(maker) if textinput
 | 
						|
    end
 | 
						|
 | 
						|
    private
 | 
						|
    def _attrs
 | 
						|
      [
 | 
						|
        ["version", true, "feed_version"],
 | 
						|
      ]
 | 
						|
    end
 | 
						|
 | 
						|
    class Channel < Element
 | 
						|
 | 
						|
      include RSS09
 | 
						|
 | 
						|
      [
 | 
						|
        ["title", nil, :text],
 | 
						|
        ["link", nil, :text],
 | 
						|
        ["description", nil, :text],
 | 
						|
        ["language", nil, :text],
 | 
						|
        ["copyright", "?", :text],
 | 
						|
        ["managingEditor", "?", :text],
 | 
						|
        ["webMaster", "?", :text],
 | 
						|
        ["rating", "?", :text],
 | 
						|
        ["pubDate", "?", :date, :rfc822],
 | 
						|
        ["lastBuildDate", "?", :date, :rfc822],
 | 
						|
        ["docs", "?", :text],
 | 
						|
        ["cloud", "?", :have_attribute],
 | 
						|
        ["skipDays", "?", :have_child],
 | 
						|
        ["skipHours", "?", :have_child],
 | 
						|
        ["image", nil, :have_child],
 | 
						|
        ["item", "*", :have_children],
 | 
						|
        ["textInput", "?", :have_child],
 | 
						|
      ].each do |name, occurs, type, *args|
 | 
						|
        __send__("install_#{type}_element", name, "", occurs, name, *args)
 | 
						|
      end
 | 
						|
      alias date pubDate
 | 
						|
      alias date= pubDate=
 | 
						|
 | 
						|
      private
 | 
						|
      def maker_target(maker)
 | 
						|
        maker.channel
 | 
						|
      end
 | 
						|
 | 
						|
      def setup_maker_elements(channel)
 | 
						|
        super
 | 
						|
        [
 | 
						|
          [skipDays, "day"],
 | 
						|
          [skipHours, "hour"],
 | 
						|
        ].each do |skip, key|
 | 
						|
          if skip
 | 
						|
            skip.__send__("#{key}s").each do |val|
 | 
						|
              target_skips = channel.__send__("skip#{key.capitalize}s")
 | 
						|
              new_target = target_skips.__send__("new_#{key}")
 | 
						|
              new_target.content = val.content
 | 
						|
            end
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      def not_need_to_call_setup_maker_variables
 | 
						|
        %w(image textInput)
 | 
						|
      end
 | 
						|
 | 
						|
      class SkipDays < Element
 | 
						|
        include RSS09
 | 
						|
 | 
						|
        [
 | 
						|
          ["day", "*"]
 | 
						|
        ].each do |name, occurs|
 | 
						|
          install_have_children_element(name, "", occurs)
 | 
						|
        end
 | 
						|
 | 
						|
        class Day < Element
 | 
						|
          include RSS09
 | 
						|
 | 
						|
          content_setup
 | 
						|
 | 
						|
          def initialize(*args)
 | 
						|
            if Utils.element_initialize_arguments?(args)
 | 
						|
              super
 | 
						|
            else
 | 
						|
              super()
 | 
						|
              self.content = args[0]
 | 
						|
            end
 | 
						|
          end
 | 
						|
 | 
						|
        end
 | 
						|
 | 
						|
      end
 | 
						|
 | 
						|
      class SkipHours < Element
 | 
						|
        include RSS09
 | 
						|
 | 
						|
        [
 | 
						|
          ["hour", "*"]
 | 
						|
        ].each do |name, occurs|
 | 
						|
          install_have_children_element(name, "", occurs)
 | 
						|
        end
 | 
						|
 | 
						|
        class Hour < Element
 | 
						|
          include RSS09
 | 
						|
 | 
						|
          content_setup(:integer)
 | 
						|
 | 
						|
          def initialize(*args)
 | 
						|
            if Utils.element_initialize_arguments?(args)
 | 
						|
              super
 | 
						|
            else
 | 
						|
              super()
 | 
						|
              self.content = args[0]
 | 
						|
            end
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
      end
 | 
						|
 | 
						|
      class Image < Element
 | 
						|
 | 
						|
        include RSS09
 | 
						|
 | 
						|
        %w(url title link).each do |name|
 | 
						|
          install_text_element(name, "", nil)
 | 
						|
        end
 | 
						|
        [
 | 
						|
          ["width", :integer],
 | 
						|
          ["height", :integer],
 | 
						|
          ["description"],
 | 
						|
        ].each do |name, type|
 | 
						|
          install_text_element(name, "", "?", name, type)
 | 
						|
        end
 | 
						|
 | 
						|
        def initialize(*args)
 | 
						|
          if Utils.element_initialize_arguments?(args)
 | 
						|
            super
 | 
						|
          else
 | 
						|
            super()
 | 
						|
            self.url = args[0]
 | 
						|
            self.title = args[1]
 | 
						|
            self.link = args[2]
 | 
						|
            self.width = args[3]
 | 
						|
            self.height = args[4]
 | 
						|
            self.description = args[5]
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        private
 | 
						|
        def maker_target(maker)
 | 
						|
          maker.image
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      class Cloud < Element
 | 
						|
 | 
						|
        include RSS09
 | 
						|
 | 
						|
        [
 | 
						|
          ["domain", "", true],
 | 
						|
          ["port", "", true, :integer],
 | 
						|
          ["path", "", true],
 | 
						|
          ["registerProcedure", "", true],
 | 
						|
          ["protocol", "", true],
 | 
						|
        ].each do |name, uri, required, type|
 | 
						|
          install_get_attribute(name, uri, required, type)
 | 
						|
        end
 | 
						|
 | 
						|
        def initialize(*args)
 | 
						|
          if Utils.element_initialize_arguments?(args)
 | 
						|
            super
 | 
						|
          else
 | 
						|
            super()
 | 
						|
            self.domain = args[0]
 | 
						|
            self.port = args[1]
 | 
						|
            self.path = args[2]
 | 
						|
            self.registerProcedure = args[3]
 | 
						|
            self.protocol = args[4]
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      class Item < Element
 | 
						|
 | 
						|
        include RSS09
 | 
						|
 | 
						|
        [
 | 
						|
          ["title", '?', :text],
 | 
						|
          ["link", '?', :text],
 | 
						|
          ["description", '?', :text],
 | 
						|
          ["category", '*', :have_children, "categories"],
 | 
						|
          ["source", '?', :have_child],
 | 
						|
          ["enclosure", '?', :have_child],
 | 
						|
        ].each do |tag, occurs, type, *args|
 | 
						|
          __send__("install_#{type}_element", tag, "", occurs, tag, *args)
 | 
						|
        end
 | 
						|
 | 
						|
        private
 | 
						|
        def maker_target(items)
 | 
						|
          if items.respond_to?("items")
 | 
						|
            # For backward compatibility
 | 
						|
            items = items.items
 | 
						|
          end
 | 
						|
          items.new_item
 | 
						|
        end
 | 
						|
 | 
						|
        def setup_maker_element(item)
 | 
						|
          super
 | 
						|
          @enclosure.setup_maker(item) if @enclosure
 | 
						|
          @source.setup_maker(item) if @source
 | 
						|
        end
 | 
						|
 | 
						|
        class Source < Element
 | 
						|
 | 
						|
          include RSS09
 | 
						|
 | 
						|
          [
 | 
						|
            ["url", "", true]
 | 
						|
          ].each do |name, uri, required|
 | 
						|
            install_get_attribute(name, uri, required)
 | 
						|
          end
 | 
						|
 | 
						|
          content_setup
 | 
						|
 | 
						|
          def initialize(*args)
 | 
						|
            if Utils.element_initialize_arguments?(args)
 | 
						|
              super
 | 
						|
            else
 | 
						|
              super()
 | 
						|
              self.url = args[0]
 | 
						|
              self.content = args[1]
 | 
						|
            end
 | 
						|
          end
 | 
						|
 | 
						|
          private
 | 
						|
          def maker_target(item)
 | 
						|
            item.source
 | 
						|
          end
 | 
						|
 | 
						|
          def setup_maker_attributes(source)
 | 
						|
            source.url = url
 | 
						|
            source.content = content
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        class Enclosure < Element
 | 
						|
 | 
						|
          include RSS09
 | 
						|
 | 
						|
          [
 | 
						|
            ["url", "", true],
 | 
						|
            ["length", "", true, :integer],
 | 
						|
            ["type", "", true],
 | 
						|
          ].each do |name, uri, required, type|
 | 
						|
            install_get_attribute(name, uri, required, type)
 | 
						|
          end
 | 
						|
 | 
						|
          def initialize(*args)
 | 
						|
            if Utils.element_initialize_arguments?(args)
 | 
						|
              super
 | 
						|
            else
 | 
						|
              super()
 | 
						|
              self.url = args[0]
 | 
						|
              self.length = args[1]
 | 
						|
              self.type = args[2]
 | 
						|
            end
 | 
						|
          end
 | 
						|
 | 
						|
          private
 | 
						|
          def maker_target(item)
 | 
						|
            item.enclosure
 | 
						|
          end
 | 
						|
 | 
						|
          def setup_maker_attributes(enclosure)
 | 
						|
            enclosure.url = url
 | 
						|
            enclosure.length = length
 | 
						|
            enclosure.type = type
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        class Category < Element
 | 
						|
 | 
						|
          include RSS09
 | 
						|
 | 
						|
          [
 | 
						|
            ["domain", "", false]
 | 
						|
          ].each do |name, uri, required|
 | 
						|
            install_get_attribute(name, uri, required)
 | 
						|
          end
 | 
						|
 | 
						|
          content_setup
 | 
						|
 | 
						|
          def initialize(*args)
 | 
						|
            if Utils.element_initialize_arguments?(args)
 | 
						|
              super
 | 
						|
            else
 | 
						|
              super()
 | 
						|
              self.domain = args[0]
 | 
						|
              self.content = args[1]
 | 
						|
            end
 | 
						|
          end
 | 
						|
 | 
						|
          private
 | 
						|
          def maker_target(item)
 | 
						|
            item.new_category
 | 
						|
          end
 | 
						|
 | 
						|
          def setup_maker_attributes(category)
 | 
						|
            category.domain = domain
 | 
						|
            category.content = content
 | 
						|
          end
 | 
						|
 | 
						|
        end
 | 
						|
 | 
						|
      end
 | 
						|
 | 
						|
      class TextInput < Element
 | 
						|
 | 
						|
        include RSS09
 | 
						|
 | 
						|
        %w(title description name link).each do |name|
 | 
						|
          install_text_element(name, "", nil)
 | 
						|
        end
 | 
						|
 | 
						|
        def initialize(*args)
 | 
						|
          if Utils.element_initialize_arguments?(args)
 | 
						|
            super
 | 
						|
          else
 | 
						|
            super()
 | 
						|
            self.title = args[0]
 | 
						|
            self.description = args[1]
 | 
						|
            self.name = args[2]
 | 
						|
            self.link = args[3]
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        private
 | 
						|
        def maker_target(maker)
 | 
						|
          maker.textinput
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
    end
 | 
						|
 | 
						|
  end
 | 
						|
 | 
						|
  RSS09::ELEMENTS.each do |name|
 | 
						|
    BaseListener.install_get_text_element("", name, name)
 | 
						|
  end
 | 
						|
 | 
						|
  module ListenerMixin
 | 
						|
    private
 | 
						|
    def initial_start_rss(tag_name, prefix, attrs, ns)
 | 
						|
      check_ns(tag_name, prefix, ns, "", false)
 | 
						|
 | 
						|
      @rss = Rss.new(attrs['version'], @version, @encoding, @standalone)
 | 
						|
      @rss.do_validate = @do_validate
 | 
						|
      @rss.xml_stylesheets = @xml_stylesheets
 | 
						|
      @last_element = @rss
 | 
						|
      pr = Proc.new do |text, tags|
 | 
						|
        @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate
 | 
						|
      end
 | 
						|
      @proc_stack.push(pr)
 | 
						|
    end
 | 
						|
 | 
						|
  end
 | 
						|
 | 
						|
end
 |