summaryrefslogtreecommitdiff
path: root/lib/rss/maker/base.rb
diff options
context:
space:
mode:
authorkou <kou@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-03-17 10:13:25 +0000
committerkou <kou@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-03-17 10:13:25 +0000
commit966a25465aab5c2972e6c453f631a15fc2223256 (patch)
tree847090e856c9901ab2cc19251c179b9b0985e65b /lib/rss/maker/base.rb
parent53cbab048452742b537ac8bccf494630d1c184c8 (diff)
* lib/rss, test/rss:
- supported Atom. - bumped version 0.1.6 to 0.1.7. * sample/rss/convert.rb: added new sample. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12087 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rss/maker/base.rb')
-rw-r--r--lib/rss/maker/base.rb710
1 files changed, 558 insertions, 152 deletions
diff --git a/lib/rss/maker/base.rb b/lib/rss/maker/base.rb
index 6d7dd557bf..ad47ff29cc 100644
--- a/lib/rss/maker/base.rb
+++ b/lib/rss/maker/base.rb
@@ -4,9 +4,7 @@ require 'rss/rss'
module RSS
module Maker
-
module Base
-
def self.append_features(klass)
super
@@ -46,28 +44,60 @@ module RSS
NEED_INITIALIZE_VARIABLES
end
- def self.def_array_element(name)
+ def self.def_array_element(name, plural=nil, klass=nil)
include Enumerable
extend Forwardable
- def_delegators("@\#{name}", :<<, :[], :[]=, :first, :last)
- def_delegators("@\#{name}", :push, :pop, :shift, :unshift)
- def_delegators("@\#{name}", :each, :size)
-
- add_need_initialize_variable(name, "[]")
+ plural ||= "\#{name}s"
+ klass ||= "self.class::\#{Utils.to_class_name(name)}"
+
+ def_delegators("@\#{plural}", :<<, :[], :[]=, :first, :last)
+ def_delegators("@\#{plural}", :push, :pop, :shift, :unshift)
+ def_delegators("@\#{plural}", :each, :size, :empty?, :clear)
+
+ add_need_initialize_variable(plural, "[]")
+
+ module_eval(<<-EOM, __FILE__, __LINE__ + 1)
+ def new_\#{name}
+ \#{name} = \#{klass}.new(@maker)
+ @\#{plural} << \#{name}
+ if block_given?
+ yield \#{name}
+ else
+ \#{name}
+ end
+ end
+ alias new_child new_\#{name}
+
+ def to_feed(*args)
+ @\#{plural}.each do |\#{name}|
+ \#{name}.to_feed(*args)
+ end
+ end
+
+ def replace(elements)
+ @\#{plural}.replace(elements.to_a)
+ end
+EOM
end
EOC
end
+ attr_reader :maker
def initialize(maker)
@maker = maker
+ @default_values_are_set = false
initialize_variables
end
def have_required_values?
- true
+ not_set_required_variables.empty?
end
-
+
+ def variable_is_set?
+ variables.any? {|var| not __send__(var).nil?}
+ end
+
private
def initialize_variables
self.class.need_initialize_variables.each do |variable_name, init_value|
@@ -75,16 +105,32 @@ module RSS
end
end
- def setup_other_elements(rss)
+ def setup_other_elements(feed, current=nil)
+ current ||= current_element(feed)
self.class.other_elements.each do |element|
- __send__("setup_#{element}", rss, current_element(rss))
+ __send__("setup_#{element}", feed, current)
end
end
- def current_element(rss)
- rss
+ def current_element(feed)
+ feed
end
-
+
+ def set_default_values(&block)
+ return yield if @default_values_are_set
+
+ begin
+ @default_values_are_set = true
+ _set_default_values(&block)
+ ensure
+ @default_values_are_set = false
+ end
+ end
+
+ def _set_default_values(&block)
+ yield
+ end
+
def setup_values(target)
set = false
if have_required_values?
@@ -102,6 +148,10 @@ module RSS
set
end
+ def set_parent(target, parent)
+ target.parent = parent if target.class.need_parent?
+ end
+
def variables
self.class.need_initialize_variables.find_all do |name, init|
"nil" == init
@@ -110,10 +160,6 @@ module RSS
end
end
- def variable_is_set?
- variables.find {|var| !__send__(var).nil?}
- end
-
def not_set_required_variables
required_variable_names.find_all do |var|
__send__(var).nil?
@@ -126,7 +172,92 @@ module RSS
end
true
end
-
+ end
+
+ module AtomPersonConstructBase
+ def self.append_features(klass)
+ super
+
+ klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1)
+ %w(name uri email).each do |element|
+ attr_accessor element
+ add_need_initialize_variable(element)
+ end
+EOC
+ end
+ end
+
+ module AtomTextConstructBase
+ module EnsureXMLContent
+ def ensure_xml_content(content)
+ xhtml_uri = ::RSS::Atom::XHTML_URI
+ unless content.is_a?(RSS::XML::Element) and
+ ["div", xhtml_uri] == [content.name, content.uri]
+ children = content
+ children = [children] unless content.is_a?(Array)
+ children = set_xhtml_uri_as_default_uri(children)
+ content = RSS::XML::Element.new("div", nil, xhtml_uri,
+ {"xmlns" => xhtml_uri},
+ children)
+ end
+ content
+ end
+
+ private
+ def set_xhtml_uri_as_default_uri(children)
+ children.collect do |child|
+ if child.is_a?(RSS::XML::Element) and
+ child.prefix.nil? and child.uri.nil?
+ RSS::XML::Element.new(child.name, nil, ::RSS::Atom::XHTML_URI,
+ child.attributes.dup,
+ set_xhtml_uri_as_default_uri(child.children))
+ else
+ child
+ end
+ end
+ end
+ end
+
+ def self.append_features(klass)
+ super
+
+ klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1)
+ include EnsureXMLContent
+
+ %w(type content xml_content).each do |element|
+ attr element, element != "xml_content"
+ add_need_initialize_variable(element)
+ end
+
+ def xml_content=(content)
+ @xml_content = ensure_xml_content(content)
+ end
+
+ alias_method(:xhtml, :xml_content)
+ alias_method(:xhtml=, :xml_content=)
+EOC
+ end
+ end
+
+ module SetupDefaultDate
+ private
+ def _set_default_values(&block)
+ keep = {
+ :date => date,
+ :dc_dates => dc_dates.to_a.dup,
+ }
+ _date = date
+ if _date and !dc_dates.any? {|dc_date| dc_date.value == _date}
+ dc_date = self.class::DublinCoreDates::Date.new(self)
+ dc_date.value = _date.dup
+ dc_dates.unshift(dc_date)
+ end
+ self.date ||= self.dc_date
+ super(&block)
+ ensure
+ date = keep[:date]
+ dc_dates.replace(keep[:dc_dates])
+ end
end
class RSSBase
@@ -143,8 +274,8 @@ module RSS
add_need_initialize_variable(element, "make_#{element}")
module_eval(<<-EOC, __FILE__, __LINE__)
private
- def setup_#{element}(rss)
- @#{element}.to_rss(rss)
+ def setup_#{element}(feed)
+ @#{element}.to_feed(feed)
end
def make_#{element}
@@ -153,12 +284,15 @@ module RSS
EOC
end
- attr_reader :rss_version
+ attr_reader :feed_version
+ alias_method(:rss_version, :feed_version)
attr_accessor :version, :encoding, :standalone
-
- def initialize(rss_version)
+
+ def initialize(feed_version)
super(self)
- @rss_version = rss_version
+ @feed_type = nil
+ @feed_subtype = nil
+ @feed_version = feed_version
@version = "1.0"
@encoding = "UTF-8"
@standalone = nil
@@ -167,19 +301,19 @@ EOC
def make
if block_given?
yield(self)
- to_rss
+ to_feed
else
nil
end
end
- def to_rss
- rss = make_rss
- setup_xml_stylesheets(rss)
- setup_elements(rss)
- setup_other_elements(rss)
- if rss.channel
- rss
+ def to_feed
+ feed = make_feed
+ setup_xml_stylesheets(feed)
+ setup_elements(feed)
+ setup_other_elements(feed)
+ if feed.valid?
+ feed
else
nil
end
@@ -190,25 +324,12 @@ EOC
def make_xml_stylesheets
XMLStyleSheets.new(self)
end
-
end
class XMLStyleSheets
include Base
- def_array_element("xml_stylesheets")
-
- def to_rss(rss)
- @xml_stylesheets.each do |xss|
- xss.to_rss(rss)
- end
- end
-
- def new_xml_stylesheet
- xss = XMLStyleSheet.new(@maker)
- @xml_stylesheets << xss
- xss
- end
+ def_array_element("xml_stylesheet", nil, "XMLStyleSheet")
class XMLStyleSheet
include Base
@@ -218,19 +339,15 @@ EOC
add_need_initialize_variable(attribute)
end
- def to_rss(rss)
+ def to_feed(feed)
xss = ::RSS::XMLStyleSheet.new
guess_type_if_need(xss)
set = setup_values(xss)
if set
- rss.xml_stylesheets << xss
+ feed.xml_stylesheets << xss
end
end
- def have_required_values?
- @href and @type
- end
-
private
def guess_type_if_need(xss)
if @type.nil?
@@ -238,20 +355,27 @@ EOC
@type = xss.type
end
end
+
+ def required_variable_names
+ %w(href type)
+ end
end
end
class ChannelBase
include Base
+ include SetupDefaultDate
- %w(cloud categories skipDays skipHours).each do |element|
+ %w(cloud categories skipDays skipHours links authors
+ contributors generator copyright description
+ title).each do |element|
attr_reader element
add_other_element(element)
add_need_initialize_variable(element, "make_#{element}")
module_eval(<<-EOC, __FILE__, __LINE__)
private
- def setup_#{element}(rss, current)
- @#{element}.to_rss(rss, current)
+ def setup_#{element}(feed, current)
+ @#{element}.to_feed(feed, current)
end
def make_#{element}
@@ -260,34 +384,102 @@ EOC
EOC
end
- %w(about title link description language copyright
+ %w(id about language
managingEditor webMaster rating docs date
- lastBuildDate generator ttl).each do |element|
+ lastBuildDate ttl).each do |element|
attr_accessor element
add_need_initialize_variable(element)
end
- alias_method(:pubDate, :date)
- alias_method(:pubDate=, :date=)
+ def pubDate
+ date
+ end
+
+ def pubDate=(date)
+ self.date = date
+ end
+
+ def updated
+ date
+ end
+
+ def updated=(date)
+ self.date = date
+ end
+
+ def link
+ _link = links.first
+ _link ? _link.href : nil
+ end
+
+ def link=(href)
+ _link = links.first || links.new_link
+ _link.rel = "self"
+ _link.href = href
+ end
+
+ def author
+ _author = authors.first
+ _author ? _author.name : nil
+ end
+
+ def author=(name)
+ _author = authors.first || authors.new_author
+ _author.name = name
+ end
+
+ def contributor
+ _contributor = contributors.first
+ _contributor ? _contributor.name : nil
+ end
+
+ def contributor=(name)
+ _contributor = contributors.first || contributors.new_contributor
+ _contributor.name = name
+ end
+
+ def generator=(content)
+ @generator.content = content
+ end
+
+ def copyright=(content)
+ @copyright.content = content
+ end
+
+ alias_method(:rights, :copyright)
+ alias_method(:rights=, :copyright=)
+
+ def description=(content)
+ @description.content = content
+ end
+
+ alias_method(:subtitle, :description)
+ alias_method(:subtitle=, :description=)
+
+ def title=(content)
+ @title.content = content
+ end
- def current_element(rss)
- rss.channel
+ def icon
+ image_favicon.about
+ end
+
+ def icon=(url)
+ image_favicon.about = url
+ end
+
+ def logo
+ maker.image.url
+ end
+
+ def logo=(url)
+ maker.image.url = url
end
class SkipDaysBase
include Base
- def_array_element("days")
-
- def new_day
- day = self.class::Day.new(@maker)
- @days << day
- day
- end
-
- def current_element(rss)
- rss.channel.skipDays
- end
+ def_array_element("day")
class DayBase
include Base
@@ -296,28 +488,13 @@ EOC
attr_accessor element
add_need_initialize_variable(element)
end
-
- def current_element(rss)
- rss.channel.skipDays.last
- end
-
end
end
class SkipHoursBase
include Base
- def_array_element("hours")
-
- def new_hour
- hour = self.class::Hour.new(@maker)
- @hours << hour
- hour
- end
-
- def current_element(rss)
- rss.channel.skipHours
- end
+ def_array_element("hour")
class HourBase
include Base
@@ -326,11 +503,6 @@ EOC
attr_accessor element
add_need_initialize_variable(element)
end
-
- def current_element(rss)
- rss.channel.skipHours.last
- end
-
end
end
@@ -341,33 +513,88 @@ EOC
attr_accessor element
add_need_initialize_variable(element)
end
-
- def current_element(rss)
- rss.channel.cloud
- end
-
end
class CategoriesBase
include Base
-
- def_array_element("categories")
- def new_category
- category = self.class::Category.new(@maker)
- @categories << category
- category
- end
+ def_array_element("category", "categories")
class CategoryBase
include Base
- %w(domain content).each do |element|
+ %w(domain content label).each do |element|
attr_accessor element
add_need_initialize_variable(element)
end
+
+ alias_method(:term, :domain)
+ alias_method(:term=, :domain=)
+ alias_method(:scheme, :content)
+ alias_method(:scheme=, :content=)
end
end
+
+ class LinksBase
+ include Base
+
+ def_array_element("link")
+
+ class LinkBase
+ include Base
+
+ %w(href rel type hreflang title length).each do |element|
+ attr_accessor element
+ add_need_initialize_variable(element)
+ end
+ end
+ end
+
+ class AuthorsBase
+ include Base
+
+ def_array_element("author")
+
+ class AuthorBase
+ include Base
+ include AtomPersonConstructBase
+ end
+ end
+
+ class ContributorsBase
+ include Base
+
+ def_array_element("contributor")
+
+ class ContributorBase
+ include Base
+ include AtomPersonConstructBase
+ end
+ end
+
+ class GeneratorBase
+ include Base
+
+ %w(uri version content).each do |element|
+ attr_accessor element
+ add_need_initialize_variable(element)
+ end
+ end
+
+ class CopyrightBase
+ include Base
+ include AtomTextConstructBase
+ end
+
+ class DescriptionBase
+ include Base
+ include AtomTextConstructBase
+ end
+
+ class TitleBase
+ include Base
+ include AtomTextConstructBase
+ end
end
class ImageBase
@@ -377,21 +604,17 @@ EOC
attr_accessor element
add_need_initialize_variable(element)
end
-
+
def link
@maker.channel.link
end
-
- def current_element(rss)
- rss.image
- end
end
class ItemsBase
include Base
- def_array_element("items")
-
+ def_array_element("item")
+
attr_accessor :do_sort, :max_size
def initialize(maker)
@@ -407,17 +630,7 @@ EOC
sort_if_need[0..@max_size]
end
end
-
- def current_element(rss)
- rss.items
- end
- def new_item
- item = self.class::Item.new(@maker)
- @items << item
- item
- end
-
private
def sort_if_need
if @do_sort.respond_to?(:call)
@@ -435,15 +648,17 @@ EOC
class ItemBase
include Base
-
- %w(guid enclosure source categories).each do |element|
+ include SetupDefaultDate
+
+ %w(guid enclosure source categories authors links
+ contributors rights description content title).each do |element|
attr_reader element
add_other_element(element)
add_need_initialize_variable(element, "make_#{element}")
module_eval(<<-EOC, __FILE__, __LINE__)
private
- def setup_#{element}(rss, current)
- @#{element}.to_rss(rss, current)
+ def setup_#{element}(feed, current)
+ @#{element}.to_feed(feed, current)
end
def make_#{element}
@@ -451,30 +666,77 @@ EOC
end
EOC
end
-
- %w(title link description date author comments).each do |element|
+
+ %w(date comments id published).each do |element|
attr_accessor element
add_need_initialize_variable(element)
end
- alias_method(:pubDate, :date)
- alias_method(:pubDate=, :date=)
+ def pubDate
+ date
+ end
+
+ def pubDate=(date)
+ self.date = date
+ end
+
+ def updated
+ date
+ end
+
+ def updated=(date)
+ self.date = date
+ end
+
+ def author
+ _link = authors.first
+ _link ? _author.name : nil
+ end
+
+ def author=(name)
+ _author = authors.first || authors.new_author
+ _author.name = name
+ end
+
+ def link
+ _link = links.first
+ _link ? _link.href : nil
+ end
+
+ def link=(href)
+ _link = links.first || links.new_link
+ _link.rel = "alternate"
+ _link.href = href
+ end
+
+ def rights=(content)
+ @rights.content = content
+ end
+
+ def description=(content)
+ @description.content = content
+ end
+
+ alias_method(:summary, :description)
+ alias_method(:summary=, :description=)
+
+ def title=(content)
+ @title.content = content
+ end
def <=>(other)
- if date and other.date
- date <=> other.date
- elsif date
+ _date = date || dc_date
+ _other_date = other.date || other.dc_date
+ if _date and _other_date
+ _date <=> _other_date
+ elsif _date
1
- elsif other.date
+ elsif _other_date
-1
else
0
end
end
-
- def current_element(rss)
- rss.items.last
- end
class GuidBase
include Base
@@ -484,7 +746,7 @@ EOC
add_need_initialize_variable(element)
end
end
-
+
class EnclosureBase
include Base
@@ -493,18 +755,168 @@ EOC
add_need_initialize_variable(element)
end
end
-
+
class SourceBase
include Base
- %w(url content).each do |element|
+ %w(authors categories contributors generator icon
+ links logo rights subtitle title).each do |element|
+ attr_reader element
+ add_other_element(element)
+ add_need_initialize_variable(element, "make_#{element}")
+ module_eval(<<-EOC, __FILE__, __LINE__)
+ private
+ def setup_#{element}(feed, current)
+ @#{element}.to_feed(feed, current)
+ end
+
+ def make_#{element}
+ self.class::#{Utils.to_class_name(element)}.new(@maker)
+ end
+ EOC
+ end
+
+ %w(id content date).each do |element|
attr_accessor element
add_need_initialize_variable(element)
end
+
+ def url
+ link = links.first
+ link ? link.href : nil
+ end
+
+ def url=(value)
+ link = links.first || links.new_link
+ link.href = value
+ end
+
+ def updated
+ date
+ end
+
+ def updated=(date)
+ self.date = date
+ end
+
+ private
+ AuthorsBase = ChannelBase::AuthorsBase
+ CategoriesBase = ChannelBase::CategoriesBase
+ ContributorsBase = ChannelBase::ContributorsBase
+ GeneratorBase = ChannelBase::GeneratorBase
+
+ class IconBase
+ include Base
+
+ %w(url).each do |element|
+ attr_accessor element
+ add_need_initialize_variable(element)
+ end
+ end
+
+ LinksBase = ChannelBase::LinksBase
+
+ class LogoBase
+ include Base
+
+ %w(uri).each do |element|
+ attr_accessor element
+ add_need_initialize_variable(element)
+ end
+ end
+
+ class RightsBase
+ include Base
+ include AtomTextConstructBase
+ end
+
+ class SubtitleBase
+ include Base
+ include AtomTextConstructBase
+ end
+
+ class TitleBase
+ include Base
+ include AtomTextConstructBase
+ end
end
-
+
CategoriesBase = ChannelBase::CategoriesBase
-
+ AuthorsBase = ChannelBase::AuthorsBase
+ LinksBase = ChannelBase::LinksBase
+ ContributorsBase = ChannelBase::ContributorsBase
+
+ class RightsBase
+ include Base
+ include AtomTextConstructBase
+ end
+
+ class DescriptionBase
+ include Base
+ include AtomTextConstructBase
+ end
+
+ class ContentBase
+ include Base
+ include AtomTextConstructBase::EnsureXMLContent
+
+ %w(type src content xml_content).each do |element|
+ attr element, element != "xml_content"
+ add_need_initialize_variable(element)
+ end
+
+ def xml_content=(content)
+ content = ensure_xml_content(content) if inline_xhtml?
+ @xml_content = content
+ end
+
+ alias_method(:xhtml, :xml_content)
+ alias_method(:xhtml=, :xml_content=)
+
+ alias_method(:xml, :xml_content)
+ alias_method(:xml=, :xml_content=)
+
+ private
+ def inline_text?
+ [nil, "text", "html"].include?(@type)
+ end
+
+ def inline_html?
+ @type == "html"
+ end
+
+ def inline_xhtml?
+ @type == "xhtml"
+ end
+
+ def inline_other?
+ !out_of_line? and ![nil, "text", "html", "xhtml"].include?(@type)
+ end
+
+ def inline_other_text?
+ return false if @type.nil? or out_of_line?
+ /\Atext\//i.match(@type) ? true : false
+ end
+
+ def inline_other_xml?
+ return false if @type.nil? or out_of_line?
+ /[\+\/]xml\z/i.match(@type) ? true : false
+ end
+
+ def inline_other_base64?
+ return false if @type.nil? or out_of_line?
+ @type.include?("/") and !inline_other_text? and !inline_other_xml?
+ end
+
+ def out_of_line?
+ not @src.nil? and @content.nil?
+ end
+ end
+
+ class TitleBase
+ include Base
+ include AtomTextConstructBase
+ end
end
end
@@ -515,12 +927,6 @@ EOC
attr_accessor element
add_need_initialize_variable(element)
end
-
- def current_element(rss)
- rss.textinput
- end
-
end
-
end
end