* lib/rss.rb, lib/rss/, test/rss/, sample/rss/: merged from trunk.

- 0.1.6 -> 2.0.0.
  - fixed image module URI. Thanks to Dmitry Borodaenko.
  - supported Atom.
  - supported ITunes module.
  - supported Slash module.

* NEWS: added an entry for RSS Parser.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@13747 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
kou 2007-10-21 12:19:43 +00:00
parent 754b1fac44
commit 57a639494a
81 changed files with 11826 additions and 1691 deletions

View file

@ -1,3 +1,14 @@
Sun Oct 21 21:16:43 2007 Kouhei Sutou <kou@cozmixng.org>
* lib/rss.rb, lib/rss/, test/rss/, sample/rss/: merged from trunk.
- 0.1.6 -> 2.0.0.
- fixed image module URI. Thanks to Dmitry Borodaenko.
- supported Atom.
- supported ITunes module.
- supported Slash module.
* NEWS: added an entry for RSS Parser.
Thu Oct 18 10:57:06 2007 Tanaka Akira <akr@fsij.org> Thu Oct 18 10:57:06 2007 Tanaka Akira <akr@fsij.org>
* ruby.h (RCLASS_IV_TBL): defined. * ruby.h (RCLASS_IV_TBL): defined.

View file

@ -1,4 +1,4 @@
# Copyright (c) 2003-2005 Kouhei Sutou. You can redistribute it and/or # Copyright (c) 2003-2007 Kouhei Sutou. You can redistribute it and/or
# modify it under the same terms as Ruby. # modify it under the same terms as Ruby.
# #
# Author:: Kouhei Sutou <kou@cozmixng.org> # Author:: Kouhei Sutou <kou@cozmixng.org>
@ -6,11 +6,14 @@
require 'rss/1.0' require 'rss/1.0'
require 'rss/2.0' require 'rss/2.0'
require 'rss/atom'
require 'rss/content' require 'rss/content'
require 'rss/dublincore' require 'rss/dublincore'
require 'rss/image' require 'rss/image'
require 'rss/itunes'
require 'rss/slash'
require 'rss/syndication' require 'rss/syndication'
#require 'rss/taxonomy' require 'rss/taxonomy'
require 'rss/trackback' require 'rss/trackback'
require "rss/maker" require "rss/maker"

499
lib/rss/.gdbinit Normal file
View file

@ -0,0 +1,499 @@
define rp
if (VALUE)$arg0 & RUBY_FIXNUM_FLAG
printf "FIXNUM: %d\n", $arg0 >> 1
else
if ((VALUE)$arg0 & ~(~(VALUE)0<<RUBY_SPECIAL_SHIFT)) == RUBY_SYMBOL_FLAG
printf "SYMBOL(%d)\n", $arg0 >> RUBY_SPECIAL_SHIFT
else
if $arg0 == RUBY_Qfalse
echo false\n
else
if $arg0 == RUBY_Qtrue
echo true\n
else
if $arg0 == RUBY_Qnil
echo nil\n
else
if $arg0 == RUBY_Qundef
echo undef\n
else
if (VALUE)$arg0 & RUBY_IMMEDIATE_MASK
echo immediate\n
else
set $flags = ((struct RBasic*)$arg0)->flags
if ($flags & RUBY_T_MASK) == RUBY_T_NONE
printf "T_NONE: "
print (struct RBasic *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_NIL
printf "T_NIL: "
print (struct RBasic *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_OBJECT
printf "T_OBJECT: "
print (struct RObject *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_CLASS
printf "T_CLASS: "
print (struct RClass *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_ICLASS
printf "T_ICLASS: "
print (struct RClass *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_MODULE
printf "T_MODULE: "
print (struct RClass *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_FLOAT
printf "T_FLOAT: %.16g ", (((struct RFloat*)$arg0)->value)
print (struct RFloat *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_STRING
printf "T_STRING: "
set print address off
output (char *)(($flags & RUBY_FL_USER1) ? \
((struct RString*)$arg0)->as.heap.ptr : \
((struct RString*)$arg0)->as.ary)
set print address on
printf " encoding:%d ", ($flags & (RUBY_FL_USER8|RUBY_FL_USER9|RUBY_FL_USER10|RUBY_FL_USER11)) >> RUBY_ENCODING_SHIFT
if ($flags & (RUBY_FL_USER12|RUBY_FL_USER13)) == 0
printf "coderange:unknown "
else
if ($flags & (RUBY_FL_USER12|RUBY_FL_USER13)) == RUBY_FL_USER12
printf "coderange:single "
else
if ($flags & (RUBY_FL_USER12|RUBY_FL_USER13)) == RUBY_FL_USER13
printf "coderange:single "
else
printf "coderange:broken "
end
end
end
print (struct RString *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_REGEXP
printf "T_REGEXP: "
set print address off
output ((struct RRegexp*)$arg0)->str
set print address on
printf " "
print (struct RRegexp *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_ARRAY
printf "T_ARRAY: len=%d ", ((struct RArray*)$arg0)->len
print (struct RArray *)$arg0
x/xw ((struct RArray*)$arg0)->ptr
else
if ($flags & RUBY_T_MASK) == RUBY_T_FIXNUM
printf "T_FIXNUM: "
print (struct RBasic *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_HASH
printf "T_HASH: ",
if ((struct RHash *)$arg0)->ntbl
printf "len=%d ", ((struct RHash *)$arg0)->ntbl->num_entries
end
print (struct RHash *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_STRUCT
printf "T_STRUCT: len=%d ", \
(($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \
($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) >> (RUBY_FL_USHIFT+1) : \
((struct RStruct *)$arg0)->as.heap.len)
print (struct RStruct *)$arg0
x/xw (($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \
((struct RStruct *)$arg0)->as.ary : \
((struct RStruct *)$arg0)->as.heap.len)
else
if ($flags & RUBY_T_MASK) == RUBY_T_BIGNUM
printf "T_BIGNUM: sign=%d len=%d ", \
(($flags & RUBY_FL_USER1) != 0), \
(($flags & RUBY_FL_USER2) ? \
($flags & (RUBY_FL_USER5|RUBY_FL_USER4|RUBY_FL_USER3)) >> (RUBY_FL_USHIFT+3) : \
((struct RBignum*)$arg0)->as.heap.len)
if $flags & RUBY_FL_USER2
printf "(embed) "
end
print (struct RBignum *)$arg0
x/xw (($flags & RUBY_FL_USER2) ? \
((struct RBignum*)$arg0)->as.ary : \
((struct RBignum*)$arg0)->as.heap.digits)
else
if ($flags & RUBY_T_MASK) == RUBY_T_FILE
printf "T_FILE: "
print (struct RFile *)$arg0
output *((struct RFile *)$arg0)->fptr
printf "\n"
else
if ($flags & RUBY_T_MASK) == RUBY_T_TRUE
printf "T_TRUE: "
print (struct RBasic *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_FALSE
printf "T_FALSE: "
print (struct RBasic *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_DATA
printf "T_DATA: "
print (struct RData *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_MATCH
printf "T_MATCH: "
print (struct RMatch *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_SYMBOL
printf "T_SYMBOL: "
print (struct RBasic *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_VALUES
printf "T_VALUES: "
print (struct RValues *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_BLOCK
printf "T_BLOCK: "
print (struct RBasic *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_UNDEF
printf "T_UNDEF: "
print (struct RBasic *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_NODE
printf "T_NODE("
output (enum node_type)(($flags&RUBY_NODE_TYPEMASK)>>RUBY_NODE_TYPESHIFT)
printf "): "
print *(NODE *)$arg0
else
printf "unknown: "
print (struct RBasic *)$arg0
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
document rp
Print a Ruby's VALUE.
end
define nd_type
print (enum node_type)((((NODE*)$arg0)->flags&RUBY_NODE_TYPEMASK)>>RUBY_NODE_TYPESHIFT)
end
document nd_type
Print a Ruby' node type.
end
define nd_file
print ((NODE*)$arg0)->nd_file
end
document nd_file
Print the source file name of a node.
end
define nd_line
print ((unsigned int)((((NODE*)$arg0)->flags>>RUBY_NODE_LSHIFT)&RUBY_NODE_LMASK))
end
document nd_line
Print the source line number of a node.
end
# Print members of ruby node.
define nd_head
printf "u1.node: "
rp $arg0.u1.node
end
define nd_alen
printf "u2.argc: "
p $arg0.u2.argc
end
define nd_next
printf "u3.node: "
rp $arg0.u3.node
end
define nd_cond
printf "u1.node: "
rp $arg0.u1.node
end
define nd_body
printf "u2.node: "
rp $arg0.u2.node
end
define nd_else
printf "u3.node: "
rp $arg0.u3.node
end
define nd_orig
printf "u3.value: "
rp $arg0.u3.value
end
define nd_resq
printf "u2.node: "
rp $arg0.u2.node
end
define nd_ensr
printf "u3.node: "
rp $arg0.u3.node
end
define nd_1st
printf "u1.node: "
rp $arg0.u1.node
end
define nd_2nd
printf "u2.node: "
rp $arg0.u2.node
end
define nd_stts
printf "u1.node: "
rp $arg0.u1.node
end
define nd_entry
printf "u3.entry: "
p $arg0.u3.entry
end
define nd_vid
printf "u1.id: "
p $arg0.u1.id
end
define nd_cflag
printf "u2.id: "
p $arg0.u2.id
end
define nd_cval
printf "u3.value: "
rp $arg0.u3.value
end
define nd_cnt
printf "u3.cnt: "
p $arg0.u3.cnt
end
define nd_tbl
printf "u1.tbl: "
p $arg0.u1.tbl
end
define nd_var
printf "u1.node: "
rp $arg0.u1.node
end
define nd_ibdy
printf "u2.node: "
rp $arg0.u2.node
end
define nd_iter
printf "u3.node: "
rp $arg0.u3.node
end
define nd_value
printf "u2.node: "
rp $arg0.u2.node
end
define nd_aid
printf "u3.id: "
p $arg0.u3.id
end
define nd_lit
printf "u1.value: "
rp $arg0.u1.value
end
define nd_frml
printf "u1.node: "
rp $arg0.u1.node
end
define nd_rest
printf "u2.argc: "
p $arg0.u2.argc
end
define nd_opt
printf "u1.node: "
rp $arg0.u1.node
end
define nd_recv
printf "u1.node: "
rp $arg0.u1.node
end
define nd_mid
printf "u2.id: "
p $arg0.u2.id
end
define nd_args
printf "u3.node: "
rp $arg0.u3.node
end
define nd_noex
printf "u1.id: "
p $arg0.u1.id
end
define nd_defn
printf "u3.node: "
rp $arg0.u3.node
end
define nd_old
printf "u1.id: "
p $arg0.u1.id
end
define nd_new
printf "u2.id: "
p $arg0.u2.id
end
define nd_cfnc
printf "u1.cfunc: "
p $arg0.u1.cfunc
end
define nd_argc
printf "u2.argc: "
p $arg0.u2.argc
end
define nd_cname
printf "u1.id: "
p $arg0.u1.id
end
define nd_super
printf "u3.node: "
rp $arg0.u3.node
end
define nd_modl
printf "u1.id: "
p $arg0.u1.id
end
define nd_clss
printf "u1.value: "
rp $arg0.u1.value
end
define nd_beg
printf "u1.node: "
rp $arg0.u1.node
end
define nd_end
printf "u2.node: "
rp $arg0.u2.node
end
define nd_state
printf "u3.state: "
p $arg0.u3.state
end
define nd_rval
printf "u2.value: "
rp $arg0.u2.value
end
define nd_nth
printf "u2.argc: "
p $arg0.u2.argc
end
define nd_tag
printf "u1.id: "
p $arg0.u1.id
end
define nd_tval
printf "u2.value: "
rp $arg0.u2.value
end
define rb_p
call rb_p($arg0)
end
define rb_id2name
call rb_id2name($arg0)
end
define rb_classname
call classname($arg0)
rb_p $
print *(struct RClass*)$arg0
end
define rb_backtrace
call rb_backtrace()
end

View file

@ -22,10 +22,13 @@ module RSS
install_have_child_element(name, "", nil) install_have_child_element(name, "", nil)
end end
attr_accessor :rss_version, :version, :encoding, :standalone attr_writer :feed_version
alias_method(:rss_version, :feed_version)
alias_method(:rss_version=, :feed_version=)
def initialize(rss_version, version=nil, encoding=nil, standalone=nil) def initialize(feed_version, version=nil, encoding=nil, standalone=nil)
super super
@feed_type = "rss"
end end
def items def items
@ -57,12 +60,14 @@ module RSS
items.each do |item| items.each do |item|
item.setup_maker(maker.items) item.setup_maker(maker.items)
end end
image.setup_maker(maker) if image
textinput.setup_maker(maker) if textinput
end end
private private
def _attrs def _attrs
[ [
["version", true, "rss_version"], ["version", true, "feed_version"],
] ]
end end
@ -400,21 +405,22 @@ module RSS
end end
RSS09::ELEMENTS.each do |name| RSS09::ELEMENTS.each do |name|
BaseListener.install_get_text_element("", name, "#{name}=") BaseListener.install_get_text_element("", name, name)
end end
module ListenerMixin module ListenerMixin
private private
def start_rss(tag_name, prefix, attrs, ns) def initial_start_rss(tag_name, prefix, attrs, ns)
check_ns(tag_name, prefix, ns, "") check_ns(tag_name, prefix, ns, "")
@rss = Rss.new(attrs['version'], @version, @encoding, @standalone) @rss = Rss.new(attrs['version'], @version, @encoding, @standalone)
@rss.do_validate = @do_validate @rss.do_validate = @do_validate
@rss.xml_stylesheets = @xml_stylesheets @rss.xml_stylesheets = @xml_stylesheets
@last_element = @rss @last_element = @rss
@proc_stack.push Proc.new { |text, tags| pr = Proc.new do |text, tags|
@rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate
} end
@proc_stack.push(pr)
end end
end end

View file

@ -45,10 +45,10 @@ module RSS
__send__("install_have_#{type}_element", tag, ::RSS::URI, occurs) __send__("install_have_#{type}_element", tag, ::RSS::URI, occurs)
end end
attr_accessor :rss_version, :version, :encoding, :standalone alias_method(:rss_version, :feed_version)
def initialize(version=nil, encoding=nil, standalone=nil) def initialize(version=nil, encoding=nil, standalone=nil)
super('1.0', version, encoding, standalone) super('1.0', version, encoding, standalone)
@feed_type = "rss"
end end
def full_name def full_name
@ -430,21 +430,22 @@ module RSS
end end
RSS10::ELEMENTS.each do |name| RSS10::ELEMENTS.each do |name|
BaseListener.install_get_text_element(URI, name, "#{name}=") BaseListener.install_get_text_element(URI, name, name)
end end
module ListenerMixin module ListenerMixin
private private
def start_RDF(tag_name, prefix, attrs, ns) def initial_start_RDF(tag_name, prefix, attrs, ns)
check_ns(tag_name, prefix, ns, RDF::URI) check_ns(tag_name, prefix, ns, RDF::URI)
@rss = RDF.new(@version, @encoding, @standalone) @rss = RDF.new(@version, @encoding, @standalone)
@rss.do_validate = @do_validate @rss.do_validate = @do_validate
@rss.xml_stylesheets = @xml_stylesheets @rss.xml_stylesheets = @xml_stylesheets
@last_element = @rss @last_element = @rss
@proc_stack.push Proc.new { |text, tags| pr = Proc.new do |text, tags|
@rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate
} end
@proc_stack.push(pr)
end end
end end

View file

@ -105,7 +105,7 @@ module RSS
end end
RSS09::ELEMENTS.each do |name| RSS09::ELEMENTS.each do |name|
BaseListener.install_get_text_element("", name, "#{name}=") BaseListener.install_get_text_element("", name, name)
end end
end end

749
lib/rss/atom.rb Normal file
View file

@ -0,0 +1,749 @@
require 'base64'
require 'rss/parser'
module RSS
module Atom
URI = "http://www.w3.org/2005/Atom"
XHTML_URI = "http://www.w3.org/1999/xhtml"
module CommonModel
NSPOOL = {}
ELEMENTS = []
def self.append_features(klass)
super
klass.install_must_call_validator("atom", URI)
[
["lang", :xml],
["base", :xml],
].each do |name, uri, required|
klass.install_get_attribute(name, uri, required, [nil, :inherit])
end
klass.class_eval do
class << self
def required_uri
URI
end
def need_parent?
true
end
end
end
end
end
module ContentModel
module ClassMethods
def content_type
@content_type ||= nil
end
end
class << self
def append_features(klass)
super
klass.extend(ClassMethods)
klass.content_setup(klass.content_type, klass.tag_name)
end
end
def maker_target(target)
target
end
private
def setup_maker_element_writer
"#{self.class.name.split(/::/).last.downcase}="
end
def setup_maker_element(target)
target.__send__(setup_maker_element_writer, content)
super
end
end
module URIContentModel
class << self
def append_features(klass)
super
klass.class_eval do
@content_type = [nil, :uri]
include(ContentModel)
end
end
end
end
module TextConstruct
def self.append_features(klass)
super
klass.class_eval do
[
["type", ""],
].each do |name, uri, required|
install_get_attribute(name, uri, required, :text_type)
end
content_setup
add_need_initialize_variable("xhtml")
class << self
def xml_getter
"xhtml"
end
def xml_setter
"xhtml="
end
end
end
end
attr_writer :xhtml
def xhtml
return @xhtml if @xhtml.nil?
if @xhtml.is_a?(XML::Element) and
[@xhtml.name, @xhtml.uri] == ["div", XHTML_URI]
return @xhtml
end
children = @xhtml
children = [children] unless children.is_a?(Array)
XML::Element.new("div", nil, XHTML_URI,
{"xmlns" => XHTML_URI}, children)
end
def have_xml_content?
@type == "xhtml"
end
def atom_validate(ignore_unknown_element, tags, uri)
if have_xml_content?
if @xhtml.nil?
raise MissingTagError.new("div", tag_name)
end
unless [@xhtml.name, @xhtml.uri] == ["div", XHTML_URI]
raise NotExpectedTagError.new(@xhtml.name, @xhtml.uri, tag_name)
end
end
end
private
def maker_target(target)
target.__send__(self.class.name.split(/::/).last.downcase) {|x| x}
end
def setup_maker_attributes(target)
target.type = type
target.content = content
target.xml_content = @xhtml
end
end
module PersonConstruct
def self.append_features(klass)
super
klass.class_eval do
[
["name", nil],
["uri", "?"],
["email", "?"],
].each do |tag, occurs|
install_have_attribute_element(tag, URI, occurs, nil, :content)
end
end
end
def maker_target(target)
target.__send__("new_#{self.class.name.split(/::/).last.downcase}")
end
class Name < RSS::Element
include CommonModel
include ContentModel
end
class Uri < RSS::Element
include CommonModel
include URIContentModel
end
class Email < RSS::Element
include CommonModel
include ContentModel
end
end
module DateConstruct
def self.append_features(klass)
super
klass.class_eval do
@content_type = :w3cdtf
include(ContentModel)
end
end
def atom_validate(ignore_unknown_element, tags, uri)
raise NotAvailableValueError.new(tag_name, "") if content.nil?
end
end
module DuplicateLinkChecker
def validate_duplicate_links(links)
link_infos = {}
links.each do |link|
rel = link.rel || "alternate"
next unless rel == "alternate"
key = [link.hreflang, link.type]
if link_infos.has_key?(key)
raise TooMuchTagError.new("link", tag_name)
end
link_infos[key] = true
end
end
end
class Feed < RSS::Element
include RootElementMixin
include CommonModel
include DuplicateLinkChecker
install_ns('', URI)
[
["author", "*", :children],
["category", "*", :children, "categories"],
["contributor", "*", :children],
["generator", "?"],
["icon", "?", nil, :content],
["id", nil, nil, :content],
["link", "*", :children],
["logo", "?"],
["rights", "?"],
["subtitle", "?", nil, :content],
["title", nil, nil, :content],
["updated", nil, nil, :content],
["entry", "*", :children, "entries"],
].each do |tag, occurs, type, *args|
type ||= :child
__send__("install_have_#{type}_element",
tag, URI, occurs, tag, *args)
end
def initialize(version=nil, encoding=nil, standalone=nil)
super("1.0", version, encoding, standalone)
@feed_type = "atom"
@feed_subtype = "feed"
end
alias_method :items, :entries
def have_author?
authors.any? {|author| !author.to_s.empty?} or
entries.any? {|entry| entry.have_author?(false)}
end
private
def atom_validate(ignore_unknown_element, tags, uri)
unless have_author?
raise MissingTagError.new("author", tag_name)
end
validate_duplicate_links(links)
end
def have_required_elements?
super and have_author?
end
def maker_target(maker)
maker.channel
end
def setup_maker_element(channel)
prev_dc_dates = channel.dc_dates.to_a.dup
super
channel.about = id.content if id
channel.dc_dates.replace(prev_dc_dates)
end
def setup_maker_elements(channel)
super
items = channel.maker.items
entries.each do |entry|
entry.setup_maker(items)
end
end
class Author < RSS::Element
include CommonModel
include PersonConstruct
end
class Category < RSS::Element
include CommonModel
[
["term", "", true],
["scheme", "", false, [nil, :uri]],
["label", ""],
].each do |name, uri, required, type|
install_get_attribute(name, uri, required, type)
end
private
def maker_target(target)
target.new_category
end
end
class Contributor < RSS::Element
include CommonModel
include PersonConstruct
end
class Generator < RSS::Element
include CommonModel
include ContentModel
[
["uri", "", false, [nil, :uri]],
["version", ""],
].each do |name, uri, required, type|
install_get_attribute(name, uri, required, type)
end
private
def setup_maker_attributes(target)
target.generator do |generator|
generator.uri = uri if uri
generator.version = version if version
end
end
end
class Icon < RSS::Element
include CommonModel
include URIContentModel
end
class Id < RSS::Element
include CommonModel
include URIContentModel
end
class Link < RSS::Element
include CommonModel
[
["href", "", true, [nil, :uri]],
["rel", ""],
["type", ""],
["hreflang", ""],
["title", ""],
["length", ""],
].each do |name, uri, required, type|
install_get_attribute(name, uri, required, type)
end
private
def maker_target(target)
target.new_link
end
end
class Logo < RSS::Element
include CommonModel
include URIContentModel
def maker_target(target)
target.maker.image
end
private
def setup_maker_element_writer
"url="
end
end
class Rights < RSS::Element
include CommonModel
include TextConstruct
end
class Subtitle < RSS::Element
include CommonModel
include TextConstruct
end
class Title < RSS::Element
include CommonModel
include TextConstruct
end
class Updated < RSS::Element
include CommonModel
include DateConstruct
end
class Entry < RSS::Element
include CommonModel
include DuplicateLinkChecker
[
["author", "*", :children],
["category", "*", :children, "categories"],
["content", "?", :child],
["contributor", "*", :children],
["id", nil, nil, :content],
["link", "*", :children],
["published", "?", :child, :content],
["rights", "?", :child],
["source", "?"],
["summary", "?", :child],
["title", nil],
["updated", nil, :child, :content],
].each do |tag, occurs, type, *args|
type ||= :attribute
__send__("install_have_#{type}_element",
tag, URI, occurs, tag, *args)
end
def have_author?(check_parent=true)
authors.any? {|author| !author.to_s.empty?} or
(check_parent and @parent and @parent.have_author?) or
(source and source.have_author?)
end
private
def atom_validate(ignore_unknown_element, tags, uri)
unless have_author?
raise MissingTagError.new("author", tag_name)
end
validate_duplicate_links(links)
end
def have_required_elements?
super and have_author?
end
def maker_target(items)
if items.respond_to?("items")
# For backward compatibility
items = items.items
end
items.new_item
end
Author = Feed::Author
Category = Feed::Category
class Content < RSS::Element
include CommonModel
class << self
def xml_setter
"xml="
end
def xml_getter
"xml"
end
end
[
["type", ""],
["src", "", false, [nil, :uri]],
].each do |name, uri, required, type|
install_get_attribute(name, uri, required, type)
end
content_setup
add_need_initialize_variable("xml")
attr_writer :xml
def have_xml_content?
inline_xhtml? or inline_other_xml?
end
def xml
return @xml unless inline_xhtml?
return @xml if @xml.nil?
if @xml.is_a?(XML::Element) and
[@xml.name, @xml.uri] == ["div", XHTML_URI]
return @xml
end
children = @xml
children = [children] unless children.is_a?(Array)
XML::Element.new("div", nil, XHTML_URI,
{"xmlns" => XHTML_URI}, children)
end
def xhtml
if inline_xhtml?
xml
else
nil
end
end
def atom_validate(ignore_unknown_element, tags, uri)
if out_of_line?
raise MissingAttributeError.new(tag_name, "type") if @type.nil?
unless (content.nil? or content.empty?)
raise NotAvailableValueError.new(tag_name, content)
end
elsif inline_xhtml?
if @xml.nil?
raise MissingTagError.new("div", tag_name)
end
unless @xml.name == "div" and @xml.uri == XHTML_URI
raise NotExpectedTagError.new(@xml.name, @xml.uri, tag_name)
end
end
end
def inline_text?
!out_of_line? and [nil, "text", "html"].include?(@type)
end
def inline_html?
return false if out_of_line?
@type == "html" or mime_split == ["text", "html"]
end
def inline_xhtml?
!out_of_line? and @type == "xhtml"
end
def inline_other?
return false if out_of_line?
media_type, subtype = mime_split
return false if media_type.nil? or subtype.nil?
true
end
def inline_other_text?
return false unless inline_other?
return false if inline_other_xml?
media_type, subtype = mime_split
return true if "text" == media_type.downcase
false
end
def inline_other_xml?
return false unless inline_other?
media_type, subtype = mime_split
normalized_mime_type = "#{media_type}/#{subtype}".downcase
if /(?:\+xml|^xml)$/ =~ subtype or
%w(text/xml-external-parsed-entity
application/xml-external-parsed-entity
application/xml-dtd).find {|x| x == normalized_mime_type}
return true
end
false
end
def inline_other_base64?
inline_other? and !inline_other_text? and !inline_other_xml?
end
def out_of_line?
not @src.nil?
end
def mime_split
media_type = subtype = nil
if /\A\s*([a-z]+)\/([a-z\+]+)\s*(?:;.*)?\z/i =~ @type.to_s
media_type = $1.downcase
subtype = $2.downcase
end
[media_type, subtype]
end
def need_base64_encode?
inline_other_base64?
end
private
def empty_content?
out_of_line? or super
end
end
Contributor = Feed::Contributor
Id = Feed::Id
Link = Feed::Link
class Published < RSS::Element
include CommonModel
include DateConstruct
end
Rights = Feed::Rights
class Source < RSS::Element
include CommonModel
[
["author", "*", :children],
["category", "*", :children, "categories"],
["contributor", "*", :children],
["generator", "?"],
["icon", "?"],
["id", "?", nil, :content],
["link", "*", :children],
["logo", "?"],
["rights", "?"],
["subtitle", "?"],
["title", "?"],
["updated", "?", nil, :content],
].each do |tag, occurs, type, *args|
type ||= :attribute
__send__("install_have_#{type}_element",
tag, URI, occurs, tag, *args)
end
def have_author?
!author.to_s.empty?
end
Author = Feed::Author
Category = Feed::Category
Contributor = Feed::Contributor
Generator = Feed::Generator
Icon = Feed::Icon
Id = Feed::Id
Link = Feed::Link
Logo = Feed::Logo
Rights = Feed::Rights
Subtitle = Feed::Subtitle
Title = Feed::Title
Updated = Feed::Updated
end
class Summary < RSS::Element
include CommonModel
include TextConstruct
end
Title = Feed::Title
Updated = Feed::Updated
end
end
class Entry < RSS::Element
include RootElementMixin
include CommonModel
include DuplicateLinkChecker
[
["author", "*", :children],
["category", "*", :children, "categories"],
["content", "?"],
["contributor", "*", :children],
["id", nil, nil, :content],
["link", "*", :children],
["published", "?", :child, :content],
["rights", "?"],
["source", "?"],
["summary", "?"],
["title", nil],
["updated", nil, nil, :content],
].each do |tag, occurs, type, *args|
type ||= :attribute
__send__("install_have_#{type}_element",
tag, URI, occurs, tag, *args)
end
def initialize(version=nil, encoding=nil, standalone=nil)
super("1.0", version, encoding, standalone)
@feed_type = "atom"
@feed_subtype = "entry"
end
def items
[self]
end
def setup_maker(maker)
maker = maker.maker if maker.respond_to?("maker")
super(maker)
end
def have_author?
authors.any? {|author| !author.to_s.empty?} or
(source and source.have_author?)
end
private
def atom_validate(ignore_unknown_element, tags, uri)
unless have_author?
raise MissingTagError.new("author", tag_name)
end
validate_duplicate_links(links)
end
def have_required_elements?
super and have_author?
end
def maker_target(maker)
maker.items.new_item
end
Author = Feed::Entry::Author
Category = Feed::Entry::Category
Content = Feed::Entry::Content
Contributor = Feed::Entry::Contributor
Id = Feed::Entry::Id
Link = Feed::Entry::Link
Published = Feed::Entry::Published
Rights = Feed::Entry::Rights
Source = Feed::Entry::Source
Summary = Feed::Entry::Summary
Title = Feed::Entry::Title
Updated = Feed::Entry::Updated
end
end
Atom::CommonModel::ELEMENTS.each do |name|
BaseListener.install_get_text_element(Atom::URI, name, "#{name}=")
end
module ListenerMixin
private
def initial_start_feed(tag_name, prefix, attrs, ns)
check_ns(tag_name, prefix, ns, Atom::URI)
@rss = Atom::Feed.new(@version, @encoding, @standalone)
@rss.do_validate = @do_validate
@rss.xml_stylesheets = @xml_stylesheets
@rss.lang = attrs["xml:lang"]
@rss.base = attrs["xml:base"]
@last_element = @rss
pr = Proc.new do |text, tags|
@rss.validate_for_stream(tags) if @do_validate
end
@proc_stack.push(pr)
end
def initial_start_entry(tag_name, prefix, attrs, ns)
check_ns(tag_name, prefix, ns, Atom::URI)
@rss = Atom::Entry.new(@version, @encoding, @standalone)
@rss.do_validate = @do_validate
@rss.xml_stylesheets = @xml_stylesheets
@rss.lang = attrs["xml:lang"]
@rss.base = attrs["xml:base"]
@last_element = @rss
pr = Proc.new do |text, tags|
@rss.validate_for_stream(tags) if @do_validate
end
@proc_stack.push(pr)
end
end
end

View file

@ -32,7 +32,7 @@ module RSS
ContentModel::ELEMENTS.uniq! ContentModel::ELEMENTS.uniq!
ContentModel::ELEMENTS.each do |full_name| ContentModel::ELEMENTS.each do |full_name|
name = full_name[prefix_size..-1] name = full_name[prefix_size..-1]
BaseListener.install_get_text_element(CONTENT_URI, name, "#{full_name}=") BaseListener.install_get_text_element(CONTENT_URI, name, full_name)
end end
end end

View file

@ -80,9 +80,13 @@ module RSS
end end
rescue LoadError rescue LoadError
require 'nkf' require 'nkf'
if NKF.const_defined?(:UTF8)
def_convert(1) do |value| def_convert(1) do |value|
"NKF.nkf(#{nkf_arg.dump}, #{value})" "NKF.nkf(#{nkf_arg.dump}, #{value})"
end end
else
def_iconv_convert(to_enc, from_enc, 1)
end
end end
end end

View file

@ -1,12 +1,9 @@
require "rss/1.0" require "rss/rss"
module RSS module RSS
DC_PREFIX = 'dc' DC_PREFIX = 'dc'
DC_URI = "http://purl.org/dc/elements/1.1/" DC_URI = "http://purl.org/dc/elements/1.1/"
RDF.install_ns(DC_PREFIX, DC_URI)
module BaseDublinCoreModel module BaseDublinCoreModel
def append_features(klass) def append_features(klass)
super super
@ -36,8 +33,20 @@ module RSS
EOC EOC
end end
klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0)) klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0))
if method_defined?(:date)
alias date_without_#{DC_PREFIX}_date= date=
def date=(value)
self.date_without_#{DC_PREFIX}_date = value
self.#{DC_PREFIX}_date = value
end
else
alias date #{DC_PREFIX}_date alias date #{DC_PREFIX}_date
alias date= #{DC_PREFIX}_date= alias date= #{DC_PREFIX}_date=
end
# For backward compatibility
alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list
EOC EOC
end end
end end
@ -61,7 +70,7 @@ module RSS
"language" => nil, "language" => nil,
"relation" => nil, "relation" => nil,
"coverage" => nil, "coverage" => nil,
"rights" => "rightses" # FIXME "rights" => "rights_list"
} }
DATE_ELEMENTS = { DATE_ELEMENTS = {
@ -122,12 +131,13 @@ module RSS
end end
DATE_ELEMENTS.each do |name, type| DATE_ELEMENTS.each do |name, type|
tag_name = "#{DC_PREFIX}:#{name}"
module_eval(<<-EOC, *get_file_and_line_from_caller(0)) module_eval(<<-EOC, *get_file_and_line_from_caller(0))
class DublinCore#{Utils.to_class_name(name)} < Element class DublinCore#{Utils.to_class_name(name)} < Element
remove_method(:content=) remove_method(:content=)
remove_method(:value=) remove_method(:value=)
date_writer("content", #{type.dump}, #{name.dump}) date_writer("content", #{type.dump}, #{tag_name.dump})
alias_method(:value=, :content=) alias_method(:value=, :content=)
end end
@ -138,13 +148,6 @@ module RSS
# For backward compatibility # For backward compatibility
DublincoreModel = DublinCoreModel DublincoreModel = DublinCoreModel
class RDF
class Channel; include DublinCoreModel; end
class Image; include DublinCoreModel; end
class Item; include DublinCoreModel; end
class Textinput; include DublinCoreModel; end
end
DublinCoreModel::ELEMENTS.each do |name| DublinCoreModel::ELEMENTS.each do |name|
class_name = Utils.to_class_name(name) class_name = Utils.to_class_name(name)
BaseListener.install_class_name(DC_URI, name, "DublinCore#{class_name}") BaseListener.install_class_name(DC_URI, name, "DublinCore#{class_name}")
@ -152,3 +155,7 @@ module RSS
DublinCoreModel::ELEMENTS.collect! {|name| "#{DC_PREFIX}_#{name}"} DublinCoreModel::ELEMENTS.collect! {|name| "#{DC_PREFIX}_#{name}"}
end end
require 'rss/dublincore/1.0'
require 'rss/dublincore/2.0'
require 'rss/dublincore/atom'

13
lib/rss/dublincore/1.0.rb Normal file
View file

@ -0,0 +1,13 @@
require "rss/1.0"
require "rss/dublincore"
module RSS
RDF.install_ns(DC_PREFIX, DC_URI)
class RDF
class Channel; include DublinCoreModel; end
class Image; include DublinCoreModel; end
class Item; include DublinCoreModel; end
class Textinput; include DublinCoreModel; end
end
end

13
lib/rss/dublincore/2.0.rb Normal file
View file

@ -0,0 +1,13 @@
require "rss/2.0"
require "rss/dublincore"
module RSS
Rss.install_ns(DC_PREFIX, DC_URI)
class Rss
class Channel
include DublinCoreModel
class Item; include DublinCoreModel; end
end
end
end

View file

@ -0,0 +1,17 @@
require "rss/atom"
require "rss/dublincore"
module RSS
module Atom
Feed.install_ns(DC_PREFIX, DC_URI)
class Feed
include DublinCoreModel
class Entry; include DublinCoreModel; end
end
class Entry
include DublinCoreModel
end
end
end

View file

@ -4,7 +4,7 @@ require 'rss/dublincore'
module RSS module RSS
IMAGE_PREFIX = 'image' IMAGE_PREFIX = 'image'
IMAGE_URI = 'http://web.resource.org/rss/1.0/modules/image/' IMAGE_URI = 'http://purl.org/rss/1.0/modules/image/'
RDF.install_ns(IMAGE_PREFIX, IMAGE_URI) RDF.install_ns(IMAGE_PREFIX, IMAGE_URI)
@ -69,7 +69,7 @@ module RSS
disp_name = "#{IMAGE_PREFIX}:#{tag}" disp_name = "#{IMAGE_PREFIX}:#{tag}"
install_text_element(tag, IMAGE_URI, "?", install_text_element(tag, IMAGE_URI, "?",
full_name, :integer, disp_name) full_name, :integer, disp_name)
BaseListener.install_get_text_element(IMAGE_URI, tag, "#{full_name}=") BaseListener.install_get_text_element(IMAGE_URI, tag, full_name)
end end
alias width= image_width= alias width= image_width=
@ -142,8 +142,8 @@ module RSS
end end
AVAILABLE_SIZES = %w(small medium large) AVAILABLE_SIZES = %w(small medium large)
alias_method :_size=, :size= alias_method :set_size, :size=
private :_size= private :set_size
def size=(new_value) def size=(new_value)
if @do_validate and !new_value.nil? if @do_validate and !new_value.nil?
new_value = new_value.strip new_value = new_value.strip
@ -152,7 +152,7 @@ module RSS
raise NotAvailableValueError.new(full_name, new_value, attr_name) raise NotAvailableValueError.new(full_name, new_value, attr_name)
end end
end end
__send__(:_size=, new_value) set_size(new_value)
end end
alias image_size= size= alias image_size= size=

410
lib/rss/itunes.rb Normal file
View file

@ -0,0 +1,410 @@
require 'rss/2.0'
module RSS
ITUNES_PREFIX = 'itunes'
ITUNES_URI = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
Rss.install_ns(ITUNES_PREFIX, ITUNES_URI)
module ITunesModelUtils
include Utils
def def_class_accessor(klass, name, type, *args)
normalized_name = name.gsub(/-/, "_")
full_name = "#{ITUNES_PREFIX}_#{normalized_name}"
klass_name = "ITunes#{Utils.to_class_name(normalized_name)}"
case type
when :element, :attribute
klass::ELEMENTS << full_name
def_element_class_accessor(klass, name, full_name, klass_name, *args)
when :elements
klass::ELEMENTS << full_name
def_elements_class_accessor(klass, name, full_name, klass_name, *args)
else
klass.install_must_call_validator(ITUNES_PREFIX, ITUNES_URI)
klass.install_text_element(normalized_name, ITUNES_URI, "?",
full_name, type, name)
end
end
def def_element_class_accessor(klass, name, full_name, klass_name,
recommended_attribute_name=nil)
klass.install_have_child_element(name, ITUNES_PREFIX, "?", full_name)
end
def def_elements_class_accessor(klass, name, full_name, klass_name,
plural_name, recommended_attribute_name=nil)
full_plural_name = "#{ITUNES_PREFIX}_#{plural_name}"
klass.install_have_children_element(name, ITUNES_PREFIX, "*",
full_name, full_plural_name)
end
end
module ITunesBaseModel
extend ITunesModelUtils
ELEMENTS = []
ELEMENT_INFOS = [["author"],
["block", :yes_other],
["explicit", :yes_clean_other],
["keywords", :csv],
["subtitle"],
["summary"]]
end
module ITunesChannelModel
extend BaseModel
extend ITunesModelUtils
include ITunesBaseModel
ELEMENTS = []
class << self
def append_features(klass)
super
return if klass.instance_of?(Module)
ELEMENT_INFOS.each do |name, type, *additional_infos|
def_class_accessor(klass, name, type, *additional_infos)
end
end
end
ELEMENT_INFOS = [
["category", :elements, "categories", "text"],
["image", :attribute, "href"],
["owner", :element],
["new-feed-url"],
] + ITunesBaseModel::ELEMENT_INFOS
class ITunesCategory < Element
include RSS09
@tag_name = "category"
class << self
def required_prefix
ITUNES_PREFIX
end
def required_uri
ITUNES_URI
end
end
[
["text", "", true]
].each do |name, uri, required|
install_get_attribute(name, uri, required)
end
ITunesCategory = self
install_have_children_element("category", ITUNES_URI, "*",
"#{ITUNES_PREFIX}_category",
"#{ITUNES_PREFIX}_categories")
def initialize(*args)
if Utils.element_initialize_arguments?(args)
super
else
super()
self.text = args[0]
end
end
def full_name
tag_name_with_prefix(ITUNES_PREFIX)
end
private
def maker_target(categories)
if text or !itunes_categories.empty?
categories.new_category
else
nil
end
end
def setup_maker_attributes(category)
category.text = text if text
end
def setup_maker_elements(category)
super(category)
itunes_categories.each do |sub_category|
sub_category.setup_maker(category)
end
end
end
class ITunesImage < Element
include RSS09
@tag_name = "image"
class << self
def required_prefix
ITUNES_PREFIX
end
def required_uri
ITUNES_URI
end
end
[
["href", "", true]
].each do |name, uri, required|
install_get_attribute(name, uri, required)
end
def initialize(*args)
if Utils.element_initialize_arguments?(args)
super
else
super()
self.href = args[0]
end
end
def full_name
tag_name_with_prefix(ITUNES_PREFIX)
end
private
def maker_target(target)
if href
target.itunes_image {|image| image}
else
nil
end
end
def setup_maker_attributes(image)
image.href = href
end
end
class ITunesOwner < Element
include RSS09
@tag_name = "owner"
class << self
def required_prefix
ITUNES_PREFIX
end
def required_uri
ITUNES_URI
end
end
install_must_call_validator(ITUNES_PREFIX, ITUNES_URI)
[
["name"],
["email"],
].each do |name,|
ITunesBaseModel::ELEMENT_INFOS << name
install_text_element(name, ITUNES_URI, nil, "#{ITUNES_PREFIX}_#{name}")
end
def initialize(*args)
if Utils.element_initialize_arguments?(args)
super
else
super()
self.itunes_name = args[0]
self.itunes_email = args[1]
end
end
def full_name
tag_name_with_prefix(ITUNES_PREFIX)
end
private
def maker_target(target)
target.itunes_owner
end
def setup_maker_element(owner)
super(owner)
owner.itunes_name = itunes_name
owner.itunes_email = itunes_email
end
end
end
module ITunesItemModel
extend BaseModel
extend ITunesModelUtils
include ITunesBaseModel
class << self
def append_features(klass)
super
return if klass.instance_of?(Module)
ELEMENT_INFOS.each do |name, type|
def_class_accessor(klass, name, type)
end
end
end
ELEMENT_INFOS = ITunesBaseModel::ELEMENT_INFOS +
[["duration", :element, "content"]]
class ITunesDuration < Element
include RSS09
@tag_name = "duration"
class << self
def required_prefix
ITUNES_PREFIX
end
def required_uri
ITUNES_URI
end
def parse(duration, do_validate=true)
if do_validate and /\A(?:
\d?\d:[0-5]\d:[0-5]\d|
[0-5]?\d:[0-5]\d
)\z/x !~ duration
raise ArgumentError,
"must be one of HH:MM:SS, H:MM:SS, MM::SS, M:SS: " +
duration.inspect
end
components = duration.split(':')
components[3..-1] = nil if components.size > 3
components.unshift("00") until components.size == 3
components.collect do |component|
component.to_i
end
end
def construct(hour, minute, second)
components = [minute, second]
if components.include?(nil)
nil
else
components.unshift(hour) if hour and hour > 0
components.collect do |component|
"%02d" % component
end.join(":")
end
end
end
content_setup
alias_method(:value, :content)
remove_method(:content=)
attr_reader :hour, :minute, :second
def initialize(*args)
if Utils.element_initialize_arguments?(args)
super
else
super()
args = args[0] if args.size == 1 and args[0].is_a?(Array)
if args.size == 1
self.content = args[0]
elsif args.size > 3
raise ArgumentError,
"must be (do_validate, params), (content), " +
"(minute, second), ([minute, second]), " +
"(hour, minute, second) or ([hour, minute, second]): " +
args.inspect
else
@second, @minute, @hour = args.reverse
update_content
end
end
end
def content=(value)
if value.nil?
@content = nil
elsif value.is_a?(self.class)
self.content = value.content
else
begin
@hour, @minute, @second = self.class.parse(value, @do_validate)
rescue ArgumentError
raise NotAvailableValueError.new(tag_name, value)
end
@content = value
end
end
alias_method(:value=, :content=)
def hour=(hour)
@hour = @do_validate ? Integer(hour) : hour.to_i
update_content
hour
end
def minute=(minute)
@minute = @do_validate ? Integer(minute) : minute.to_i
update_content
minute
end
def second=(second)
@second = @do_validate ? Integer(second) : second.to_i
update_content
second
end
def full_name
tag_name_with_prefix(ITUNES_PREFIX)
end
private
def update_content
@content = self.class.construct(hour, minute, second)
end
def maker_target(target)
if @content
target.itunes_duration {|duration| duration}
else
nil
end
end
def setup_maker_element(duration)
super(duration)
duration.content = @content
end
end
end
class Rss
class Channel
include ITunesChannelModel
class Item; include ITunesItemModel; end
end
end
element_infos =
ITunesChannelModel::ELEMENT_INFOS + ITunesItemModel::ELEMENT_INFOS
element_infos.each do |name, type|
case type
when :element, :elements, :attribute
class_name = Utils.to_class_name(name)
BaseListener.install_class_name(ITUNES_URI, name, "ITunes#{class_name}")
else
accessor_base = "#{ITUNES_PREFIX}_#{name.gsub(/-/, '_')}"
BaseListener.install_get_text_element(ITUNES_URI, name, accessor_base)
end
end
end

View file

@ -1,14 +1,14 @@
require "rss/rss" require "rss/rss"
module RSS module RSS
module Maker module Maker
MAKERS = {} MAKERS = {}
class << self class << self
def make(version, &block) def make(version, &block)
maker(version).make(&block) m = maker(version)
raise UnsupportedMakerVersionError.new(version) if m.nil?
m.make(&block)
end end
def maker(version) def maker(version)
@ -19,19 +19,26 @@ module RSS
MAKERS[version] = maker MAKERS[version] = maker
end end
def filename_to_version(filename) def versions
File.basename(filename, ".*") MAKERS.keys.uniq.sort
end
end
end end
def makers
MAKERS.values.uniq
end
end
end
end end
require "rss/maker/1.0" require "rss/maker/1.0"
require "rss/maker/2.0" require "rss/maker/2.0"
require "rss/maker/feed"
require "rss/maker/entry"
require "rss/maker/content" require "rss/maker/content"
require "rss/maker/dublincore" require "rss/maker/dublincore"
require "rss/maker/slash"
require "rss/maker/syndication" require "rss/maker/syndication"
require "rss/maker/taxonomy" require "rss/maker/taxonomy"
require "rss/maker/trackback" require "rss/maker/trackback"
require "rss/maker/image" require "rss/maker/image"
require "rss/maker/itunes"

View file

@ -7,13 +7,14 @@ module RSS
class RSS09 < RSSBase class RSS09 < RSSBase
def initialize(rss_version="0.91") def initialize(feed_version="0.91")
super super
@feed_type = "rss"
end end
private private
def make_rss def make_feed
Rss.new(@rss_version, @version, @encoding, @standalone) Rss.new(@feed_version, @version, @encoding, @standalone)
end end
def setup_elements(rss) def setup_elements(rss)
@ -21,41 +22,34 @@ module RSS
end end
class Channel < ChannelBase class Channel < ChannelBase
def to_feed(rss)
def to_rss(rss)
channel = Rss::Channel.new channel = Rss::Channel.new
set = setup_values(channel) set = setup_values(channel)
if set _not_set_required_variables = not_set_required_variables
if _not_set_required_variables.empty?
rss.channel = channel rss.channel = channel
set_parent(channel, rss)
setup_items(rss) setup_items(rss)
setup_image(rss) setup_image(rss)
setup_textinput(rss) setup_textinput(rss)
setup_other_elements(rss) setup_other_elements(rss, channel)
if rss.channel.image
rss rss
else else
nil raise NotSetError.new("maker.channel", _not_set_required_variables)
end end
elsif variable_is_set?
raise NotSetError.new("maker.channel", not_set_required_variables)
end
end
def have_required_values?
@title and @link and @description and @language
end end
private private
def setup_items(rss) def setup_items(rss)
@maker.items.to_rss(rss) @maker.items.to_feed(rss)
end end
def setup_image(rss) def setup_image(rss)
@maker.image.to_rss(rss) @maker.image.to_feed(rss)
end end
def setup_textinput(rss) def setup_textinput(rss)
@maker.textinput.to_rss(rss) @maker.textinput.to_feed(rss)
end end
def variables def variables
@ -63,162 +57,405 @@ module RSS
end end
def required_variable_names def required_variable_names
%w(title link description language) %w(link language)
end
def not_set_required_variables
vars = super
vars << "description" unless description {|d| d.have_required_values?}
vars << "title" unless title {|t| t.have_required_values?}
vars
end end
class SkipDays < SkipDaysBase class SkipDays < SkipDaysBase
def to_rss(rss, channel) def to_feed(rss, channel)
unless @days.empty? unless @days.empty?
skipDays = Rss::Channel::SkipDays.new skipDays = Rss::Channel::SkipDays.new
channel.skipDays = skipDays channel.skipDays = skipDays
set_parent(skipDays, channel)
@days.each do |day| @days.each do |day|
day.to_rss(rss, skipDays.days) day.to_feed(rss, skipDays.days)
end end
end end
end end
class Day < DayBase class Day < DayBase
def to_rss(rss, days) def to_feed(rss, days)
day = Rss::Channel::SkipDays::Day.new day = Rss::Channel::SkipDays::Day.new
set = setup_values(day) set = setup_values(day)
if set if set
days << day days << day
setup_other_elements(rss) set_parent(day, days)
setup_other_elements(rss, day)
end end
end end
def have_required_values? private
@content def required_variable_names
%w(content)
end end
end end
end end
class SkipHours < SkipHoursBase class SkipHours < SkipHoursBase
def to_rss(rss, channel) def to_feed(rss, channel)
unless @hours.empty? unless @hours.empty?
skipHours = Rss::Channel::SkipHours.new skipHours = Rss::Channel::SkipHours.new
channel.skipHours = skipHours channel.skipHours = skipHours
set_parent(skipHours, channel)
@hours.each do |hour| @hours.each do |hour|
hour.to_rss(rss, skipHours.hours) hour.to_feed(rss, skipHours.hours)
end end
end end
end end
class Hour < HourBase class Hour < HourBase
def to_rss(rss, hours) def to_feed(rss, hours)
hour = Rss::Channel::SkipHours::Hour.new hour = Rss::Channel::SkipHours::Hour.new
set = setup_values(hour) set = setup_values(hour)
if set if set
hours << hour hours << hour
setup_other_elements(rss) set_parent(hour, hours)
setup_other_elements(rss, hour)
end end
end end
def have_required_values? private
@content def required_variable_names
%w(content)
end end
end end
end end
class Cloud < CloudBase class Cloud < CloudBase
def to_rss(*args) def to_feed(*args)
end end
end end
class Categories < CategoriesBase class Categories < CategoriesBase
def to_rss(*args) def to_feed(*args)
end end
class Category < CategoryBase class Category < CategoryBase
end end
end end
class Links < LinksBase
def to_feed(rss, channel)
return if @links.empty?
@links.first.to_feed(rss, channel)
end
class Link < LinkBase
def to_feed(rss, channel)
if have_required_values?
channel.link = href
else
raise NotSetError.new("maker.channel.link",
not_set_required_variables)
end
end
private
def required_variable_names
%w(href)
end
end
end
class Authors < AuthorsBase
def to_feed(rss, channel)
end
class Author < AuthorBase
def to_feed(rss, channel)
end
end
end
class Contributors < ContributorsBase
def to_feed(rss, channel)
end
class Contributor < ContributorBase
end
end
class Generator < GeneratorBase
def to_feed(rss, channel)
end
end
class Copyright < CopyrightBase
def to_feed(rss, channel)
channel.copyright = content if have_required_values?
end
private
def required_variable_names
%w(content)
end
end
class Description < DescriptionBase
def to_feed(rss, channel)
channel.description = content if have_required_values?
end
private
def required_variable_names
%w(content)
end
end
class Title < TitleBase
def to_feed(rss, channel)
channel.title = content if have_required_values?
end
private
def required_variable_names
%w(content)
end
end
end end
class Image < ImageBase class Image < ImageBase
def to_rss(rss) def to_feed(rss)
image = Rss::Channel::Image.new image = Rss::Channel::Image.new
set = setup_values(image) set = setup_values(image)
if set if set
image.link = link image.link = link
rss.channel.image = image rss.channel.image = image
setup_other_elements(rss) set_parent(image, rss.channel)
end setup_other_elements(rss, image)
end elsif required_element?
raise NotSetError.new("maker.image", not_set_required_variables)
def have_required_values?
@url and @title and link
end
end
class Items < ItemsBase
def to_rss(rss)
if rss.channel
normalize.each do |item|
item.to_rss(rss)
end
setup_other_elements(rss)
end
end
class Item < ItemBase
def to_rss(rss)
item = Rss::Channel::Item.new
set = setup_values(item)
if set
rss.items << item
setup_other_elements(rss)
end end
end end
private private
def have_required_values? def required_variable_names
@title and @link %w(url title link)
end
def required_element?
true
end
end
class Items < ItemsBase
def to_feed(rss)
if rss.channel
normalize.each do |item|
item.to_feed(rss)
end
setup_other_elements(rss, rss.items)
end
end
class Item < ItemBase
def to_feed(rss)
item = Rss::Channel::Item.new
set = setup_values(item)
if set or title {|t| t.have_required_values?}
rss.items << item
set_parent(item, rss.channel)
setup_other_elements(rss, item)
elsif variable_is_set?
raise NotSetError.new("maker.items", not_set_required_variables)
end
end
private
def required_variable_names
%w(link)
end
def not_set_required_variables
vars = super
vars << "title" unless title {|t| t.have_required_values?}
vars
end end
class Guid < GuidBase class Guid < GuidBase
def to_rss(*args) def to_feed(*args)
end end
end end
class Enclosure < EnclosureBase class Enclosure < EnclosureBase
def to_rss(*args) def to_feed(*args)
end end
end end
class Source < SourceBase class Source < SourceBase
def to_rss(*args) def to_feed(*args)
end
class Authors < AuthorsBase
def to_feed(*args)
end
class Author < AuthorBase
end end
end end
class Categories < CategoriesBase class Categories < CategoriesBase
def to_rss(*args) def to_feed(*args)
end end
class Category < CategoryBase class Category < CategoryBase
end end
end end
class Contributors < ContributorsBase
def to_feed(*args)
end
class Contributor < ContributorBase
end end
end end
class Textinput < TextinputBase class Generator < GeneratorBase
def to_rss(rss) def to_feed(*args)
textInput = Rss::Channel::TextInput.new end
set = setup_values(textInput) end
if set
rss.channel.textInput = textInput class Icon < IconBase
setup_other_elements(rss) def to_feed(*args)
end
end
class Links < LinksBase
def to_feed(*args)
end
class Link < LinkBase
end
end
class Logo < LogoBase
def to_feed(*args)
end
end
class Rights < RightsBase
def to_feed(*args)
end
end
class Subtitle < SubtitleBase
def to_feed(*args)
end
end
class Title < TitleBase
def to_feed(*args)
end
end
end
class Categories < CategoriesBase
def to_feed(*args)
end
class Category < CategoryBase
end
end
class Authors < AuthorsBase
def to_feed(*args)
end
class Author < AuthorBase
end
end
class Links < LinksBase
def to_feed(rss, item)
return if @links.empty?
@links.first.to_feed(rss, item)
end
class Link < LinkBase
def to_feed(rss, item)
if have_required_values?
item.link = href
else
raise NotSetError.new("maker.link",
not_set_required_variables)
end end
end end
private private
def have_required_values? def required_variable_names
@title and @description and @name and @link %w(href)
end end
end end
end end
add_maker(filename_to_version(__FILE__), RSS09) class Contributors < ContributorsBase
add_maker(filename_to_version(__FILE__) + "1", RSS09) def to_feed(rss, item)
end
class Contributor < ContributorBase
end
end
class Rights < RightsBase
def to_feed(rss, item)
end
end
class Description < DescriptionBase
def to_feed(rss, item)
item.description = content if have_required_values?
end
private
def required_variable_names
%w(content)
end
end
class Content < ContentBase
def to_feed(rss, item)
end
end
class Title < TitleBase
def to_feed(rss, item)
item.title = content if have_required_values?
end
private
def required_variable_names
%w(content)
end
end
end
end
class Textinput < TextinputBase
def to_feed(rss)
textInput = Rss::Channel::TextInput.new
set = setup_values(textInput)
if set
rss.channel.textInput = textInput
set_parent(textInput, rss.channel)
setup_other_elements(rss, textInput)
end
end
private
def required_variable_names
%w(title description name link)
end
end
end
add_maker("0.9", RSS09)
add_maker("0.91", RSS09)
add_maker("rss0.91", RSS09)
end end
end end

View file

@ -9,10 +9,11 @@ module RSS
def initialize def initialize
super("1.0") super("1.0")
@feed_type = "rss"
end end
private private
def make_rss def make_feed
RDF.new(@version, @encoding, @standalone) RDF.new(@version, @encoding, @standalone)
end end
@ -25,43 +26,46 @@ module RSS
class Channel < ChannelBase class Channel < ChannelBase
def to_rss(rss) def to_feed(rss)
set = false set_default_values do
if @about _not_set_required_variables = not_set_required_variables
if _not_set_required_variables.empty?
channel = RDF::Channel.new(@about) channel = RDF::Channel.new(@about)
set = setup_values(channel) set = setup_values(channel)
if set
channel.dc_dates.clear channel.dc_dates.clear
rss.channel = channel rss.channel = channel
set_parent(channel, rss)
setup_items(rss) setup_items(rss)
setup_image(rss) setup_image(rss)
setup_textinput(rss) setup_textinput(rss)
setup_other_elements(rss) setup_other_elements(rss, channel)
else
raise NotSetError.new("maker.channel", _not_set_required_variables)
end end
end end
if (!@about or !set) and variable_is_set?
raise NotSetError.new("maker.channel", not_set_required_variables)
end
end
def have_required_values?
@about and @title and @link and @description
end end
private private
def setup_items(rss) def setup_items(rss)
items = RDF::Channel::Items.new items = RDF::Channel::Items.new
seq = items.Seq seq = items.Seq
@maker.items.normalize.each do |item| set_parent(items, seq)
seq.lis << RDF::Channel::Items::Seq::Li.new(item.link) target_items = @maker.items.normalize
raise NotSetError.new("maker", ["items"]) if target_items.empty?
target_items.each do |item|
li = RDF::Channel::Items::Seq::Li.new(item.link)
seq.lis << li
set_parent(li, seq)
end end
rss.channel.items = items rss.channel.items = items
set_parent(rss.channel, items)
end end
def setup_image(rss) def setup_image(rss)
if @maker.image.have_required_values? if @maker.image.have_required_values?
rss.channel.image = RDF::Channel::Image.new(@maker.image.url) image = RDF::Channel::Image.new(@maker.image.url)
rss.channel.image = image
set_parent(image, rss.channel)
end end
end end
@ -69,15 +73,23 @@ module RSS
if @maker.textinput.have_required_values? if @maker.textinput.have_required_values?
textinput = RDF::Channel::Textinput.new(@maker.textinput.link) textinput = RDF::Channel::Textinput.new(@maker.textinput.link)
rss.channel.textinput = textinput rss.channel.textinput = textinput
set_parent(textinput, rss.channel)
end end
end end
def required_variable_names def required_variable_names
%w(about title link description) %w(about link)
end
def not_set_required_variables
vars = super
vars << "description" unless description {|d| d.have_required_values?}
vars << "title" unless title {|t| t.have_required_values?}
vars
end end
class SkipDays < SkipDaysBase class SkipDays < SkipDaysBase
def to_rss(*args) def to_feed(*args)
end end
class Day < DayBase class Day < DayBase
@ -85,7 +97,7 @@ module RSS
end end
class SkipHours < SkipHoursBase class SkipHours < SkipHoursBase
def to_rss(*args) def to_feed(*args)
end end
class Hour < HourBase class Hour < HourBase
@ -93,112 +105,330 @@ module RSS
end end
class Cloud < CloudBase class Cloud < CloudBase
def to_rss(*args) def to_feed(*args)
end end
end end
class Categories < CategoriesBase class Categories < CategoriesBase
def to_rss(*args) def to_feed(*args)
end end
class Category < CategoryBase class Category < CategoryBase
end end
end end
class Links < LinksBase
def to_feed(rss, channel)
return if @links.empty?
@links.first.to_feed(rss, channel)
end
class Link < LinkBase
def to_feed(rss, channel)
if have_required_values?
channel.link = href
else
raise NotSetError.new("maker.channel.link",
not_set_required_variables)
end
end
private
def required_variable_names
%w(href)
end
end
end
class Authors < AuthorsBase
def to_feed(rss, channel)
end
class Author < AuthorBase
def to_feed(rss, channel)
end
end
end
class Contributors < ContributorsBase
def to_feed(rss, channel)
end
class Contributor < ContributorBase
end
end
class Generator < GeneratorBase
def to_feed(rss, channel)
end
end
class Copyright < CopyrightBase
def to_feed(rss, channel)
end
end
class Description < DescriptionBase
def to_feed(rss, channel)
channel.description = content if have_required_values?
end
private
def required_variable_names
%w(content)
end
end
class Title < TitleBase
def to_feed(rss, channel)
channel.title = content if have_required_values?
end
private
def required_variable_names
%w(content)
end
end
end end
class Image < ImageBase class Image < ImageBase
def to_rss(rss) def to_feed(rss)
if @url if @url
image = RDF::Image.new(@url) image = RDF::Image.new(@url)
set = setup_values(image) set = setup_values(image)
if set if set
rss.image = image rss.image = image
setup_other_elements(rss) set_parent(image, rss)
setup_other_elements(rss, image)
end end
end end
end end
def have_required_values? def have_required_values?
@url and @title and link and @maker.channel.have_required_values? super and @maker.channel.have_required_values?
end end
private private
def variables def variables
super + ["link"] super + ["link"]
end end
def required_variable_names
%w(url title link)
end
end end
class Items < ItemsBase class Items < ItemsBase
def to_rss(rss) def to_feed(rss)
if rss.channel if rss.channel
normalize.each do |item| normalize.each do |item|
item.to_rss(rss) item.to_feed(rss)
end end
setup_other_elements(rss) setup_other_elements(rss, rss.items)
end end
end end
class Item < ItemBase class Item < ItemBase
def to_rss(rss) def to_feed(rss)
if @link set_default_values do
item = RDF::Item.new(@link) item = RDF::Item.new(link)
set = setup_values(item) set = setup_values(item)
if set if set
item.dc_dates.clear item.dc_dates.clear
rss.items << item rss.items << item
setup_other_elements(rss) set_parent(item, rss)
setup_other_elements(rss, item)
elsif !have_required_values?
raise NotSetError.new("maker.item", not_set_required_variables)
end end
end end
end end
def have_required_values? private
@title and @link def required_variable_names
%w(link)
end
def variables
super + %w(link)
end
def not_set_required_variables
set_default_values do
vars = super
vars << "title" unless title {|t| t.have_required_values?}
vars
end
end end
class Guid < GuidBase class Guid < GuidBase
def to_rss(*args) def to_feed(*args)
end end
end end
class Enclosure < EnclosureBase class Enclosure < EnclosureBase
def to_rss(*args) def to_feed(*args)
end end
end end
class Source < SourceBase class Source < SourceBase
def to_rss(*args) def to_feed(*args)
end
class Authors < AuthorsBase
def to_feed(*args)
end
class Author < AuthorBase
end end
end end
class Categories < CategoriesBase class Categories < CategoriesBase
def to_rss(*args) def to_feed(*args)
end end
class Category < CategoryBase class Category < CategoryBase
end end
end end
class Contributors < ContributorsBase
def to_feed(*args)
end
class Contributor < ContributorBase
end
end
class Generator < GeneratorBase
def to_feed(*args)
end
end
class Icon < IconBase
def to_feed(*args)
end
end
class Links < LinksBase
def to_feed(*args)
end
class Link < LinkBase
end
end
class Logo < LogoBase
def to_feed(*args)
end
end
class Rights < RightsBase
def to_feed(*args)
end
end
class Subtitle < SubtitleBase
def to_feed(*args)
end
end
class Title < TitleBase
def to_feed(*args)
end
end
end
class Categories < CategoriesBase
def to_feed(*args)
end
class Category < CategoryBase
end
end
class Authors < AuthorsBase
def to_feed(*args)
end
class Author < AuthorBase
end
end
class Links < LinksBase
def to_feed(*args)
end
class Link < LinkBase
end
end
class Contributors < ContributorsBase
def to_feed(rss, item)
end
class Contributor < ContributorBase
end
end
class Rights < RightsBase
def to_feed(rss, item)
end
end
class Description < DescriptionBase
def to_feed(rss, item)
item.description = content if have_required_values?
end
private
def required_variable_names
%w(content)
end
end
class Content < ContentBase
def to_feed(rss, item)
end
end
class Title < TitleBase
def to_feed(rss, item)
item.title = content if have_required_values?
end
private
def required_variable_names
%w(content)
end
end
end end
end end
class Textinput < TextinputBase class Textinput < TextinputBase
def to_rss(rss) def to_feed(rss)
if @link if @link
textinput = RDF::Textinput.new(@link) textinput = RDF::Textinput.new(@link)
set = setup_values(textinput) set = setup_values(textinput)
if set if set
rss.textinput = textinput rss.textinput = textinput
setup_other_elements(rss) set_parent(textinput, rss)
setup_other_elements(rss, textinput)
end end
end end
end end
def have_required_values? def have_required_values?
@title and @description and @name and @link and super and @maker.channel.have_required_values?
@maker.channel.have_required_values? end
private
def required_variable_names
%w(title description name link)
end end
end end
end end
add_maker(filename_to_version(__FILE__), RSS10) add_maker("1.0", RSS10)
add_maker("rss1.0", RSS10)
end end
end end

View file

@ -7,18 +7,15 @@ module RSS
class RSS20 < RSS09 class RSS20 < RSS09
def initialize(rss_version="2.0") def initialize(feed_version="2.0")
super super
end end
class Channel < RSS09::Channel class Channel < RSS09::Channel
def have_required_values? private
@title and @link and @description
end
def required_variable_names def required_variable_names
%w(title link description) %w(link)
end end
class SkipDays < RSS09::Channel::SkipDays class SkipDays < RSS09::Channel::SkipDays
@ -32,137 +29,186 @@ module RSS
end end
class Cloud < RSS09::Channel::Cloud class Cloud < RSS09::Channel::Cloud
def to_rss(rss, channel) def to_feed(rss, channel)
cloud = Rss::Channel::Cloud.new cloud = Rss::Channel::Cloud.new
set = setup_values(cloud) set = setup_values(cloud)
if set if set
channel.cloud = cloud channel.cloud = cloud
setup_other_elements(rss) set_parent(cloud, channel)
setup_other_elements(rss, cloud)
end end
end end
def have_required_values? private
@domain and @port and @path and def required_variable_names
@registerProcedure and @protocol %w(domain port path registerProcedure protocol)
end end
end end
class Categories < RSS09::Channel::Categories class Categories < RSS09::Channel::Categories
def to_rss(rss, channel) def to_feed(rss, channel)
@categories.each do |category| @categories.each do |category|
category.to_rss(rss, channel) category.to_feed(rss, channel)
end end
end end
class Category < RSS09::Channel::Categories::Category class Category < RSS09::Channel::Categories::Category
def to_rss(rss, channel) def to_feed(rss, channel)
category = Rss::Channel::Category.new category = Rss::Channel::Category.new
set = setup_values(category) set = setup_values(category)
if set if set
channel.categories << category channel.categories << category
setup_other_elements(rss) set_parent(category, channel)
setup_other_elements(rss, category)
end end
end end
def have_required_values?
@content
end
end
end
end
class Image < RSS09::Image
end
class Items < RSS09::Items
class Item < RSS09::Items::Item
def have_required_values?
@title or @description
end
private private
def required_variable_names
%w(content)
end
end
end
class Generator < GeneratorBase
def to_feed(rss, channel)
channel.generator = content
end
private
def required_variable_names
%w(content)
end
end
end
class Image < RSS09::Image
private
def required_element?
false
end
end
class Items < RSS09::Items
class Item < RSS09::Items::Item
private
def required_variable_names
%w(title description)
end
def variables def variables
super + ["pubDate"] super + ["pubDate"]
end end
class Guid < RSS09::Items::Item::Guid class Guid < RSS09::Items::Item::Guid
def to_rss(rss, item) def to_feed(rss, item)
guid = Rss::Channel::Item::Guid.new guid = Rss::Channel::Item::Guid.new
set = setup_values(guid) set = setup_values(guid)
if set if set
item.guid = guid item.guid = guid
setup_other_elements(rss) set_parent(guid, item)
setup_other_elements(rss, guid)
end end
end end
def have_required_values? private
@content def required_variable_names
%w(content)
end end
end end
class Enclosure < RSS09::Items::Item::Enclosure class Enclosure < RSS09::Items::Item::Enclosure
def to_rss(rss, item) def to_feed(rss, item)
enclosure = Rss::Channel::Item::Enclosure.new enclosure = Rss::Channel::Item::Enclosure.new
set = setup_values(enclosure) set = setup_values(enclosure)
if set if set
item.enclosure = enclosure item.enclosure = enclosure
setup_other_elements(rss) set_parent(enclosure, item)
setup_other_elements(rss, enclosure)
end end
end end
def have_required_values? private
@url and @length and @type def required_variable_names
%w(url length type)
end end
end end
class Source < RSS09::Items::Item::Source class Source < RSS09::Items::Item::Source
def to_rss(rss, item) def to_feed(rss, item)
source = Rss::Channel::Item::Source.new source = Rss::Channel::Item::Source.new
set = setup_values(source) set = setup_values(source)
if set if set
item.source = source item.source = source
setup_other_elements(rss) set_parent(source, item)
setup_other_elements(rss, source)
end end
end end
def have_required_values? private
@url and @content def required_variable_names
%w(url content)
end
class Links < RSS09::Items::Item::Source::Links
def to_feed(rss, source)
return if @links.empty?
@links.first.to_feed(rss, source)
end
class Link < RSS09::Items::Item::Source::Links::Link
def to_feed(rss, source)
source.url = href
end
end
end end
end end
class Categories < RSS09::Items::Item::Categories class Categories < RSS09::Items::Item::Categories
def to_rss(rss, item) def to_feed(rss, item)
@categories.each do |category| @categories.each do |category|
category.to_rss(rss, item) category.to_feed(rss, item)
end end
end end
class Category < RSS09::Items::Item::Categories::Category class Category < RSS09::Items::Item::Categories::Category
def to_rss(rss, item) def to_feed(rss, item)
category = Rss::Channel::Item::Category.new category = Rss::Channel::Item::Category.new
set = setup_values(category) set = setup_values(category)
if set if set
item.categories << category item.categories << category
set_parent(category, item)
setup_other_elements(rss) setup_other_elements(rss)
end end
end end
def have_required_values? private
@content def required_variable_names
end %w(content)
end end
end end
end end
class Authors < RSS09::Items::Item::Authors
def to_feed(rss, item)
return if @authors.empty?
@authors.first.to_feed(rss, item)
end
class Author < RSS09::Items::Item::Authors::Author
def to_feed(rss, item)
item.author = name
end
end
end
end
end end
class Textinput < RSS09::Textinput class Textinput < RSS09::Textinput
end end
end end
add_maker(filename_to_version(__FILE__), RSS20) add_maker("2.0", RSS20)
add_maker("rss2.0", RSS20)
end end
end end

172
lib/rss/maker/atom.rb Normal file
View file

@ -0,0 +1,172 @@
require "rss/atom"
require "rss/maker/base"
module RSS
module Maker
module AtomPersons
module_function
def def_atom_persons(klass, name, maker_name, plural=nil)
plural ||= "#{name}s"
klass_name = Utils.to_class_name(name)
plural_klass_name = Utils.to_class_name(plural)
klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1)
class #{plural_klass_name} < #{plural_klass_name}Base
class #{klass_name} < #{klass_name}Base
def to_feed(feed, current)
#{name} = feed.class::#{klass_name}.new
set = setup_values(#{name})
unless set
raise NotSetError.new(#{maker_name.dump},
not_set_required_variables)
end
current.#{plural} << #{name}
set_parent(#{name}, current)
setup_other_elements(#{name})
end
private
def required_variable_names
%w(name)
end
end
end
EOC
end
end
module AtomTextConstruct
class << self
def def_atom_text_construct(klass, name, maker_name, klass_name=nil,
atom_klass_name=nil)
klass_name ||= Utils.to_class_name(name)
atom_klass_name ||= Utils.to_class_name(name)
klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1)
class #{klass_name} < #{klass_name}Base
include #{self.name}
def to_feed(feed, current)
#{name} = current.class::#{atom_klass_name}.new
if setup_values(#{name})
current.#{name} = #{name}
set_parent(#{name}, current)
setup_other_elements(feed)
elsif variable_is_set?
raise NotSetError.new(#{maker_name.dump},
not_set_required_variables)
end
end
end
EOC
end
end
private
def required_variable_names
if type == "xhtml"
%w(xml_content)
else
%w(content)
end
end
def variables
if type == "xhtml"
super + %w(xhtml)
else
super
end
end
end
module AtomCategory
def to_feed(feed, current)
category = feed.class::Category.new
set = setup_values(category)
if set
current.categories << category
set_parent(category, current)
setup_other_elements(feed)
else
raise NotSetError.new(self.class.not_set_name,
not_set_required_variables)
end
end
private
def required_variable_names
%w(term)
end
def variables
super + ["term", "scheme"]
end
end
module AtomLink
def to_feed(feed, current)
link = feed.class::Link.new
set = setup_values(link)
if set
current.links << link
set_parent(link, current)
setup_other_elements(feed)
else
raise NotSetError.new(self.class.not_set_name,
not_set_required_variables)
end
end
private
def required_variable_names
%w(href)
end
end
module AtomGenerator
def to_feed(feed, current)
generator = current.class::Generator.new
if setup_values(generator)
current.generator = generator
set_parent(generator, current)
setup_other_elements(feed)
elsif variable_is_set?
raise NotSetError.new(self.class.not_set_name,
not_set_required_variables)
end
end
private
def required_variable_names
%w(content)
end
end
module AtomLogo
def to_feed(feed, current)
logo = current.class::Logo.new
class << logo
alias_method(:uri=, :content=)
end
set = setup_values(logo)
class << logo
remove_method(:uri=)
end
if set
current.logo = logo
set_parent(logo, current)
setup_other_elements(feed)
elsif variable_is_set?
raise NotSetError.new(self.class.not_set_name,
not_set_required_variables)
end
end
private
def required_variable_names
%w(uri)
end
end
end
end

File diff suppressed because it is too large Load diff

View file

@ -7,17 +7,8 @@ module RSS
def self.append_features(klass) def self.append_features(klass)
super super
::RSS::ContentModel::ELEMENTS.each do |element| ::RSS::ContentModel::ELEMENTS.each do |name|
klass.add_need_initialize_variable(element) klass.def_other_element(name)
klass.add_other_element(element)
klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
attr_accessor :#{element}
def setup_#{element}(rss, current)
if #{element} and current.respond_to?(:#{element}=)
current.#{element} = @#{element} if @#{element}
end
end
EOC
end end
end end
end end

View file

@ -15,60 +15,40 @@ module RSS
plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}" plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
full_plural_klass_name = "self.class::#{plural_klass_name}" full_plural_klass_name = "self.class::#{plural_klass_name}"
full_klass_name = "#{full_plural_klass_name}::#{klass_name}" full_klass_name = "#{full_plural_klass_name}::#{klass_name}"
klass.add_need_initialize_variable(full_plural_name, klass.def_classed_elements(full_name, "value", plural_klass_name,
"make_#{full_plural_name}") full_plural_name, name)
klass.add_other_element(full_plural_name) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
klass.module_eval(<<-EOC, __FILE__, __LINE__+1) def new_#{full_name}(value=nil)
attr_accessor :#{full_plural_name} _#{full_name} = #{full_plural_name}.new_#{name}
def make_#{full_plural_name} _#{full_name}.value = value
#{full_plural_klass_name}.new(@maker) if block_given?
yield _#{full_name}
else
_#{full_name}
end
end
EOC
end end
def setup_#{full_plural_name}(rss, current) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
@#{full_plural_name}.to_rss(rss, current) # For backward compatibility
end alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list
EOC
def #{full_name}
@#{full_plural_name}[0] and @#{full_plural_name}[0].value
end
def #{full_name}=(new_value)
@#{full_plural_name}[0] = #{full_klass_name}.new(self)
@#{full_plural_name}[0].value = new_value
end
EOC
end
end end
::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name| ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
plural_name ||= "#{name}s" plural_name ||= "#{name}s"
full_name ||= "#{DC_PREFIX}_#{name}"
full_plural_name ||= "#{DC_PREFIX}_#{plural_name}"
klass_name = Utils.to_class_name(name) klass_name = Utils.to_class_name(name)
full_klass_name = "DublinCore#{klass_name}"
plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}" plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
module_eval(<<-EOC, __FILE__, __LINE__) module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class #{plural_klass_name}Base class #{plural_klass_name}Base < Base
include Base def_array_element(#{name.dump}, #{full_plural_name.dump},
#{full_klass_name.dump})
def_array_element(#{plural_name.dump})
def new_#{name}
#{name} = self.class::#{klass_name}.new(self)
@#{plural_name} << #{name}
if block_given?
yield #{name}
else
#{name}
end
end
def to_rss(rss, current)
@#{plural_name}.each do |#{name}|
#{name}.to_rss(rss, current)
end
end
class #{klass_name}Base
include Base
class #{full_klass_name}Base < Base
attr_accessor :value attr_accessor :value
add_need_initialize_variable("value") add_need_initialize_variable("value")
alias_method(:content, :value) alias_method(:content, :value)
@ -77,8 +57,16 @@ EOC
def have_required_values? def have_required_values?
@value @value
end end
def to_feed(feed, current)
if value and current.respond_to?(:#{full_name})
new_item = current.class::#{full_klass_name}.new(value)
current.#{full_plural_name} << new_item
end end
end end
end
#{klass_name}Base = #{full_klass_name}Base
end
EOC EOC
end end
@ -86,18 +74,13 @@ EOC
::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name| ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
plural_name ||= "#{name}s" plural_name ||= "#{name}s"
klass_name = Utils.to_class_name(name) klass_name = Utils.to_class_name(name)
plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
full_klass_name = "DublinCore#{klass_name}" full_klass_name = "DublinCore#{klass_name}"
klass.module_eval(<<-EOC, *Utils.get_file_and_line_from_caller(1)) plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class #{plural_klass_name} < #{plural_klass_name}Base class #{plural_klass_name} < #{plural_klass_name}Base
class #{klass_name} < #{klass_name}Base class #{full_klass_name} < #{full_klass_name}Base
def to_rss(rss, current)
if value and current.respond_to?(:dc_#{name})
new_item = current.class::#{full_klass_name}.new(value)
current.dc_#{plural_name} << new_item
end
end
end end
#{klass_name} = #{full_klass_name}
end end
EOC EOC
end end
@ -106,47 +89,18 @@ EOC
class ChannelBase class ChannelBase
include DublinCoreModel include DublinCoreModel
remove_method(:date)
remove_method(:date=)
alias_method(:date, :dc_date)
alias_method(:date=, :dc_date=)
end end
class ImageBase; include DublinCoreModel; end class ImageBase; include DublinCoreModel; end
class ItemsBase class ItemsBase
class ItemBase class ItemBase
include DublinCoreModel include DublinCoreModel
remove_method(:date)
remove_method(:date=)
alias_method(:date, :dc_date)
alias_method(:date=, :dc_date=)
end end
end end
class TextinputBase; include DublinCoreModel; end class TextinputBase; include DublinCoreModel; end
class RSS10 makers.each do |maker|
class Channel maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
DublinCoreModel.install_dublin_core(self)
end
class Image
DublinCoreModel.install_dublin_core(self)
end
class Items
class Item
DublinCoreModel.install_dublin_core(self)
end
end
class Textinput
DublinCoreModel.install_dublin_core(self)
end
end
class RSS09
class Channel class Channel
DublinCoreModel.install_dublin_core(self) DublinCoreModel.install_dublin_core(self)
end end
@ -164,6 +118,7 @@ EOC
class Textinput class Textinput
DublinCoreModel.install_dublin_core(self) DublinCoreModel.install_dublin_core(self)
end end
EOC
end end
end end
end end

163
lib/rss/maker/entry.rb Normal file
View file

@ -0,0 +1,163 @@
require "rss/maker/atom"
require "rss/maker/feed"
module RSS
module Maker
module Atom
class Entry < RSSBase
def initialize
super("1.0")
@feed_type = "atom"
@feed_subtype = "entry"
end
private
def make_feed
::RSS::Atom::Entry.new(@version, @encoding, @standalone)
end
def setup_elements(entry)
setup_items(entry)
end
class Channel < ChannelBase
class SkipDays < SkipDaysBase
class Day < DayBase
end
end
class SkipHours < SkipHoursBase
class Hour < HourBase
end
end
class Cloud < CloudBase
end
Categories = Feed::Channel::Categories
Links = Feed::Channel::Links
Authors = Feed::Channel::Authors
Contributors = Feed::Channel::Contributors
class Generator < GeneratorBase
include AtomGenerator
def self.not_set_name
"maker.channel.generator"
end
end
Copyright = Feed::Channel::Copyright
class Description < DescriptionBase
end
Title = Feed::Channel::Title
end
class Image < ImageBase
end
class Items < ItemsBase
def to_feed(entry)
(normalize.first || Item.new(@maker)).to_feed(entry)
end
class Item < ItemBase
def to_feed(entry)
set_default_values do
setup_values(entry)
entry.dc_dates.clear
setup_other_elements(entry)
unless have_required_values?
raise NotSetError.new("maker.item", not_set_required_variables)
end
end
end
private
def required_variable_names
%w(id updated)
end
def variables
super + ["updated"]
end
def variable_is_set?
super or !authors.empty?
end
def not_set_required_variables
set_default_values do
vars = super
if authors.all? {|author| !author.have_required_values?}
vars << "author"
end
vars << "title" unless title {|t| t.have_required_values?}
vars
end
end
def _set_default_values(&block)
keep = {
:authors => authors.to_a.dup,
:contributors => contributors.to_a.dup,
:categories => categories.to_a.dup,
:id => id,
:links => links.to_a.dup,
:rights => @rights,
:title => @title,
:updated => updated,
}
authors.replace(@maker.channel.authors) if keep[:authors].empty?
if keep[:contributors].empty?
contributors.replace(@maker.channel.contributors)
end
if keep[:categories].empty?
categories.replace(@maker.channel.categories)
end
self.id ||= link || @maker.channel.id
links.replace(@maker.channel.links) if keep[:links].empty?
unless keep[:rights].variable_is_set?
@maker.channel.rights {|r| @rights = r}
end
unless keep[:title].variable_is_set?
@maker.channel.title {|t| @title = t}
end
self.updated ||= @maker.channel.updated
super(&block)
ensure
authors.replace(keep[:authors])
contributors.replace(keep[:contributors])
categories.replace(keep[:categories])
links.replace(keep[:links])
self.id = keep[:id]
@rights = keep[:rights]
@title = keep[:title]
self.updated = keep[:prev_updated]
end
Guid = Feed::Items::Item::Guid
Enclosure = Feed::Items::Item::Enclosure
Source = Feed::Items::Item::Source
Categories = Feed::Items::Item::Categories
Authors = Feed::Items::Item::Authors
Contributors = Feed::Items::Item::Contributors
Links = Feed::Items::Item::Links
Rights = Feed::Items::Item::Rights
Description = Feed::Items::Item::Description
Title = Feed::Items::Item::Title
Content = Feed::Items::Item::Content
end
end
class Textinput < TextinputBase
end
end
end
add_maker("atom:entry", Atom::Entry)
add_maker("atom1.0:entry", Atom::Entry)
end
end

429
lib/rss/maker/feed.rb Normal file
View file

@ -0,0 +1,429 @@
require "rss/maker/atom"
module RSS
module Maker
module Atom
class Feed < RSSBase
def initialize
super("1.0")
@feed_type = "atom"
@feed_subtype = "feed"
end
private
def make_feed
::RSS::Atom::Feed.new(@version, @encoding, @standalone)
end
def setup_elements(feed)
setup_channel(feed)
setup_image(feed)
setup_items(feed)
end
class Channel < ChannelBase
def to_feed(feed)
set_default_values do
setup_values(feed)
feed.dc_dates.clear
setup_other_elements(feed)
if image_favicon.about
icon = feed.class::Icon.new
icon.content = image_favicon.about
feed.icon = icon
end
unless have_required_values?
raise NotSetError.new("maker.channel",
not_set_required_variables)
end
end
end
def have_required_values?
super and
(!authors.empty? or
@maker.items.any? {|item| !item.authors.empty?})
end
private
def required_variable_names
%w(id updated)
end
def variables
super + %w(id updated)
end
def variable_is_set?
super or !authors.empty?
end
def not_set_required_variables
vars = super
if authors.empty? and
@maker.items.all? {|item| item.author.to_s.empty?}
vars << "author"
end
vars << "title" unless title {|t| t.have_required_values?}
vars
end
def _set_default_values(&block)
keep = {
:id => id,
:updated => updated,
}
self.id ||= about
self.updated ||= dc_date
super(&block)
ensure
self.id = keep[:id]
self.updated = keep[:updated]
end
class SkipDays < SkipDaysBase
def to_feed(*args)
end
class Day < DayBase
end
end
class SkipHours < SkipHoursBase
def to_feed(*args)
end
class Hour < HourBase
end
end
class Cloud < CloudBase
def to_feed(*args)
end
end
class Categories < CategoriesBase
class Category < CategoryBase
include AtomCategory
def self.not_set_name
"maker.channel.category"
end
end
end
class Links < LinksBase
class Link < LinkBase
include AtomLink
def self.not_set_name
"maker.channel.link"
end
end
end
AtomPersons.def_atom_persons(self, "author", "maker.channel.author")
AtomPersons.def_atom_persons(self, "contributor",
"maker.channel.contributor")
class Generator < GeneratorBase
include AtomGenerator
def self.not_set_name
"maker.channel.generator"
end
end
AtomTextConstruct.def_atom_text_construct(self, "rights",
"maker.channel.copyright",
"Copyright")
AtomTextConstruct.def_atom_text_construct(self, "subtitle",
"maker.channel.description",
"Description")
AtomTextConstruct.def_atom_text_construct(self, "title",
"maker.channel.title")
end
class Image < ImageBase
def to_feed(feed)
logo = feed.class::Logo.new
class << logo
alias_method(:url=, :content=)
end
set = setup_values(logo)
class << logo
remove_method(:url=)
end
if set
feed.logo = logo
set_parent(logo, feed)
setup_other_elements(feed, logo)
elsif variable_is_set?
raise NotSetError.new("maker.image", not_set_required_variables)
end
end
private
def required_variable_names
%w(url)
end
end
class Items < ItemsBase
def to_feed(feed)
normalize.each do |item|
item.to_feed(feed)
end
setup_other_elements(feed, feed.entries)
end
class Item < ItemBase
def to_feed(feed)
set_default_values do
entry = feed.class::Entry.new
set = setup_values(entry)
setup_other_elements(feed, entry)
if set
feed.entries << entry
set_parent(entry, feed)
elsif variable_is_set?
raise NotSetError.new("maker.item", not_set_required_variables)
end
end
end
def have_required_values?
set_default_values do
super and title {|t| t.have_required_values?}
end
end
private
def required_variable_names
%w(id updated)
end
def variables
super + ["updated"]
end
def not_set_required_variables
vars = super
vars << "title" unless title {|t| t.have_required_values?}
vars
end
def _set_default_values(&block)
keep = {
:id => id,
:updated => updated,
}
self.id ||= link
self.updated ||= dc_date
super(&block)
ensure
self.id = keep[:id]
self.updated = keep[:updated]
end
class Guid < GuidBase
def to_feed(feed, current)
end
end
class Enclosure < EnclosureBase
def to_feed(feed, current)
end
end
class Source < SourceBase
def to_feed(feed, current)
source = current.class::Source.new
setup_values(source)
current.source = source
set_parent(source, current)
setup_other_elements(feed, source)
current.source = nil if source.to_s == "<source/>"
end
private
def required_variable_names
[]
end
def variables
super + ["updated"]
end
AtomPersons.def_atom_persons(self, "author",
"maker.item.source.author")
AtomPersons.def_atom_persons(self, "contributor",
"maker.item.source.contributor")
class Categories < CategoriesBase
class Category < CategoryBase
include AtomCategory
def self.not_set_name
"maker.item.source.category"
end
end
end
class Generator < GeneratorBase
include AtomGenerator
def self.not_set_name
"maker.item.source.generator"
end
end
class Icon < IconBase
def to_feed(feed, current)
icon = current.class::Icon.new
class << icon
alias_method(:url=, :content=)
end
set = setup_values(icon)
class << icon
remove_method(:url=)
end
if set
current.icon = icon
set_parent(icon, current)
setup_other_elements(feed, icon)
elsif variable_is_set?
raise NotSetError.new("maker.item.source.icon",
not_set_required_variables)
end
end
private
def required_variable_names
%w(url)
end
end
class Links < LinksBase
class Link < LinkBase
include AtomLink
def self.not_set_name
"maker.item.source.link"
end
end
end
class Logo < LogoBase
include AtomLogo
def self.not_set_name
"maker.item.source.logo"
end
end
maker_name_base = "maker.item.source."
maker_name = "#{maker_name_base}rights"
AtomTextConstruct.def_atom_text_construct(self, "rights",
maker_name)
maker_name = "#{maker_name_base}subtitle"
AtomTextConstruct.def_atom_text_construct(self, "subtitle",
maker_name)
maker_name = "#{maker_name_base}title"
AtomTextConstruct.def_atom_text_construct(self, "title",
maker_name)
end
class Categories < CategoriesBase
class Category < CategoryBase
include AtomCategory
def self.not_set_name
"maker.item.category"
end
end
end
AtomPersons.def_atom_persons(self, "author", "maker.item.author")
AtomPersons.def_atom_persons(self, "contributor",
"maker.item.contributor")
class Links < LinksBase
class Link < LinkBase
include AtomLink
def self.not_set_name
"maker.item.link"
end
end
end
AtomTextConstruct.def_atom_text_construct(self, "rights",
"maker.item.rights")
AtomTextConstruct.def_atom_text_construct(self, "summary",
"maker.item.description",
"Description")
AtomTextConstruct.def_atom_text_construct(self, "title",
"maker.item.title")
class Content < ContentBase
def to_feed(feed, current)
content = current.class::Content.new
if setup_values(content)
content.src = nil if content.src and content.content
current.content = content
set_parent(content, current)
setup_other_elements(feed, content)
elsif variable_is_set?
raise NotSetError.new("maker.item.content",
not_set_required_variables)
end
end
alias_method(:xml, :xml_content)
private
def required_variable_names
if out_of_line?
%w(type)
elsif xml_type?
%w(xml_content)
else
%w(content)
end
end
def variables
if out_of_line?
super
elsif xml_type?
super + %w(xml)
else
super
end
end
def xml_type?
_type = type
return false if _type.nil?
_type == "xhtml" or
/(?:\+xml|\/xml)$/i =~ _type or
%w(text/xml-external-parsed-entity
application/xml-external-parsed-entity
application/xml-dtd).include?(_type.downcase)
end
end
end
end
class Textinput < TextinputBase
end
end
end
add_maker("atom", Atom::Feed)
add_maker("atom:feed", Atom::Feed)
add_maker("atom1.0", Atom::Feed)
add_maker("atom1.0:feed", Atom::Feed)
end
end

View file

@ -9,24 +9,18 @@ module RSS
super super
name = "#{RSS::IMAGE_PREFIX}_item" name = "#{RSS::IMAGE_PREFIX}_item"
klass.add_need_initialize_variable(name, "make_#{name}") klass.def_classed_element(name)
klass.add_other_element(name)
klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
attr_reader :#{name}
def setup_#{name}(rss, current)
if @#{name}
@#{name}.to_rss(rss, current)
end
end end
def make_#{name} def self.install_image_item(klass)
self.class::#{Utils.to_class_name(name)}.new(@maker) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class ImageItem < ImageItemBase
DublinCoreModel.install_dublin_core(self)
end end
EOC EOC
end end
class ImageItemBase class ImageItemBase < Base
include Base
include Maker::DublinCoreModel include Maker::DublinCoreModel
attr_accessor :about, :resource, :image_width, :image_height attr_accessor :about, :resource, :image_width, :image_height
@ -42,6 +36,15 @@ EOC
def have_required_values? def have_required_values?
@about @about
end end
def to_feed(feed, current)
if current.respond_to?(:image_item=) and have_required_values?
item = current.class::ImageItem.new
setup_values(item)
setup_other_elements(item)
current.image_item = item
end
end
end end
end end
@ -50,24 +53,18 @@ EOC
super super
name = "#{RSS::IMAGE_PREFIX}_favicon" name = "#{RSS::IMAGE_PREFIX}_favicon"
klass.add_need_initialize_variable(name, "make_#{name}") klass.def_classed_element(name)
klass.add_other_element(name)
klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
attr_reader :#{name}
def setup_#{name}(rss, current)
if @#{name}
@#{name}.to_rss(rss, current)
end
end end
def make_#{name} def self.install_image_favicon(klass)
self.class::#{Utils.to_class_name(name)}.new(@maker) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class ImageFavicon < ImageFaviconBase
DublinCoreModel.install_dublin_core(self)
end end
EOC EOC
end end
class ImageFaviconBase class ImageFaviconBase < Base
include Base
include Maker::DublinCoreModel include Maker::DublinCoreModel
attr_accessor :about, :image_size attr_accessor :about, :image_size
@ -79,6 +76,15 @@ EOC
def have_required_values? def have_required_values?
@about and @image_size @about and @image_size
end end
def to_feed(feed, current)
if current.respond_to?(:image_favicon=) and have_required_values?
favicon = current.class::ImageFavicon.new
setup_values(favicon)
setup_other_elements(favicon)
current.image_favicon = favicon
end
end
end end
end end
@ -88,58 +94,18 @@ EOC
class ItemBase; include Maker::ImageItemModel; end class ItemBase; include Maker::ImageItemModel; end
end end
class RSS10 makers.each do |maker|
maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class Channel
ImageFaviconModel.install_image_favicon(self)
end
class Items class Items
class Item class Item
class ImageItem < ImageItemBase ImageItemModel.install_image_item(self)
DublinCoreModel.install_dublin_core(self)
def to_rss(rss, current)
if @about
item = ::RSS::ImageItemModel::ImageItem.new(@about, @resource)
setup_values(item)
setup_other_elements(item)
current.image_item = item
end end
end end
EOC
end end
end end
end
class Channel
class ImageFavicon < ImageFaviconBase
DublinCoreModel.install_dublin_core(self)
def to_rss(rss, current)
if @about and @image_size
args = [@about, @image_size]
favicon = ::RSS::ImageFaviconModel::ImageFavicon.new(*args)
setup_values(favicon)
setup_other_elements(favicon)
current.image_favicon = favicon
end
end
end
end
end
class RSS09
class Items
class Item
class ImageItem < ImageItemBase
DublinCoreModel.install_dublin_core(self)
def to_rss(*args)
end
end
end
end
class Channel
class ImageFavicon < ImageFaviconBase
DublinCoreModel.install_dublin_core(self)
def to_rss(*args)
end
end
end
end
end
end end

242
lib/rss/maker/itunes.rb Normal file
View file

@ -0,0 +1,242 @@
require 'rss/itunes'
require 'rss/maker/2.0'
module RSS
module Maker
module ITunesBaseModel
def def_class_accessor(klass, name, type, *args)
name = name.gsub(/-/, "_").gsub(/^itunes_/, '')
full_name = "#{RSS::ITUNES_PREFIX}_#{name}"
case type
when nil
klass.def_other_element(full_name)
when :yes_other
def_yes_other_accessor(klass, full_name)
when :yes_clean_other
def_yes_clean_other_accessor(klass, full_name)
when :csv
def_csv_accessor(klass, full_name)
when :element, :attribute
recommended_attribute_name, = *args
klass_name = "ITunes#{Utils.to_class_name(name)}"
klass.def_classed_element(full_name, klass_name,
recommended_attribute_name)
when :elements
plural_name, recommended_attribute_name = args
plural_name ||= "#{name}s"
full_plural_name = "#{RSS::ITUNES_PREFIX}_#{plural_name}"
klass_name = "ITunes#{Utils.to_class_name(name)}"
plural_klass_name = "ITunes#{Utils.to_class_name(plural_name)}"
def_elements_class_accessor(klass, full_name, full_plural_name,
klass_name, plural_klass_name,
recommended_attribute_name)
end
end
def def_yes_other_accessor(klass, full_name)
klass.def_other_element(full_name)
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{full_name}?
Utils::YesOther.parse(@#{full_name})
end
EOC
end
def def_yes_clean_other_accessor(klass, full_name)
klass.def_other_element(full_name)
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{full_name}?
Utils::YesCleanOther.parse(#{full_name})
end
EOC
end
def def_csv_accessor(klass, full_name)
klass.def_csv_element(full_name)
end
def def_elements_class_accessor(klass, full_name, full_plural_name,
klass_name, plural_klass_name,
recommended_attribute_name=nil)
if recommended_attribute_name
klass.def_classed_elements(full_name, recommended_attribute_name,
plural_klass_name, full_plural_name)
else
klass.def_classed_element(full_plural_name, plural_klass_name)
end
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def new_#{full_name}(text=nil)
#{full_name} = @#{full_plural_name}.new_#{full_name}
#{full_name}.text = text
if block_given?
yield #{full_name}
else
#{full_name}
end
end
EOC
end
end
module ITunesChannelModel
extend ITunesBaseModel
class << self
def append_features(klass)
super
::RSS::ITunesChannelModel::ELEMENT_INFOS.each do |name, type, *args|
def_class_accessor(klass, name, type, *args)
end
end
end
class ITunesCategoriesBase < Base
def_array_element("category", "itunes_categories",
"ITunesCategory")
class ITunesCategoryBase < Base
attr_accessor :text
add_need_initialize_variable("text")
def_array_element("category", "itunes_categories",
"ITunesCategory")
def have_required_values?
text
end
alias_method :to_feed_for_categories, :to_feed
def to_feed(feed, current)
if text and current.respond_to?(:itunes_category)
new_item = current.class::ITunesCategory.new(text)
to_feed_for_categories(feed, new_item)
current.itunes_categories << new_item
end
end
end
end
class ITunesImageBase < Base
add_need_initialize_variable("href")
attr_accessor("href")
def to_feed(feed, current)
if @href and current.respond_to?(:itunes_image)
current.itunes_image ||= current.class::ITunesImage.new
current.itunes_image.href = @href
end
end
end
class ITunesOwnerBase < Base
%w(itunes_name itunes_email).each do |name|
add_need_initialize_variable(name)
attr_accessor(name)
end
def to_feed(feed, current)
if current.respond_to?(:itunes_owner=)
_not_set_required_variables = not_set_required_variables
if (required_variable_names - _not_set_required_variables).empty?
return
end
unless have_required_values?
raise NotSetError.new("maker.channel.itunes_owner",
_not_set_required_variables)
end
current.itunes_owner ||= current.class::ITunesOwner.new
current.itunes_owner.itunes_name = @itunes_name
current.itunes_owner.itunes_email = @itunes_email
end
end
private
def required_variable_names
%w(itunes_name itunes_email)
end
end
end
module ITunesItemModel
extend ITunesBaseModel
class << self
def append_features(klass)
super
::RSS::ITunesItemModel::ELEMENT_INFOS.each do |name, type, *args|
def_class_accessor(klass, name, type, *args)
end
end
end
class ITunesDurationBase < Base
attr_reader :content
add_need_initialize_variable("content")
%w(hour minute second).each do |name|
attr_reader(name)
add_need_initialize_variable(name, '0')
end
def content=(content)
if content.nil?
@hour, @minute, @second, @content = nil
else
@hour, @minute, @second =
::RSS::ITunesItemModel::ITunesDuration.parse(content)
@content = content
end
end
def hour=(hour)
@hour = Integer(hour)
update_content
end
def minute=(minute)
@minute = Integer(minute)
update_content
end
def second=(second)
@second = Integer(second)
update_content
end
def to_feed(feed, current)
if @content and current.respond_to?(:itunes_duration=)
current.itunes_duration ||= current.class::ITunesDuration.new
current.itunes_duration.content = @content
end
end
private
def update_content
components = [@hour, @minute, @second]
@content =
::RSS::ITunesItemModel::ITunesDuration.construct(*components)
end
end
end
class ChannelBase
include Maker::ITunesChannelModel
class ITunesCategories < ITunesCategoriesBase
class ITunesCategory < ITunesCategoryBase
ITunesCategory = self
end
end
class ITunesImage < ITunesImageBase; end
class ITunesOwner < ITunesOwnerBase; end
end
class ItemsBase
class ItemBase
include Maker::ITunesItemModel
class ITunesDuration < ITunesDurationBase; end
end
end
end
end

33
lib/rss/maker/slash.rb Normal file
View file

@ -0,0 +1,33 @@
require 'rss/slash'
require 'rss/maker/1.0'
module RSS
module Maker
module SlashModel
def self.append_features(klass)
super
::RSS::SlashModel::ELEMENT_INFOS.each do |name, type|
full_name = "#{RSS::SLASH_PREFIX}_#{name}"
case type
when :csv_integer
klass.def_csv_element(full_name, :integer)
else
klass.def_other_element(full_name)
end
end
klass.module_eval do
alias_method(:slash_hit_parades, :slash_hit_parade)
alias_method(:slash_hit_parades=, :slash_hit_parade=)
end
end
end
class ItemsBase
class ItemBase
include SlashModel
end
end
end
end

View file

@ -7,17 +7,8 @@ module RSS
def self.append_features(klass) def self.append_features(klass)
super super
::RSS::SyndicationModel::ELEMENTS.each do |element| ::RSS::SyndicationModel::ELEMENTS.each do |name|
klass.add_need_initialize_variable(element) klass.def_other_element(name)
klass.add_other_element(element)
klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
attr_accessor :#{element}
def setup_#{element}(rss, current)
if #{element} and current.respond_to?(:#{element}=)
current.#{element} = @#{element} if @#{element}
end
end
EOC
end end
end end
end end

View file

@ -8,24 +8,14 @@ module RSS
def self.append_features(klass) def self.append_features(klass)
super super
klass.add_need_initialize_variable("taxo_topics", "make_taxo_topics") klass.def_classed_element("#{RSS::TAXO_PREFIX}_topics",
klass.add_other_element("taxo_topics") "TaxonomyTopics")
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
attr_reader :taxo_topics
def make_taxo_topics
self.class::TaxonomyTopics.new(@maker)
end
def setup_taxo_topics(rss, current)
@taxo_topics.to_rss(rss, current)
end
EOC
end end
def self.install_taxo_topics(klass) def self.install_taxo_topics(klass)
klass.module_eval(<<-EOC, *Utils.get_file_and_line_from_caller(1)) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class TaxonomyTopics < TaxonomyTopicsBase class TaxonomyTopics < TaxonomyTopicsBase
def to_rss(rss, current) def to_feed(feed, current)
if current.respond_to?(:taxo_topics) if current.respond_to?(:taxo_topics)
topics = current.class::TaxonomyTopics.new topics = current.class::TaxonomyTopics.new
bag = topics.Bag bag = topics.Bag
@ -39,11 +29,10 @@ EOC
EOC EOC
end end
class TaxonomyTopicsBase class TaxonomyTopicsBase < Base
include Base
attr_reader :resources attr_reader :resources
def_array_element("resources") def_array_element("resource")
remove_method :new_resource
end end
end end
@ -51,77 +40,35 @@ EOC
def self.append_features(klass) def self.append_features(klass)
super super
klass.add_need_initialize_variable("taxo_topics", "make_taxo_topics") class_name = "TaxonomyTopics"
klass.add_other_element("taxo_topics") klass.def_classed_elements("#{TAXO_PREFIX}_topic", "value", class_name)
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
attr_reader :taxo_topics
def make_taxo_topics
self.class::TaxonomyTopics.new(@maker)
end
def setup_taxo_topics(rss, current)
@taxo_topics.to_rss(rss, current)
end
def taxo_topic
@taxo_topics[0] and @taxo_topics[0].value
end
def taxo_topic=(new_value)
@taxo_topic[0] = self.class::TaxonomyTopic.new(self)
@taxo_topic[0].value = new_value
end
EOC
end end
def self.install_taxo_topic(klass) def self.install_taxo_topic(klass)
klass.module_eval(<<-EOC, *Utils.get_file_and_line_from_caller(1)) klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class TaxonomyTopics < TaxonomyTopicsBase class TaxonomyTopics < TaxonomyTopicsBase
class TaxonomyTopic < TaxonomyTopicBase class TaxonomyTopic < TaxonomyTopicBase
DublinCoreModel.install_dublin_core(self) DublinCoreModel.install_dublin_core(self)
TaxonomyTopicsModel.install_taxo_topics(self) TaxonomyTopicsModel.install_taxo_topics(self)
def to_rss(rss, current) def to_feed(feed, current)
if current.respond_to?(:taxo_topics) if current.respond_to?(:taxo_topics)
topic = current.class::TaxonomyTopic.new(value) topic = current.class::TaxonomyTopic.new(value)
topic.taxo_link = value topic.taxo_link = value
taxo_topics.to_rss(rss, topic) if taxo_topics taxo_topics.to_feed(feed, topic) if taxo_topics
current.taxo_topics << topic current.taxo_topics << topic
setup_other_elements(rss) setup_other_elements(feed, topic)
end end
end end
def current_element(rss)
super.taxo_topics.last
end
end end
end end
EOC EOC
end end
class TaxonomyTopicsBase class TaxonomyTopicsBase < Base
include Base def_array_element("taxo_topic", nil, "TaxonomyTopic")
def_array_element("taxo_topics") class TaxonomyTopicBase < Base
def new_taxo_topic
taxo_topic = self.class::TaxonomyTopic.new(self)
@taxo_topics << taxo_topic
if block_given?
yield taxo_topic
else
taxo_topic
end
end
def to_rss(rss, current)
@taxo_topics.each do |taxo_topic|
taxo_topic.to_rss(rss, current)
end
end
class TaxonomyTopicBase
include Base
include DublinCoreModel include DublinCoreModel
include TaxonomyTopicsModel include TaxonomyTopicsModel
@ -151,21 +98,8 @@ EOC
end end
end end
class RSS10 makers.each do |maker|
TaxonomyTopicModel.install_taxo_topic(self) maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class Channel
TaxonomyTopicsModel.install_taxo_topics(self)
end
class Items
class Item
TaxonomyTopicsModel.install_taxo_topics(self)
end
end
end
class RSS09
TaxonomyTopicModel.install_taxo_topic(self) TaxonomyTopicModel.install_taxo_topic(self)
class Channel class Channel
@ -177,6 +111,7 @@ EOC
TaxonomyTopicsModel.install_taxo_topics(self) TaxonomyTopicsModel.install_taxo_topics(self)
end end
end end
EOC
end end
end end
end end

View file

@ -8,57 +8,15 @@ module RSS
def self.append_features(klass) def self.append_features(klass)
super super
name = "#{RSS::TRACKBACK_PREFIX}_ping" klass.def_other_element("#{RSS::TRACKBACK_PREFIX}_ping")
klass.add_need_initialize_variable(name) klass.def_classed_elements("#{RSS::TRACKBACK_PREFIX}_about", "value",
klass.add_other_element(name) "TrackBackAbouts")
klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
attr_accessor :#{name}
def setup_#{name}(rss, current)
if #{name} and current.respond_to?(:#{name}=)
current.#{name} = #{name}
end
end
EOC
name = "#{RSS::TRACKBACK_PREFIX}_abouts"
klass.add_need_initialize_variable(name, "make_#{name}")
klass.add_other_element(name)
klass.module_eval(<<-EOC, __FILE__, __LINE__+1)
attr_accessor :#{name}
def make_#{name}
self.class::TrackBackAbouts.new(self)
end end
def setup_#{name}(rss, current) class TrackBackAboutsBase < Base
@#{name}.to_rss(rss, current) def_array_element("about", nil, "TrackBackAbout")
end
EOC
end
class TrackBackAboutsBase
include Base
def_array_element("abouts")
def new_about
about = self.class::TrackBackAbout.new(@maker)
@abouts << about
if block_given?
yield about
else
about
end
end
def to_rss(rss, current)
@abouts.each do |about|
about.to_rss(rss, current)
end
end
class TrackBackAboutBase
include Base
class TrackBackAboutBase < Base
attr_accessor :value attr_accessor :value
add_need_initialize_variable("value") add_need_initialize_variable("value")
@ -71,6 +29,14 @@ module RSS
@value @value
end end
def to_feed(feed, current)
if current.respond_to?(:trackback_abouts) and have_required_values?
about = current.class::TrackBackAbout.new
setup_values(about)
setup_other_elements(about)
current.trackback_abouts << about
end
end
end end
end end
end end
@ -79,52 +45,17 @@ module RSS
class ItemBase; include TrackBackModel; end class ItemBase; include TrackBackModel; end
end end
class RSS10 makers.each do |maker|
maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class Items class Items
class Item class Item
class TrackBackAbouts < TrackBackAboutsBase class TrackBackAbouts < TrackBackAboutsBase
class TrackBackAbout < TrackBackAboutBase class TrackBackAbout < TrackBackAboutBase
def to_rss(rss, current)
if resource
about = ::RSS::TrackBackModel10::TrackBackAbout.new(resource)
current.trackback_abouts << about
end end
end end
end end
end end
EOC
end end
end end
end
class RSS09
class Items
class Item
class TrackBackAbouts < TrackBackAboutsBase
def to_rss(*args)
end
class TrackBackAbout < TrackBackAboutBase
end
end
end
end
end
class RSS20
class Items
class Item
class TrackBackAbouts < TrackBackAboutsBase
class TrackBackAbout < TrackBackAboutBase
def to_rss(rss, current)
if content
about = ::RSS::TrackBackModel20::TrackBackAbout.new(content)
current.trackback_abouts << about
end
end
end
end
end
end
end
end
end end

View file

@ -2,6 +2,7 @@ require "forwardable"
require "open-uri" require "open-uri"
require "rss/rss" require "rss/rss"
require "rss/xml"
module RSS module RSS
@ -118,7 +119,7 @@ module RSS
return rss if rss.is_a?(::URI::Generic) return rss if rss.is_a?(::URI::Generic)
begin begin
URI(rss) ::URI.parse(rss)
rescue ::URI::Error rescue ::URI::Error
rss rss
end end
@ -173,24 +174,28 @@ module RSS
class << self class << self
@@setters = {} @@accessor_bases = {}
@@registered_uris = {} @@registered_uris = {}
@@class_names = {} @@class_names = {}
# return the setter for the uri, tag_name pair, or nil. # return the setter for the uri, tag_name pair, or nil.
def setter(uri, tag_name) def setter(uri, tag_name)
begin _getter = getter(uri, tag_name)
@@setters[uri][tag_name] if _getter
rescue NameError "#{_getter}="
else
nil nil
end end
end end
def getter(uri, tag_name)
(@@accessor_bases[uri] || {})[tag_name]
end
# return the tag_names for setters associated with uri # return the tag_names for setters associated with uri
def available_tags(uri) def available_tags(uri)
begin begin
@@setters[uri].keys @@accessor_bases[uri].keys
rescue NameError rescue NameError
[] []
end end
@ -223,8 +228,8 @@ module RSS
end end
end end
def install_get_text_element(uri, name, setter) def install_get_text_element(uri, name, accessor_base)
install_setter(uri, name, setter) install_accessor_base(uri, name, accessor_base)
def_get_text_element(uri, name, *get_file_and_line_from_caller(1)) def_get_text_element(uri, name, *get_file_and_line_from_caller(1))
end end
@ -233,35 +238,31 @@ module RSS
end end
private private
# set the setter for the uri, tag_name pair # set the accessor for the uri, tag_name pair
def install_setter(uri, tag_name, setter) def install_accessor_base(uri, tag_name, accessor_base)
@@setters[uri] ||= {} @@accessor_bases[uri] ||= {}
@@setters[uri][tag_name] = setter @@accessor_bases[uri][tag_name] = accessor_base.chomp("=")
end end
def def_get_text_element(uri, name, file, line) def def_get_text_element(uri, element_name, file, line)
register_uri(uri, name) register_uri(uri, element_name)
unless private_instance_methods(false).include?("start_#{name}") method_name = "start_#{element_name}"
module_eval(<<-EOT, file, line) unless private_method_defined?(method_name)
def start_#{name}(name, prefix, attrs, ns) define_method(method_name) do |name, prefix, attrs, ns|
uri = _ns(ns, prefix) uri = _ns(ns, prefix)
if self.class.uri_registered?(uri, #{name.inspect}) if self.class.uri_registered?(uri, element_name)
start_get_text_element(name, prefix, ns, uri) start_get_text_element(name, prefix, ns, uri)
else else
start_else_element(name, prefix, attrs, ns) start_else_element(name, prefix, attrs, ns)
end end
end end
EOT private(method_name)
__send__("private", "start_#{name}")
end end
end end
end end
end end
module ListenerMixin module ListenerMixin
attr_reader :rss attr_reader :rss
attr_accessor :ignore_unknown_element attr_accessor :ignore_unknown_element
@ -271,13 +272,16 @@ module RSS
@rss = nil @rss = nil
@ignore_unknown_element = true @ignore_unknown_element = true
@do_validate = true @do_validate = true
@ns_stack = [{}] @ns_stack = [{"xml" => :xml}]
@tag_stack = [[]] @tag_stack = [[]]
@text_stack = [''] @text_stack = ['']
@proc_stack = [] @proc_stack = []
@last_element = nil @last_element = nil
@version = @encoding = @standalone = nil @version = @encoding = @standalone = nil
@xml_stylesheets = [] @xml_stylesheets = []
@xml_child_mode = false
@xml_element = nil
@last_xml_element = nil
end end
# set instance vars for version, encoding, standalone # set instance vars for version, encoding, standalone
@ -289,7 +293,7 @@ module RSS
if name == "xml-stylesheet" if name == "xml-stylesheet"
params = parse_pi_content(content) params = parse_pi_content(content)
if params.has_key?("href") if params.has_key?("href")
@xml_stylesheets << XMLStyleSheet.new(*params) @xml_stylesheets << XMLStyleSheet.new(params)
end end
end end
end end
@ -311,12 +315,41 @@ module RSS
prefix, local = split_name(name) prefix, local = split_name(name)
@tag_stack.last.push([_ns(ns, prefix), local]) @tag_stack.last.push([_ns(ns, prefix), local])
@tag_stack.push([]) @tag_stack.push([])
if respond_to?("start_#{local}", true) if @xml_child_mode
previous = @last_xml_element
element_attrs = attributes.dup
unless previous
ns.each do |ns_prefix, value|
next if ns_prefix == "xml"
key = ns_prefix.empty? ? "xmlns" : "xmlns:#{ns_prefix}"
element_attrs[key] ||= value
end
end
next_element = XML::Element.new(local,
prefix.empty? ? nil : prefix,
_ns(ns, prefix),
element_attrs)
previous << next_element if previous
@last_xml_element = next_element
pr = Proc.new do |text, tags|
if previous
@last_xml_element = previous
else
@xml_element = @last_xml_element
@last_xml_element = nil
end
end
@proc_stack.push(pr)
else
if @rss.nil? and respond_to?("initial_start_#{local}", true)
__send__("initial_start_#{local}", local, prefix, attrs, ns.dup)
elsif respond_to?("start_#{local}", true)
__send__("start_#{local}", local, prefix, attrs, ns.dup) __send__("start_#{local}", local, prefix, attrs, ns.dup)
else else
start_else_element(local, prefix, attrs, ns.dup) start_else_element(local, prefix, attrs, ns.dup)
end end
end end
end
def tag_end(name) def tag_end(name)
if DEBUG if DEBUG
@ -331,8 +364,12 @@ module RSS
end end
def text(data) def text(data)
if @xml_child_mode
@last_xml_element << data if @last_xml_element
else
@text_stack.last << data @text_stack.last << data
end end
end
private private
def _ns(ns, prefix) def _ns(ns, prefix)
@ -354,7 +391,8 @@ module RSS
def start_else_element(local, prefix, attrs, ns) def start_else_element(local, prefix, attrs, ns)
class_name = self.class.class_name(_ns(ns, prefix), local) class_name = self.class.class_name(_ns(ns, prefix), local)
current_class = @last_element.class current_class = @last_element.class
if current_class.constants.include?(class_name) if current_class.const_defined?(class_name) or
current_class.constants.include?(class_name)
next_class = current_class.const_get(class_name) next_class = current_class.const_get(class_name)
start_have_something_element(local, prefix, attrs, ns, next_class) start_have_something_element(local, prefix, attrs, ns, next_class)
else else
@ -377,19 +415,26 @@ module RSS
end end
def check_ns(tag_name, prefix, ns, require_uri) def check_ns(tag_name, prefix, ns, require_uri)
unless _ns(ns, prefix) == require_uri
if @do_validate if @do_validate
if _ns(ns, prefix) == require_uri
#ns.delete(prefix)
else
raise NSError.new(tag_name, prefix, require_uri) raise NSError.new(tag_name, prefix, require_uri)
else
# Force bind required URI with prefix
@ns_stack.last[prefix] = require_uri
end end
end end
end end
def start_get_text_element(tag_name, prefix, ns, required_uri) def start_get_text_element(tag_name, prefix, ns, required_uri)
@proc_stack.push Proc.new {|text, tags| pr = Proc.new do |text, tags|
setter = self.class.setter(required_uri, tag_name) setter = self.class.setter(required_uri, tag_name)
if @last_element.respond_to?(setter) if @last_element.respond_to?(setter)
if @do_validate
getter = self.class.getter(required_uri, tag_name)
if @last_element.__send__(getter)
raise TooMuchTagError.new(tag_name, @last_element.tag_name)
end
end
@last_element.__send__(setter, text.to_s) @last_element.__send__(setter, text.to_s)
else else
if @do_validate and !@ignore_unknown_element if @do_validate and !@ignore_unknown_element
@ -397,7 +442,8 @@ module RSS
@last_element.tag_name) @last_element.tag_name)
end end
end end
} end
@proc_stack.push(pr)
end end
def start_have_something_element(tag_name, prefix, attrs, ns, klass) def start_have_something_element(tag_name, prefix, attrs, ns, klass)
@ -438,16 +484,32 @@ module RSS
previous = @last_element previous = @last_element
next_element = klass.new(@do_validate, attributes) next_element = klass.new(@do_validate, attributes)
previous.instance_eval {set_next_element(tag_name, next_element)} previous.set_next_element(tag_name, next_element)
@last_element = next_element @last_element = next_element
@proc_stack.push Proc.new { |text, tags| @last_element.parent = previous if klass.need_parent?
@xml_child_mode = @last_element.have_xml_content?
pr = Proc.new do |text, tags|
p(@last_element.class) if DEBUG p(@last_element.class) if DEBUG
@last_element.content = text if klass.have_content? if @xml_child_mode
@last_element.content = @xml_element.to_s
xml_setter = @last_element.class.xml_setter
@last_element.__send__(xml_setter, @xml_element)
@xml_element = nil
@xml_child_mode = false
else
if klass.have_content?
if @last_element.need_base64_encode?
text = Base64.decode64(text.lstrip)
end
@last_element.content = text
end
end
if @do_validate if @do_validate
@last_element.validate_for_stream(tags, @ignore_unknown_element) @last_element.validate_for_stream(tags, @ignore_unknown_element)
end end
@last_element = previous @last_element = previous
} end
@proc_stack.push(pr)
end end
end end

25
lib/rss/prelude.rb Normal file
View file

@ -0,0 +1,25 @@
# Mutex
class Mutex
def synchronize
self.lock
begin
yield
ensure
self.unlock
end
end
end
# Thread
class Thread
MUTEX_FOR_THREAD_EXCLUSIVE = Mutex.new
def self.exclusive
MUTEX_FOR_THREAD_EXCLUSIVE.synchronize{
yield
}
end
end

View file

@ -12,10 +12,18 @@ class Time
(Z|[+-]\d\d:\d\d)?)? (Z|[+-]\d\d:\d\d)?)?
\s*\z/ix =~ date and (($5 and $8) or (!$5 and !$8)) \s*\z/ix =~ date and (($5 and $8) or (!$5 and !$8))
datetime = [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i] datetime = [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i]
datetime << $7.to_f * 1000000 if $7 usec = 0
if $8 usec = $7.to_f * 1000000 if $7
Time.utc(*datetime) - zone_offset($8) zone = $8
if zone
off = zone_offset(zone, datetime[0])
datetime = apply_offset(*(datetime + [off]))
datetime << usec
time = Time.utc(*datetime)
time.localtime unless zone_utc?(zone)
time
else else
datetime << usec
Time.local(*datetime) Time.local(*datetime)
end end
else else
@ -25,8 +33,15 @@ class Time
end end
end end
unless instance_methods.include?("w3cdtf") unless method_defined?(:w3cdtf)
alias w3cdtf iso8601 def w3cdtf
if usec.zero?
fraction_digits = 0
else
fraction_digits = Math.log10(usec.to_s.sub(/0*$/, '').to_i).floor + 1
end
xmlschema(fraction_digits)
end
end end
end end
@ -37,7 +52,7 @@ require "rss/xml-stylesheet"
module RSS module RSS
VERSION = "0.1.6" VERSION = "0.2.0"
URI = "http://purl.org/rss/1.0/" URI = "http://purl.org/rss/1.0/"
@ -137,16 +152,25 @@ module RSS
end end
end end
module BaseModel class UnsupportedMakerVersionError < Error
attr_reader :version
def initialize(version)
@version = version
super("Maker doesn't support version: #{@version}")
end
end
module BaseModel
include Utils include Utils
def install_have_child_element(tag_name, uri, occurs, name=nil) def install_have_child_element(tag_name, uri, occurs, name=nil, type=nil)
name ||= tag_name name ||= tag_name
add_need_initialize_variable(name) add_need_initialize_variable(name)
install_model(tag_name, uri, occurs, name) install_model(tag_name, uri, occurs, name)
attr_accessor name writer_type, reader_type = type
def_corresponded_attr_writer name, writer_type
def_corresponded_attr_reader name, reader_type
install_element(name) do |n, elem_name| install_element(name) do |n, elem_name|
<<-EOC <<-EOC
if @#{n} if @#{n}
@ -164,7 +188,7 @@ EOC
plural_name ||= "#{name}s" plural_name ||= "#{name}s"
add_have_children_element(name, plural_name) add_have_children_element(name, plural_name)
add_plural_form(name, plural_name) add_plural_form(name, plural_name)
install_model(tag_name, uri, occurs, plural_name) install_model(tag_name, uri, occurs, plural_name, true)
def_children_accessor(name, plural_name) def_children_accessor(name, plural_name)
install_element(name, "s") do |n, elem_name| install_element(name, "s") do |n, elem_name|
@ -179,20 +203,26 @@ EOC
end end
end end
def install_text_element(tag_name, uri, occurs, name=nil, type=nil, disp_name=nil) def install_text_element(tag_name, uri, occurs, name=nil, type=nil,
disp_name=nil)
name ||= tag_name name ||= tag_name
disp_name ||= name disp_name ||= name
self::ELEMENTS << name self::ELEMENTS << name
add_need_initialize_variable(name) add_need_initialize_variable(name)
install_model(tag_name, uri, occurs, name) install_model(tag_name, uri, occurs, name)
def_corresponded_attr_writer name, type, disp_name def_corresponded_attr_writer(name, type, disp_name)
convert_attr_reader name def_corresponded_attr_reader(name, type || :convert)
install_element(name) do |n, elem_name| install_element(name) do |n, elem_name|
<<-EOC <<-EOC
if @#{n} if respond_to?(:#{n}_content)
content = #{n}_content
else
content = @#{n}
end
if content
rv = "\#{indent}<#{elem_name}>" rv = "\#{indent}<#{elem_name}>"
value = html_escape(@#{n}) value = html_escape(content)
if need_convert if need_convert
rv << convert(value) rv << convert(value)
else else
@ -252,26 +282,112 @@ EOC
EOC EOC
end end
def convert_attr_reader(*attrs) def inherit_convert_attr_reader(*attrs)
attrs.each do |attr| attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer) attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, *get_file_and_line_from_caller(2)) module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{attr}_without_inherit
convert(@#{attr})
end
def #{attr} def #{attr}
if @converter if @#{attr}
@converter.convert(@#{attr}) #{attr}_without_inherit
elsif @parent
@parent.#{attr}
else else
@#{attr} nil
end end
end end
EOC EOC
end end
end end
def uri_convert_attr_reader(*attrs)
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{attr}_without_base
convert(@#{attr})
end
def #{attr}
value = #{attr}_without_base
return nil if value.nil?
if /\\A[a-z][a-z0-9+.\\-]*:/i =~ value
value
else
"\#{base}\#{value}"
end
end
EOC
end
end
def convert_attr_reader(*attrs)
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{attr}
convert(@#{attr})
end
EOC
end
end
def yes_clean_other_attr_reader(*attrs)
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
attr_reader(:#{attr})
def #{attr}?
YesCleanOther.parse(@#{attr})
end
EOC
end
end
def yes_other_attr_reader(*attrs)
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
attr_reader(:#{attr})
def #{attr}?
Utils::YesOther.parse(@#{attr})
end
EOC
end
end
def csv_attr_reader(*attrs)
separator = nil
if attrs.last.is_a?(Hash)
options = attrs.pop
separator = options[:separator]
end
separator ||= ", "
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
attr_reader(:#{attr})
def #{attr}_content
if @#{attr}.nil?
@#{attr}
else
@#{attr}.join(#{separator.dump})
end
end
EOC
end
end
def date_writer(name, type, disp_name=name) def date_writer(name, type, disp_name=name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2)) module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{name}=(new_value) def #{name}=(new_value)
if new_value.nil? or new_value.kind_of?(Time) if new_value.nil?
@#{name} = new_value @#{name} = new_value
elsif new_value.kind_of?(Time)
@#{name} = new_value.dup
else else
if @do_validate if @do_validate
begin begin
@ -283,7 +399,9 @@ EOC
@#{name} = nil @#{name} = nil
if /\\A\\s*\\z/ !~ new_value.to_s if /\\A\\s*\\z/ !~ new_value.to_s
begin begin
unless Date._parse(new_value, false).empty?
@#{name} = Time.parse(new_value) @#{name} = Time.parse(new_value)
end
rescue ArgumentError rescue ArgumentError
end end
end end
@ -364,6 +482,68 @@ EOC
EOC EOC
end end
def text_type_writer(name, disp_name=name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{name}=(new_value)
if @do_validate and
!["text", "html", "xhtml", nil].include?(new_value)
raise NotAvailableValueError.new('#{disp_name}', new_value)
end
@#{name} = new_value
end
EOC
end
def content_writer(name, disp_name=name)
klass_name = "self.class::#{Utils.to_class_name(name)}"
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{name}=(new_value)
if new_value.is_a?(#{klass_name})
@#{name} = new_value
else
@#{name} = #{klass_name}.new
@#{name}.content = new_value
end
end
EOC
end
def yes_clean_other_writer(name, disp_name=name)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{name}=(value)
value = (value ? "yes" : "no") if [true, false].include?(value)
@#{name} = value
end
EOC
end
def yes_other_writer(name, disp_name=name)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{name}=(new_value)
if [true, false].include?(new_value)
new_value = new_value ? "yes" : "no"
end
@#{name} = new_value
end
EOC
end
def csv_writer(name, disp_name=name)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{name}=(new_value)
@#{name} = Utils::CSV.parse(new_value)
end
EOC
end
def csv_integer_writer(name, disp_name=name)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{name}=(new_value)
@#{name} = Utils::CSV.parse(new_value) {|v| Integer(v)}
end
EOC
end
def def_children_accessor(accessor_name, plural_name) def def_children_accessor(accessor_name, plural_name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2)) module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{plural_name} def #{plural_name}
@ -379,10 +559,12 @@ EOC
end end
def #{accessor_name}=(*args) def #{accessor_name}=(*args)
receiver = self.class.name
warn("Warning:\#{caller.first.sub(/:in `.*'\z/, '')}: " \ warn("Warning:\#{caller.first.sub(/:in `.*'\z/, '')}: " \
"Don't use `#{accessor_name} = XXX'/`set_#{accessor_name}(XXX)'. " \ "Don't use `\#{receiver}\##{accessor_name} = XXX'/" \
"`\#{receiver}\#set_#{accessor_name}(XXX)'. " \
"Those APIs are not sense of Ruby. " \ "Those APIs are not sense of Ruby. " \
"Use `#{plural_name} << XXX' instead of them.") "Use `\#{receiver}\##{plural_name} << XXX' instead of them.")
if args.size == 1 if args.size == 1
@#{accessor_name}.push(args[0]) @#{accessor_name}.push(args[0])
else else
@ -394,10 +576,61 @@ EOC
end end
end end
class Element module SetupMaker
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 maker_target(maker)
nil
end
def setup_maker_attributes(target)
end
def setup_maker_element(target)
self.class.need_initialize_variables.each do |var|
value = __send__(var)
next if value.nil?
if value.respond_to?("setup_maker") and
!not_need_to_call_setup_maker_variables.include?(var)
value.setup_maker(target)
else
setter = "#{var}="
if target.respond_to?(setter)
target.__send__(setter, value)
end
end
end
end
def not_need_to_call_setup_maker_variables
[]
end
def setup_maker_elements(parent)
self.class.have_children_elements.each do |name, plural_name|
if parent.respond_to?(plural_name)
target = parent.__send__(plural_name)
__send__(plural_name).each do |elem|
elem.setup_maker(target)
end
end
end
end
end
class Element
extend BaseModel extend BaseModel
include Utils include Utils
extend Utils::InheritedReader
include SetupMaker
INDENT = " " INDENT = " "
@ -410,29 +643,31 @@ EOC
PLURAL_FORMS = {} PLURAL_FORMS = {}
class << self class << self
def must_call_validators def must_call_validators
MUST_CALL_VALIDATORS inherited_hash_reader("MUST_CALL_VALIDATORS")
end end
def models def models
MODELS inherited_array_reader("MODELS")
end end
def get_attributes def get_attributes
GET_ATTRIBUTES inherited_array_reader("GET_ATTRIBUTES")
end end
def have_children_elements def have_children_elements
HAVE_CHILDREN_ELEMENTS inherited_array_reader("HAVE_CHILDREN_ELEMENTS")
end end
def to_element_methods def to_element_methods
TO_ELEMENT_METHODS inherited_array_reader("TO_ELEMENT_METHODS")
end end
def need_initialize_variables def need_initialize_variables
NEED_INITIALIZE_VARIABLES inherited_array_reader("NEED_INITIALIZE_VARIABLES")
end end
def plural_forms def plural_forms
PLURAL_FORMS inherited_hash_reader("PLURAL_FORMS")
end end
def inherited_base
::RSS::Element
end
def inherited(klass) def inherited(klass)
klass.const_set("MUST_CALL_VALIDATORS", {}) klass.const_set("MUST_CALL_VALIDATORS", {})
@ -443,64 +678,42 @@ EOC
klass.const_set("NEED_INITIALIZE_VARIABLES", []) klass.const_set("NEED_INITIALIZE_VARIABLES", [])
klass.const_set("PLURAL_FORMS", {}) klass.const_set("PLURAL_FORMS", {})
klass.module_eval(<<-EOC) tag_name = klass.name.split(/::/).last
public tag_name[0, 1] = tag_name[0, 1].downcase
klass.instance_variable_set("@tag_name", tag_name)
@tag_name = name.split(/::/).last klass.instance_variable_set("@have_content", false)
@tag_name[0,1] = @tag_name[0,1].downcase
@have_content = false
def self.must_call_validators
super.merge(MUST_CALL_VALIDATORS)
end
def self.models
MODELS + super
end
def self.get_attributes
GET_ATTRIBUTES + super
end
def self.have_children_elements
HAVE_CHILDREN_ELEMENTS + super
end
def self.to_element_methods
TO_ELEMENT_METHODS + super
end
def self.need_initialize_variables
NEED_INITIALIZE_VARIABLES + super
end
def self.plural_forms
super.merge(PLURAL_FORMS)
end end
def install_must_call_validator(prefix, uri)
def self.install_must_call_validator(prefix, uri) self::MUST_CALL_VALIDATORS[uri] = prefix
MUST_CALL_VALIDATORS[uri] = prefix
end end
def self.install_model(tag, uri, occurs=nil, getter=nil) def install_model(tag, uri, occurs=nil, getter=nil, plural=false)
getter ||= tag getter ||= tag
if m = MODELS.find {|t, u, o, g| t == tag and u == uri} if m = self::MODELS.find {|t, u, o, g, p| t == tag and u == uri}
m[2] = occurs m[2] = occurs
else else
MODELS << [tag, uri, occurs, getter] self::MODELS << [tag, uri, occurs, getter, plural]
end end
end end
def self.install_get_attribute(name, uri, required=true, def install_get_attribute(name, uri, required=true,
type=nil, disp_name=nil, type=nil, disp_name=nil,
element_name=nil) element_name=nil)
disp_name ||= name disp_name ||= name
element_name ||= name element_name ||= name
def_corresponded_attr_writer name, type, disp_name writer_type, reader_type = type
convert_attr_reader name def_corresponded_attr_writer name, writer_type, disp_name
def_corresponded_attr_reader name, reader_type
if type == :boolean and /^is/ =~ name if type == :boolean and /^is/ =~ name
alias_method "\#{$POSTMATCH}?", name alias_method "#{$POSTMATCH}?", name
end end
GET_ATTRIBUTES << [name, uri, required, element_name] self::GET_ATTRIBUTES << [name, uri, required, element_name]
add_need_initialize_variable(disp_name) add_need_initialize_variable(disp_name)
end end
def self.def_corresponded_attr_writer(name, type=nil, disp_name=name) def def_corresponded_attr_writer(name, type=nil, disp_name=nil)
disp_name ||= name
case type case type
when :integer when :integer
integer_writer name, disp_name integer_writer name, disp_name
@ -510,38 +723,67 @@ EOC
boolean_writer name, disp_name boolean_writer name, disp_name
when :w3cdtf, :rfc822, :rfc2822 when :w3cdtf, :rfc822, :rfc2822
date_writer name, type, disp_name date_writer name, type, disp_name
when :text_type
text_type_writer name, disp_name
when :content
content_writer name, disp_name
when :yes_clean_other
yes_clean_other_writer name, disp_name
when :yes_other
yes_other_writer name, disp_name
when :csv
csv_writer name
when :csv_integer
csv_integer_writer name
else else
attr_writer name attr_writer name
end end
end end
def self.content_setup(type=nil) def def_corresponded_attr_reader(name, type=nil)
def_corresponded_attr_writer "content", type case type
convert_attr_reader :content when :inherit
inherit_convert_attr_reader name
when :uri
uri_convert_attr_reader name
when :yes_clean_other
yes_clean_other_attr_reader name
when :yes_other
yes_other_attr_reader name
when :csv
csv_attr_reader name
when :csv_integer
csv_attr_reader name, :separator => ","
else
convert_attr_reader name
end
end
def content_setup(type=nil, disp_name=nil)
writer_type, reader_type = type
def_corresponded_attr_writer :content, writer_type, disp_name
def_corresponded_attr_reader :content, reader_type
@have_content = true @have_content = true
end end
def self.have_content? def have_content?
@have_content @have_content
end end
def self.add_have_children_element(variable_name, plural_name) def add_have_children_element(variable_name, plural_name)
HAVE_CHILDREN_ELEMENTS << [variable_name, plural_name] self::HAVE_CHILDREN_ELEMENTS << [variable_name, plural_name]
end end
def self.add_to_element_method(method_name) def add_to_element_method(method_name)
TO_ELEMENT_METHODS << method_name self::TO_ELEMENT_METHODS << method_name
end end
def self.add_need_initialize_variable(variable_name) def add_need_initialize_variable(variable_name)
NEED_INITIALIZE_VARIABLES << variable_name self::NEED_INITIALIZE_VARIABLES << variable_name
end end
def self.add_plural_form(singular, plural) def add_plural_form(singular, plural)
PLURAL_FORMS[singular] = plural self::PLURAL_FORMS[singular] = plural
end
EOC
end end
def required_prefix def required_prefix
@ -552,6 +794,10 @@ EOC
"" ""
end end
def need_parent?
false
end
def install_ns(prefix, uri) def install_ns(prefix, uri)
if self::NSPOOL.has_key?(prefix) if self::NSPOOL.has_key?(prefix)
raise OverlappedPrefixError.new(prefix) raise OverlappedPrefixError.new(prefix)
@ -564,12 +810,16 @@ EOC
end end
end end
attr_accessor :do_validate attr_accessor :parent, :do_validate
def initialize(do_validate=true, attrs={}) def initialize(do_validate=true, attrs=nil)
@parent = nil
@converter = nil @converter = nil
if attrs.nil? and (do_validate.is_a?(Hash) or do_validate.is_a?(Array))
do_validate, attrs = true, do_validate
end
@do_validate = do_validate @do_validate = do_validate
initialize_variables(attrs) initialize_variables(attrs || {})
end end
def tag_name def tag_name
@ -599,9 +849,20 @@ EOC
end end
end end
def valid?(ignore_unknown_element=true)
validate(ignore_unknown_element)
true
rescue RSS::Error
false
end
def validate(ignore_unknown_element=true) def validate(ignore_unknown_element=true)
do_validate = @do_validate
@do_validate = true
validate_attribute validate_attribute
__validate(ignore_unknown_element) __validate(ignore_unknown_element)
ensure
@do_validate = do_validate
end end
def validate_for_stream(tags, ignore_unknown_element=true) def validate_for_stream(tags, ignore_unknown_element=true)
@ -609,20 +870,15 @@ EOC
__validate(ignore_unknown_element, tags, false) __validate(ignore_unknown_element, tags, false)
end 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
def to_s(need_convert=true, indent='') def to_s(need_convert=true, indent='')
if self.class.have_content? if self.class.have_content?
return "" unless @content return "" if !empty_content? and !content_is_set?
rv = tag(indent) do |next_indent| rv = tag(indent) do |next_indent|
h(@content) if empty_content?
""
else
xmled_content
end
end end
else else
rv = tag(indent) do |next_indent| rv = tag(indent) do |next_indent|
@ -635,6 +891,44 @@ EOC
rv rv
end end
def have_xml_content?
false
end
def need_base64_encode?
false
end
def set_next_element(tag_name, next_element)
klass = next_element.class
prefix = ""
prefix << "#{klass.required_prefix}_" if klass.required_prefix
key = "#{prefix}#{tag_name.gsub(/-/, '_')}"
if self.class.plural_forms.has_key?(key)
ary = __send__("#{self.class.plural_forms[key]}")
ary << next_element
else
__send__("#{key}=", next_element)
end
end
protected
def have_required_elements?
self.class::MODELS.all? do |tag, uri, occurs, getter|
if occurs.nil? or occurs == "+"
child = __send__(getter)
if child.is_a?(Array)
children = child
children.any? {|c| c.have_required_elements?}
else
!child.to_s.empty?
end
else
true
end
end
end
private private
def initialize_variables(attrs) def initialize_variables(attrs)
normalized_attrs = {} normalized_attrs = {}
@ -646,16 +940,16 @@ EOC
if value if value
__send__("#{variable_name}=", value) __send__("#{variable_name}=", value)
else else
instance_eval("@#{variable_name} = nil") instance_variable_set("@#{variable_name}", nil)
end end
end end
initialize_have_children_elements initialize_have_children_elements
@content = "" if self.class.have_content? @content = normalized_attrs["content"] if self.class.have_content?
end end
def initialize_have_children_elements def initialize_have_children_elements
self.class.have_children_elements.each do |variable_name, plural_name| self.class.have_children_elements.each do |variable_name, plural_name|
instance_eval("@#{variable_name} = []") instance_variable_set("@#{variable_name}", [])
end end
end end
@ -665,8 +959,10 @@ EOC
attrs = collect_attrs attrs = collect_attrs
return "" if attrs.nil? return "" if attrs.nil?
return "" unless have_required_elements?
attrs.update(additional_attrs) attrs.update(additional_attrs)
start_tag = make_start_tag(indent, next_indent, attrs) start_tag = make_start_tag(indent, next_indent, attrs.dup)
if block if block
content = block.call(next_indent) content = block.call(next_indent)
@ -681,6 +977,7 @@ EOC
else else
content = content.reject{|x| x.empty?} content = content.reject{|x| x.empty?}
if content.empty? if content.empty?
return "" if attrs.empty?
end_tag = "/>" end_tag = "/>"
else else
start_tag << ">\n" start_tag << ">\n"
@ -722,56 +1019,6 @@ EOC
'' ''
end 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|
value = __send__(var)
if value.respond_to?("setup_maker") and
!not_need_to_call_setup_maker_variables.include?(var)
value.setup_maker(target)
else
setter = "#{var}="
if target.respond_to?(setter)
target.__send__(setter, value)
end
end
end
end
def not_need_to_call_setup_maker_variables
[]
end
def setup_maker_elements(parent)
self.class.have_children_elements.each do |name, plural_name|
if parent.respond_to?(plural_name)
target = parent.__send__(plural_name)
__send__(plural_name).each do |elem|
elem.setup_maker(target)
end
end
end
end
def set_next_element(tag_name, next_element)
klass = next_element.class
prefix = ""
prefix << "#{klass.required_prefix}_" if klass.required_prefix
key = "#{prefix}#{tag_name}"
if self.class.plural_forms.has_key?(key)
ary = __send__("#{self.class.plural_forms[key]}")
ary << next_element
else
__send__("#{prefix}#{tag_name}=", next_element)
end
end
def children def children
rv = [] rv = []
self.class.models.each do |name, uri, occurs, getter| self.class.models.each do |name, uri, occurs, getter|
@ -787,10 +1034,10 @@ EOC
def _tags def _tags
rv = [] rv = []
self.class.models.each do |name, uri, occurs, getter| self.class.models.each do |name, uri, occurs, getter, plural|
value = __send__(getter) value = __send__(getter)
next if value.nil? next if value.nil?
if value.is_a?(Array) if plural and value.is_a?(Array)
rv.concat([[uri, name]] * value.size) rv.concat([[uri, name]] * value.size)
else else
rv << [uri, name] rv << [uri, name]
@ -817,7 +1064,7 @@ EOC
must_call_validators.each do |uri, prefix| must_call_validators.each do |uri, prefix|
_validate(ignore_unknown_element, tags[uri], uri) _validate(ignore_unknown_element, tags[uri], uri)
meth = "#{prefix}_validate" meth = "#{prefix}_validate"
if respond_to?(meth, true) if !prefix.empty? and respond_to?(meth, true)
__send__(meth, ignore_unknown_element, tags[uri], uri) __send__(meth, ignore_unknown_element, tags[uri], uri)
end end
end end
@ -825,9 +1072,11 @@ EOC
def validate_attribute def validate_attribute
_attrs.each do |a_name, required, alias_name| _attrs.each do |a_name, required, alias_name|
if required and __send__(alias_name || a_name).nil? value = instance_variable_get("@#{alias_name || a_name}")
if required and value.nil?
raise MissingAttributeError.new(tag_name, a_name) raise MissingAttributeError.new(tag_name, a_name)
end end
__send__("#{alias_name || a_name}=", value)
end end
end end
@ -843,6 +1092,7 @@ EOC
tags = tags.sort_by {|x| element_names.index(x) || tags_size} tags = tags.sort_by {|x| element_names.index(x) || tags_size}
end end
_tags = tags.dup if tags
models.each_with_index do |model, i| models.each_with_index do |model, i|
name, model_uri, occurs, getter = model name, model_uri, occurs, getter = model
@ -933,6 +1183,27 @@ EOC
rv rv
end end
def empty_content?
false
end
def content_is_set?
if have_xml_content?
__send__(self.class.xml_getter)
else
content
end
end
def xmled_content
if have_xml_content?
__send__(self.class.xml_getter).to_s
else
_content = content
_content = Base64.encode64(_content) if need_base64_encode?
h(_content)
end
end
end end
module RootElementMixin module RootElementMixin
@ -940,16 +1211,23 @@ EOC
include XMLStyleSheetMixin include XMLStyleSheetMixin
attr_reader :output_encoding attr_reader :output_encoding
attr_reader :feed_type, :feed_subtype, :feed_version
def initialize(rss_version, version=nil, encoding=nil, standalone=nil) attr_accessor :version, :encoding, :standalone
def initialize(feed_version, version=nil, encoding=nil, standalone=nil)
super() super()
@rss_version = rss_version @feed_type = nil
@feed_subtype = nil
@feed_version = feed_version
@version = version || '1.0' @version = version || '1.0'
@encoding = encoding @encoding = encoding
@standalone = standalone @standalone = standalone
@output_encoding = nil @output_encoding = nil
end end
def feed_info
[@feed_type, @feed_version, @feed_subtype]
end
def output_encoding=(enc) def output_encoding=(enc)
@output_encoding = enc @output_encoding = enc
self.converter = Converter.new(@output_encoding, @encoding) self.converter = Converter.new(@output_encoding, @encoding)
@ -964,25 +1242,48 @@ EOC
xss.setup_maker(maker) xss.setup_maker(maker)
end end
setup_maker_elements(maker) super
end end
def to_xml(version=nil, &block) def to_feed(type, &block)
if version.nil? or version == @rss_version Maker.make(type) do |maker|
to_s
else
RSS::Maker.make(version) do |maker|
setup_maker(maker) setup_maker(maker)
block.call(maker) if block block.call(maker) if block
end.to_s end
end
def to_rss(type, &block)
to_feed("rss#{type}", &block)
end
def to_atom(type, &block)
to_feed("atom:#{type}", &block)
end
def to_xml(type=nil, &block)
if type.nil? or same_feed_type?(type)
to_s
else
to_feed(type, &block).to_s
end end
end end
private private
def same_feed_type?(type)
if /^(atom|rss)?(\d+\.\d+)?(?::(.+))?$/i =~ type
feed_type = ($1 || @feed_type).downcase
feed_version = $2 || @feed_version
feed_subtype = $3 || @feed_subtype
[feed_type, feed_version, feed_subtype] == feed_info
else
false
end
end
def tag(indent, attrs={}, &block) def tag(indent, attrs={}, &block)
rv = xmldecl + xml_stylesheet_pi rv = super(indent, ns_declarations.merge(attrs), &block)
rv << super(indent, ns_declarations.merge(attrs), &block) return rv if rv.empty?
rv "#{xmldecl}#{xml_stylesheet_pi}#{rv}"
end end
def xmldecl def xmldecl
@ -1004,12 +1305,8 @@ EOC
decls decls
end end
def setup_maker_elements(maker) def maker_target(target)
channel.setup_maker(maker) if channel target
image.setup_maker(maker) if image
textinput.setup_maker(maker) if textinput
super(maker)
end end
end end
end end

49
lib/rss/slash.rb Normal file
View file

@ -0,0 +1,49 @@
require 'rss/1.0'
module RSS
SLASH_PREFIX = 'slash'
SLASH_URI = "http://purl.org/rss/1.0/modules/slash/"
RDF.install_ns(SLASH_PREFIX, SLASH_URI)
module SlashModel
extend BaseModel
ELEMENT_INFOS = \
[
["section"],
["department"],
["comments", :positive_integer],
["hit_parade", :csv_integer],
]
class << self
def append_features(klass)
super
return if klass.instance_of?(Module)
klass.install_must_call_validator(SLASH_PREFIX, SLASH_URI)
ELEMENT_INFOS.each do |name, type, *additional_infos|
full_name = "#{SLASH_PREFIX}_#{name}"
klass.install_text_element(full_name, SLASH_URI, "?",
full_name, type, name)
end
klass.module_eval do
alias_method(:slash_hit_parades, :slash_hit_parade)
undef_method(:slash_hit_parade)
alias_method(:slash_hit_parade, :slash_hit_parade_content)
end
end
end
end
class RDF
class Item; include SlashModel; end
end
SlashModel::ELEMENT_INFOS.each do |name, type|
accessor_base = "#{SLASH_PREFIX}_#{name}"
BaseListener.install_get_text_element(SLASH_URI, name, accessor_base)
end
end

View file

@ -29,16 +29,19 @@ module RSS
%w(updateBase).each do |name| %w(updateBase).each do |name|
install_date_element(name, SY_URI, "?", install_date_element(name, SY_URI, "?",
"#{SY_PREFIX}_#{name}", 'w3cdtf', name) "#{SY_PREFIX}_#{name}", 'w3cdtf',
"#{SY_PREFIX}:#{name}")
end
end end
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
alias_method(:_sy_updatePeriod=, :sy_updatePeriod=) alias_method(:_sy_updatePeriod=, :sy_updatePeriod=)
def sy_updatePeriod=(new_value) def sy_updatePeriod=(new_value)
new_value = new_value.strip new_value = new_value.strip
validate_sy_updatePeriod(new_value) if @do_validate validate_sy_updatePeriod(new_value) if @do_validate
self._sy_updatePeriod = new_value self._sy_updatePeriod = new_value
end end
end EOC
end end
private private
@ -58,7 +61,7 @@ module RSS
SyndicationModel::ELEMENTS.uniq! SyndicationModel::ELEMENTS.uniq!
SyndicationModel::ELEMENTS.each do |full_name| SyndicationModel::ELEMENTS.each do |full_name|
name = full_name[prefix_size..-1] name = full_name[prefix_size..-1]
BaseListener.install_get_text_element(SY_URI, name, "#{full_name}=") BaseListener.install_get_text_element(SY_URI, name, full_name)
end end
end end

View file

@ -12,7 +12,7 @@ module RSS
%w(link).each do |name| %w(link).each do |name|
full_name = "#{TAXO_PREFIX}_#{name}" full_name = "#{TAXO_PREFIX}_#{name}"
BaseListener.install_get_text_element(TAXO_URI, name, "#{full_name}=") BaseListener.install_get_text_element(TAXO_URI, name, full_name)
TAXO_ELEMENTS << "#{TAXO_PREFIX}_#{name}" TAXO_ELEMENTS << "#{TAXO_PREFIX}_#{name}"
end end

View file

@ -4,14 +4,16 @@ module RSS
# Convert a name_with_underscores to CamelCase. # Convert a name_with_underscores to CamelCase.
def to_class_name(name) def to_class_name(name)
name.split(/_/).collect do |part| name.split(/[_\-]/).collect do |part|
"#{part[0, 1].upcase}#{part[1..-1]}" "#{part[0, 1].upcase}#{part[1..-1]}"
end.join("") end.join("")
end end
def get_file_and_line_from_caller(i=0) def get_file_and_line_from_caller(i=0)
file, line, = caller[i].split(':') file, line, = caller[i].split(':')
[file, line.to_i] line = line.to_i
line += 1 if i.zero?
[file, line]
end end
# escape '&', '"', '<' and '>' for use in HTML. # escape '&', '"', '<' and '>' for use in HTML.
@ -33,5 +35,77 @@ module RSS
def element_initialize_arguments?(args) def element_initialize_arguments?(args)
[true, false].include?(args[0]) and args[1].is_a?(Hash) [true, false].include?(args[0]) and args[1].is_a?(Hash)
end end
module YesCleanOther
module_function
def parse(value)
if [true, false, nil].include?(value)
value
else
case value.to_s
when /\Ayes\z/i
true
when /\Aclean\z/i
false
else
nil
end
end
end
end
module YesOther
module_function
def parse(value)
if [true, false].include?(value)
value
else
/\Ayes\z/i.match(value.to_s) ? true : false
end
end
end
module CSV
module_function
def parse(value, &block)
if value.is_a?(String)
value = value.strip.split(/\s*,\s*/)
value = value.collect(&block) if block_given?
value
else
value
end
end
end
module InheritedReader
def inherited_reader(constant_name)
base_class = inherited_base
result = base_class.const_get(constant_name)
found_base_class = false
ancestors.reverse_each do |klass|
if found_base_class
if klass.const_defined?(constant_name)
result = yield(result, klass.const_get(constant_name))
end
else
found_base_class = klass == base_class
end
end
result
end
def inherited_array_reader(constant_name)
inherited_reader(constant_name) do |result, current|
current + result
end
end
def inherited_hash_reader(constant_name)
inherited_reader(constant_name) do |result, current|
result.merge(current)
end
end
end
end end
end end

View file

@ -35,6 +35,10 @@ module RSS
attr_accessor(*ATTRIBUTES) attr_accessor(*ATTRIBUTES)
attr_accessor(:do_validate) attr_accessor(:do_validate)
def initialize(*attrs) def initialize(*attrs)
if attrs.size == 1 and
(attrs.first.is_a?(Hash) or attrs.first.is_a?(Array))
attrs = attrs.first
end
@do_validate = true @do_validate = true
ATTRIBUTES.each do |attr| ATTRIBUTES.each do |attr|
__send__("#{attr}=", nil) __send__("#{attr}=", nil)

71
lib/rss/xml.rb Normal file
View file

@ -0,0 +1,71 @@
require "rss/utils"
module RSS
module XML
class Element
include Enumerable
attr_reader :name, :prefix, :uri, :attributes, :children
def initialize(name, prefix=nil, uri=nil, attributes={}, children=[])
@name = name
@prefix = prefix
@uri = uri
@attributes = attributes
if children.is_a?(String) or !children.respond_to?(:each)
@children = [children]
else
@children = children
end
end
def [](name)
@attributes[name]
end
def []=(name, value)
@attributes[name] = value
end
def <<(child)
@children << child
end
def each(&block)
@children.each(&block)
end
def ==(other)
other.kind_of?(self.class) and
@name == other.name and
@uri == other.uri and
@attributes == other.attributes and
@children == other.children
end
def to_s
rv = "<#{full_name}"
attributes.each do |key, value|
rv << " #{Utils.html_escape(key)}=\"#{Utils.html_escape(value)}\""
end
if children.empty?
rv << "/>"
else
rv << ">"
children.each do |child|
rv << child.to_s
end
rv << "</#{full_name}>"
end
rv
end
def full_name
if @prefix
"#{@prefix}:#{@name}"
else
@name
end
end
end
end
end

View file

@ -64,6 +64,12 @@ rss = RSS::Maker.make("1.0") do |maker|
item.setup_maker(maker.items) item.setup_maker(maker.items)
end end
end end
maker.items.each do |item|
item.title ||= "UNKNOWN"
item.link ||= "UNKNOWN"
end
maker.items.do_sort = true maker.items.do_sort = true
maker.items.max_size = 15 maker.items.max_size = 15
end end

View file

@ -23,7 +23,7 @@ ARGV.each do |fname|
when '-v' when '-v'
verbose = true verbose = true
next next
when /^-t(0\.91|1\.0|2\.0)$/ when /^-t(0\.91|1\.0|2\.0|atom)$/
to_version = $1 to_version = $1
next next
end end

13
sample/rss/list_description.rb Normal file → Executable file
View file

@ -56,9 +56,18 @@ ARGV.each do |fname|
rescue RSS::UnknownConversionMethodError rescue RSS::UnknownConversionMethodError
error($!) if verbose error($!) if verbose
end end
rss.channel.title ||= "Unknown"
rss = rss.to_rss("1.0") do |maker|
maker.channel.about ||= maker.channel.link
maker.channel.description ||= "No description"
maker.items.each do |item|
item.title ||= "No title"
item.link ||= "UNKNOWN"
end
end
next if rss.nil?
rss.items.each do |item| rss.items.each do |item|
item.title ||= "Unknown"
channels[rss.channel.title] ||= [] channels[rss.channel.title] ||= []
channels[rss.channel.title] << item if item.description channels[rss.channel.title] << item if item.description
end end

View file

@ -29,16 +29,16 @@ ARGV.each do |fname|
read = false read = false
begin begin
rss = RSS::Parser.parse(source) rss = RSS::Parser.parse(source)
puts "Re-read valid RSS: #{fname}" puts "Re-read valid feed: #{fname}"
RSS::Parser.parse(rss.to_s) RSS::Parser.parse(rss.to_s)
read = true read = true
rescue RSS::InvalidRSSError rescue RSS::InvalidRSSError
error($!) if verbose error($!) if verbose
## do non validate parse for invalid RSS 1.0 ## do non validate parse for invalid feed
begin begin
rss = RSS::Parser.parse(source, false) rss = RSS::Parser.parse(source, false)
rescue RSS::Error rescue RSS::Error
## invalid RSS. ## invalid feed
error($!) if verbose error($!) if verbose
end end
rescue RSS::Error rescue RSS::Error
@ -46,9 +46,9 @@ ARGV.each do |fname|
end end
if rss.nil? if rss.nil?
puts "Invalid RSS: #{fname}" puts "Invalid feed: #{fname}"
elsif !read elsif !read
puts "Re-read invalid RSS: #{fname}" puts "Re-read invalid feed: #{fname}"
begin begin
RSS::Parser.parse(rss.to_s) RSS::Parser.parse(rss.to_s)
rescue RSS::Error rescue RSS::Error

20
sample/rss/rss_recent.rb Normal file → Executable file
View file

@ -55,15 +55,19 @@ ARGV.each do |fname|
rescue RSS::UnknownConversionMethodError rescue RSS::UnknownConversionMethodError
error($!) if verbose error($!) if verbose
end end
rss = rss.to_rss("1.0") do |maker|
maker.channel.about ||= maker.channel.link
maker.channel.description ||= "No description"
maker.items.each do |item|
item.title ||= "UNKNOWN"
item.link ||= "UNKNOWN"
end
end
next if rss.nil?
rss.items.each do |item| rss.items.each do |item|
if item.respond_to?(:pubDate) and item.pubDate items << [rss.channel, item] if item.dc_date
class << item
alias_method(:dc_date, :pubDate)
end
end
if item.respond_to?(:dc_date) and item.dc_date
items << [rss.channel, item]
end
end end
end end
end end

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,8 @@ require "erb"
require "test/unit" require "test/unit"
require 'rss-assertions' require 'rss-assertions'
require "rss"
module RSS module RSS
class TestCase < Test::Unit::TestCase class TestCase < Test::Unit::TestCase
include ERB::Util include ERB::Util
@ -42,6 +44,45 @@ module RSS
CATEGORY_DOMAIN = "http://www.superopendirectory.com/" CATEGORY_DOMAIN = "http://www.superopendirectory.com/"
FEED_TITLE = "dive into mark"
FEED_UPDATED = "2003-12-13T18:30:02Z"
FEED_AUTHOR_NAME = "John Doe"
FEED_ID = "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6"
ENTRY_TITLE = "Atom-Powered Robots Run Amok"
ENTRY_LINK = "http://example.org/2003/12/13/atom03"
ENTRY_ID = "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a"
ENTRY_UPDATED = "2003-12-13T18:30:02Z"
ENTRY_SUMMARY = "Some text."
t = Time.iso8601("2000-01-01T12:00:05+00:00")
class << t
alias_method(:to_s, :iso8601)
end
DC_ELEMENTS = {
:title => "hoge",
:description =>
" XML is placing increasingly heavy loads on
the existing technical infrastructure of the Internet.",
:creator => "Rael Dornfest (mailto:rael@oreilly.com)",
:subject => "XML",
:publisher => "The O'Reilly Network",
:contributor => "hogehoge",
:type => "fugafuga",
:format => "hohoho",
:identifier => "fufufu",
:source => "barbar",
:language => "ja",
:relation => "cococo",
:rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
:date => t,
}
DC_NODES = DC_ELEMENTS.collect do |name, value|
"<#{DC_PREFIX}:#{name}>#{value}</#{DC_PREFIX}:#{name}>"
end.join("\n")
def default_test def default_test
# This class isn't tested # This class isn't tested
end end
@ -205,6 +246,82 @@ EOC
EOR EOR
end end
def make_feed_without_entry(content=nil, xmlns=[])
<<-EOA
<feed xmlns="#{Atom::URI}"
#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}>
<id>#{FEED_ID}</id>
<title>#{FEED_TITLE}</title>
<updated>#{FEED_UPDATED}</updated>
<author>
<name>#{FEED_AUTHOR_NAME}</name>
</author>
#{block_given? ? yield : content}
</feed>
EOA
end
def make_entry(content=nil)
<<-EOA
<entry>
<title>#{ENTRY_TITLE}</title>
<id>#{ENTRY_ID}</id>
<updated>#{ENTRY_UPDATED}</updated>
#{block_given? ? yield : content}
</entry>
EOA
end
def make_feed_with_open_entry(content=nil, xmlns=[], &block)
make_feed_without_entry(<<-EOA, xmlns)
#{make_entry(content, &block)}
EOA
end
def make_feed_with_open_entry_source(content=nil, xmlns=[])
make_feed_with_open_entry(<<-EOA, xmlns)
<source>
#{block_given? ? yield : content}
</source>
EOA
end
def make_feed(content=nil, xmlns=[])
make_feed_without_entry(<<-EOA, xmlns)
<entry>
<title>#{ENTRY_TITLE}</title>
<link href="#{ENTRY_LINK}"/>
<id>#{ENTRY_ID}</id>
<updated>#{ENTRY_UPDATED}</updated>
<summary>#{ENTRY_SUMMARY}</summary>
</entry>
#{block_given? ? yield : content}
EOA
end
def make_entry_document(content=nil, xmlns=[])
<<-EOA
<entry xmlns="#{Atom::URI}"
#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}>
<id>#{ENTRY_ID}</id>
<title>#{ENTRY_TITLE}</title>
<updated>#{ENTRY_UPDATED}</updated>
<author>
<name>#{FEED_AUTHOR_NAME}</name>
</author>
#{block_given? ? yield : content}
</entry>
EOA
end
def make_entry_document_with_open_source(content=nil, xmlns=[])
make_entry_document(<<-EOA, xmlns)
<source>
#{block_given? ? yield : content}
</source>
EOA
end
def make_element(elem_name, attrs, contents) def make_element(elem_name, attrs, contents)
attrs_str = attrs.collect do |name, value| attrs_str = attrs.collect do |name, value|
"#{h name}='#{h value}'" "#{h name}='#{h value}'"
@ -216,11 +333,60 @@ EOR
"<#{h elem_name} #{attrs_str}>\n#{contents_str}\n</#{h elem_name}>" "<#{h elem_name} #{attrs_str}>\n#{contents_str}\n</#{h elem_name}>"
end end
def xmlns_container(xmlns_decls, content)
attributes = xmlns_decls.collect do |prefix, uri|
"xmlns:#{h prefix}=\"#{h uri}\""
end.join(" ")
"<dummy #{attributes}>#{content}</dummy>"
end
private private
def setup_rss10(rdf)
assert_equal("", rdf.to_s)
channel = RDF::Channel.new
assert_equal("", channel.to_s)
channel.about = "http://example.com/index.rdf"
channel.title = "title"
channel.link = "http://example.com/"
channel.description = "description"
assert_equal("", channel.to_s)
item_title = "item title"
item_link = "http://example.com/item"
channel.items = RDF::Channel::Items.new
channel.items.Seq.lis << RDF::Channel::Items::Seq::Li.new(item_link)
assert_not_equal("", channel.to_s)
rdf.channel = channel
assert_equal("", rdf.to_s)
item = RDF::Item.new
item.title = item_title
item.link = item_link
item.about = item_link
rdf.items << item
assert_not_equal("", rdf.to_s)
end
def setup_rss20(rss)
assert_equal("", rss.to_s)
channel = Rss::Channel.new
assert_equal("", channel.to_s)
channel.title = "title"
channel.link = "http://example.com/"
channel.description = "description"
assert_not_equal("", channel.to_s)
rss.channel = channel
assert_not_equal("", rss.to_s)
end
def setup_dummy_channel(maker) def setup_dummy_channel(maker)
about = "http://hoge.com" about = "http://hoge.com"
title = "fugafuga" title = "fugafuga"
link = "http://hoge.com" link = "http://hoge.com/feed.xml"
description = "fugafugafugafuga" description = "fugafugafugafuga"
language = "ja" language = "ja"
@ -231,6 +397,17 @@ EOR
maker.channel.language = language maker.channel.language = language
end end
def setup_dummy_channel_atom(maker)
updated = Time.now
author = "Foo"
setup_dummy_channel(maker)
maker.channel.links.first.rel = "self"
maker.channel.links.first.type = "application/atom+xml"
maker.channel.updated = updated
maker.channel.author = author
end
def setup_dummy_image(maker) def setup_dummy_image(maker)
title = "fugafuga" title = "fugafuga"
link = "http://hoge.com" link = "http://hoge.com"
@ -263,6 +440,14 @@ EOR
item.link = link item.link = link
end end
def setup_dummy_item_atom(maker)
setup_dummy_item(maker)
item = maker.items.first
item.id = "http://example.net/xxx"
item.updated = Time.now
end
def setup_taxo_topic(target, topics) def setup_taxo_topic(target, topics)
topics.each do |topic| topics.each do |topic|
taxo_topic = target.taxo_topics.new_taxo_topic taxo_topic = target.taxo_topics.new_taxo_topic

View file

@ -19,8 +19,8 @@ module RSS
standalone = false standalone = false
rdf = RDF.new(version, encoding, standalone) rdf = RDF.new(version, encoding, standalone)
setup_rss10(rdf)
doc = REXML::Document.new(rdf.to_s(false)) doc = REXML::Document.new(rdf.to_s)
xmldecl = doc.xml_decl xmldecl = doc.xml_decl
@ -59,16 +59,31 @@ module RSS
link = "http://hoge.com" link = "http://hoge.com"
description = "fugafugafugafuga" description = "fugafugafugafuga"
resource = "http://hoge.com/hoge.png" resource = "http://hoge.com/hoge.png"
item_title = "item title"
item_link = "http://hoge.com/item"
image = RDF::Channel::Image.new(resource) image = RDF::Channel::Image.new(resource)
items = RDF::Channel::Items.new items = RDF::Channel::Items.new
items.Seq.lis << items.class::Seq::Li.new(item_link)
textinput = RDF::Channel::Textinput.new(resource) textinput = RDF::Channel::Textinput.new(resource)
rss_item = RDF::Item.new
rss_item.title = item_title
rss_item.link = item_link
rss_item.about = item_link
channel = RDF::Channel.new(about) channel = RDF::Channel.new(about)
%w(title link description image items textinput).each do |x| %w(title link description image items textinput).each do |x|
channel.__send__("#{x}=", instance_eval(x)) channel.__send__("#{x}=", instance_eval(x))
end end
doc = REXML::Document.new(make_RDF(channel.to_s)) doc = REXML::Document.new(make_RDF(<<-EOR))
#{channel}
<items>
#{rss_item}
</items>
EOR
c = doc.root.elements[1] c = doc.root.elements[1]
assert_equal(about, c.attributes["about"]) assert_equal(about, c.attributes["about"])
@ -123,8 +138,12 @@ module RSS
assert_equal(resource, res.value) assert_equal(resource, res.value)
end end
def test_items def test_channel_items
item_link = "http://example.com/item"
items = RDF::Channel::Items.new items = RDF::Channel::Items.new
li = items.Seq.class::Li.new(item_link)
items.Seq.lis << li
doc = REXML::Document.new(make_RDF(items.to_s)) doc = REXML::Document.new(make_RDF(items.to_s))
i = doc.root.elements[1] i = doc.root.elements[1]
@ -133,18 +152,34 @@ module RSS
assert_equal(@uri, i.namespace) assert_equal(@uri, i.namespace)
assert_equal(1, i.elements.size) assert_equal(1, i.elements.size)
assert_equal("Seq", i.elements[1].name) seq = i.elements[1]
assert_equal(@rdf_uri, i.elements[1].namespace) assert_equal("Seq", seq.name)
assert_equal(@rdf_uri, seq.namespace)
assert_equal(1, seq.elements.size)
l = seq.elements[1]
assert_equal("li", l.name)
assert_equal(@rdf_uri, l.namespace)
assert_equal(item_link, l.attributes["resource"])
end end
def test_seq def test_seq
item_link = "http://example.com/item"
seq = RDF::Seq.new seq = RDF::Seq.new
li = seq.class::Li.new(item_link)
seq.lis << li
doc = REXML::Document.new(make_RDF(seq.to_s)) doc = REXML::Document.new(make_RDF(seq.to_s))
s = doc.root.elements[1] s = doc.root.elements[1]
assert_equal("Seq", s.name) assert_equal("Seq", s.name)
assert_equal(@rdf_uri, s.namespace) assert_equal(@rdf_uri, s.namespace)
assert_equal(1, s.elements.size)
l = s.elements[1]
assert_equal("li", l.name)
assert_equal(@rdf_uri, l.namespace)
assert_equal(item_link, l.attributes["resource"])
end end
def test_li def test_li
@ -242,8 +277,20 @@ module RSS
end end
rss09 = RSS::Parser.parse(rss09) rss09 = RSS::Parser.parse(rss09)
assert_equal("0.91", rss09.rss_version) assert_equal("0.91", rss09.rss_version)
assert_equal(["rss", "0.91", nil], rss09.feed_info)
rss20 = RSS::Parser.parse(rss.to_xml("2.0")) rss20 = RSS::Parser.parse(rss.to_xml("2.0"))
assert_equal("2.0", rss20.rss_version) assert_equal("2.0", rss20.rss_version)
assert_equal(["rss", "2.0", nil], rss20.feed_info)
atom_xml = rss.to_xml("atom") do |maker|
maker.channel.author = "Alice"
maker.channel.updated ||= Time.now
maker.items.each do |item|
item.updated ||= Time.now
end
end
atom = RSS::Parser.parse(atom_xml)
assert_equal(["atom", "1.0", "feed"], atom.feed_info)
end end
end end
end end

View file

@ -2,8 +2,6 @@ require "rexml/document"
require "rss-testcase" require "rss-testcase"
require "rss/2.0"
module RSS module RSS
class TestRSS20Core < TestCase class TestRSS20Core < TestCase
@ -17,6 +15,7 @@ module RSS
standalone = false standalone = false
rss = Rss.new(@rss_version, version, encoding, standalone) rss = Rss.new(@rss_version, version, encoding, standalone)
setup_rss20(rss)
doc = REXML::Document.new(rss.to_s(false)) doc = REXML::Document.new(rss.to_s(false))
@ -48,7 +47,9 @@ module RSS
{:href => "a.css", :type => "text/css"}, {:href => "a.css", :type => "text/css"},
], ],
].each do |attrs_ary| ].each do |attrs_ary|
assert_xml_stylesheet_pis(attrs_ary, Rss.new(@rss_version)) rss = Rss.new(@rss_version)
setup_rss20(rss)
assert_xml_stylesheet_pis(attrs_ary, rss)
end end
end end
@ -253,6 +254,10 @@ module RSS
pubDate = Time.parse("Sat, 07 Sep 2002 00:00:01 GMT") pubDate = Time.parse("Sat, 07 Sep 2002 00:00:01 GMT")
channel = Rss::Channel.new channel = Rss::Channel.new
channel.title = "title"
channel.link = "http://example.com/"
channel.description = "description"
item = Rss::Channel::Item.new item = Rss::Channel::Item.new
channel.items << item channel.items << item
@ -378,13 +383,28 @@ module RSS
rss = RSS::Parser.parse(make_sample_rss20) rss = RSS::Parser.parse(make_sample_rss20)
assert_equal(rss.to_s, rss.to_xml) assert_equal(rss.to_s, rss.to_xml)
assert_equal(rss.to_s, rss.to_xml("2.0")) assert_equal(rss.to_s, rss.to_xml("2.0"))
rss09 = RSS::Parser.parse(rss.to_xml("0.91")) rss09_xml = rss.to_xml("0.91") do |maker|
setup_dummy_image(maker)
end
rss09 = RSS::Parser.parse(rss09_xml)
assert_equal("0.91", rss09.rss_version) assert_equal("0.91", rss09.rss_version)
rss10 = rss.to_xml("1.0") do |maker| rss10 = rss.to_xml("1.0") do |maker|
maker.channel.about = "http://www.example.com/index.rdf" maker.channel.about = "http://www.example.com/index.rdf"
end end
rss10 = RSS::Parser.parse(rss10) rss10 = RSS::Parser.parse(rss10)
assert_equal("1.0", rss10.rss_version) assert_equal("1.0", rss10.rss_version)
atom_xml = rss.to_xml("atom1.0") do |maker|
maker.channel.id = "http://www.example.com/atom.xml"
maker.channel.author = "Alice"
maker.channel.updated = Time.now
maker.items.each do |item|
item.author = "Bob"
item.updated = Time.now
end
end
atom = RSS::Parser.parse(atom_xml)
assert_equal(["atom", "1.0", "feed"], atom.feed_info)
end end
end end
end end

688
test/rss/test_atom.rb Normal file
View file

@ -0,0 +1,688 @@
require "rexml/document"
require "rss-testcase"
require "rss/atom"
module RSS
class TestAtomCore < TestCase
def setup
@uri = "http://www.w3.org/2005/Atom"
@xhtml_uri = "http://www.w3.org/1999/xhtml"
end
def test_feed
version = "1.0"
encoding = "UTF-8"
standalone = false
feed = Atom::Feed.new(version, encoding, standalone)
assert_equal("", feed.to_s)
author = feed.class::Author.new
name = feed.class::Author::Name.new
name.content = "an author"
author.name = name
assert_not_equal("", author.to_s)
feed.authors << author
assert_equal("", feed.to_s)
id = feed.class::Id.new
id.content = "http://example.com/atom.xml"
assert_not_equal("", id.to_s)
feed.id = id
assert_equal("", feed.to_s)
title = feed.class::Title.new
title.content = "a title"
assert_not_equal("", title.to_s)
feed.title = title
assert_equal("", feed.to_s)
updated = feed.class::Updated.new
updated.content = Time.now
assert_not_equal("", updated.to_s)
feed.updated = updated
assert_not_equal("", feed.to_s)
feed.authors.clear
assert_equal("", feed.to_s)
entry = Atom::Feed::Entry.new
setup_entry(entry)
assert_not_equal("", entry.to_s)
author = entry.authors.first
entry.authors.clear
assert_equal("", entry.to_s)
entry.parent = feed
assert_equal("", entry.to_s)
feed.authors << author
assert_not_equal("", entry.to_s)
feed.authors.clear
feed.entries << entry
assert_equal("", feed.to_s)
entry.authors << author
assert_not_equal("", entry.to_s)
assert_not_equal("", feed.to_s)
doc = REXML::Document.new(feed.to_s)
xmldecl = doc.xml_decl
%w(version encoding).each do |x|
assert_equal(instance_eval(x), xmldecl.__send__(x))
end
assert_equal(standalone, !xmldecl.standalone.nil?)
assert_equal(@uri, doc.root.namespace)
end
def test_entry
version = "1.0"
encoding = "UTF-8"
standalone = false
entry = Atom::Entry.new(version, encoding, standalone)
setup_entry(entry)
author = entry.authors.first
entry.authors.clear
assert_equal("", entry.to_s)
source = Atom::Entry::Source.new
source.authors << author
entry.source = source
assert_not_equal("", entry.to_s)
doc = REXML::Document.new(entry.to_s)
xmldecl = doc.xml_decl
%w(version encoding).each do |x|
assert_equal(instance_eval(x), xmldecl.__send__(x))
end
assert_equal(standalone, !xmldecl.standalone.nil?)
assert_equal(@uri, doc.root.namespace)
end
def test_not_displayed_xml_stylesheets
feed = Atom::Feed.new
plain_feed = feed.to_s
3.times do
feed.xml_stylesheets.push(XMLStyleSheet.new)
assert_equal(plain_feed, feed.to_s)
end
end
def test_atom_author
assert_atom_person_to_s(Atom::Feed::Author)
assert_atom_person_to_s(Atom::Feed::Entry::Author)
assert_atom_person_to_s(Atom::Entry::Author)
assert_atom_person_to_s(Atom::Feed::Entry::Source::Author)
assert_atom_person_to_s(Atom::Entry::Source::Author)
end
def test_atom_category
assert_atom_category_to_s(Atom::Feed::Category)
assert_atom_category_to_s(Atom::Feed::Entry::Category)
assert_atom_category_to_s(Atom::Entry::Category)
assert_atom_category_to_s(Atom::Feed::Entry::Source::Category)
assert_atom_category_to_s(Atom::Entry::Source::Category)
end
def test_atom_contributor
assert_atom_person_to_s(Atom::Feed::Contributor)
assert_atom_person_to_s(Atom::Feed::Entry::Contributor)
assert_atom_person_to_s(Atom::Entry::Contributor)
assert_atom_person_to_s(Atom::Feed::Entry::Source::Contributor)
assert_atom_person_to_s(Atom::Entry::Source::Contributor)
end
def test_atom_generator
assert_atom_generator_to_s(Atom::Feed::Generator)
assert_atom_generator_to_s(Atom::Feed::Entry::Source::Generator)
assert_atom_generator_to_s(Atom::Entry::Source::Generator)
end
def test_atom_icon
assert_atom_icon_to_s(Atom::Feed::Icon)
assert_atom_icon_to_s(Atom::Feed::Entry::Source::Icon)
assert_atom_icon_to_s(Atom::Entry::Source::Icon)
end
def test_atom_id
assert_atom_id_to_s(Atom::Feed::Id)
assert_atom_id_to_s(Atom::Feed::Entry::Id)
assert_atom_id_to_s(Atom::Entry::Id)
assert_atom_id_to_s(Atom::Feed::Entry::Source::Id)
assert_atom_id_to_s(Atom::Entry::Source::Id)
end
def test_atom_link
assert_atom_link_to_s(Atom::Feed::Link)
assert_atom_link_to_s(Atom::Feed::Entry::Link)
assert_atom_link_to_s(Atom::Entry::Link)
assert_atom_link_to_s(Atom::Feed::Entry::Source::Link)
assert_atom_link_to_s(Atom::Entry::Source::Link)
end
def test_atom_logo
assert_atom_logo_to_s(Atom::Feed::Logo)
assert_atom_logo_to_s(Atom::Feed::Entry::Source::Logo)
assert_atom_logo_to_s(Atom::Entry::Source::Logo)
end
def test_atom_rights
assert_atom_text_construct_to_s(Atom::Feed::Rights)
assert_atom_text_construct_to_s(Atom::Feed::Entry::Rights)
assert_atom_text_construct_to_s(Atom::Entry::Rights)
assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Rights)
assert_atom_text_construct_to_s(Atom::Entry::Source::Rights)
end
def test_atom_subtitle
assert_atom_text_construct_to_s(Atom::Feed::Subtitle)
assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Subtitle)
assert_atom_text_construct_to_s(Atom::Entry::Source::Subtitle)
end
def test_atom_title
assert_atom_text_construct_to_s(Atom::Feed::Title)
assert_atom_text_construct_to_s(Atom::Feed::Entry::Title)
assert_atom_text_construct_to_s(Atom::Entry::Title)
assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Title)
assert_atom_text_construct_to_s(Atom::Entry::Source::Title)
end
def test_atom_updated
assert_atom_date_construct_to_s(Atom::Feed::Updated)
assert_atom_date_construct_to_s(Atom::Feed::Entry::Updated)
assert_atom_date_construct_to_s(Atom::Entry::Updated)
assert_atom_date_construct_to_s(Atom::Feed::Entry::Source::Updated)
assert_atom_date_construct_to_s(Atom::Entry::Source::Updated)
end
def test_atom_content
assert_atom_content_to_s(Atom::Feed::Entry::Content)
assert_atom_content_to_s(Atom::Entry::Content)
end
def test_atom_published
assert_atom_date_construct_to_s(Atom::Feed::Entry::Published)
assert_atom_date_construct_to_s(Atom::Entry::Published)
end
def test_atom_summary
assert_atom_text_construct_to_s(Atom::Feed::Entry::Summary)
assert_atom_text_construct_to_s(Atom::Entry::Summary)
end
def test_to_xml(with_convenience_way=true)
atom = RSS::Parser.parse(make_feed)
assert_equal(atom.to_s, atom.to_xml)
assert_equal(atom.to_s, atom.to_xml("atom"))
assert_equal(atom.to_s, atom.to_xml("atom1.0"))
assert_equal(atom.to_s, atom.to_xml("atom1.0:feed"))
assert_equal(atom.to_s, atom.to_xml("atom:feed"))
rss09_xml = atom.to_xml("0.91") do |maker|
maker.channel.language = "en-us"
maker.channel.link = "http://example.com/"
if with_convenience_way
maker.channel.description = atom.title.content
else
maker.channel.description {|d| d.content = atom.title.content}
end
maker.image.url = "http://example.com/logo.png"
maker.image.title = "Logo"
end
rss09 = RSS::Parser.parse(rss09_xml)
assert_equal(["rss", "0.91", nil], rss09.feed_info)
rss20_xml = atom.to_xml("2.0") do |maker|
maker.channel.link = "http://example.com/"
if with_convenience_way
maker.channel.description = atom.title.content
else
maker.channel.description {|d| d.content = atom.title.content}
end
end
rss20 = RSS::Parser.parse(rss20_xml)
assert_equal("2.0", rss20.rss_version)
assert_equal(["rss", "2.0", nil], rss20.feed_info)
end
def test_to_xml_with_new_api_since_018
test_to_xml(false)
end
private
def setup_entry(entry)
_wrap_assertion do
assert_equal("", entry.to_s)
author = entry.class::Author.new
name = entry.class::Author::Name.new
name.content = "an author"
author.name = name
assert_not_equal("", author.to_s)
entry.authors << author
assert_equal("", entry.to_s)
id = entry.class::Id.new
id.content = "http://example.com/atom.xml"
assert_not_equal("", id.to_s)
entry.id = id
assert_equal("", entry.to_s)
title = entry.class::Title.new
title.content = "a title"
assert_not_equal("", title.to_s)
entry.title = title
assert_equal("", entry.to_s)
updated = entry.class::Updated.new
updated.content = Time.now
assert_not_equal("", updated.to_s)
entry.updated = updated
assert_not_equal("", entry.to_s)
end
end
def assert_atom_person_to_s(target_class)
_wrap_assertion do
name = "A person"
uri = "http://example.com/person/"
email = "person@example.com"
target = target_class.new
assert_equal("", target.to_s)
target = target_class.new
person_name = target_class::Name.new
person_name.content = name
target.name = person_name
xml_target = REXML::Document.new(target.to_s).root
assert_equal(["name"], xml_target.elements.collect {|e| e.name})
assert_equal([name], xml_target.elements.collect {|e| e.text})
person_uri = target_class::Uri.new
person_uri.content = uri
target.uri = person_uri
xml_target = REXML::Document.new(target.to_s).root
assert_equal(["name", "uri"], xml_target.elements.collect {|e| e.name})
assert_equal([name, uri], xml_target.elements.collect {|e| e.text})
person_email = target_class::Email.new
person_email.content = email
target.email = person_email
xml_target = REXML::Document.new(target.to_s).root
assert_equal(["name", "uri", "email"],
xml_target.elements.collect {|e| e.name})
assert_equal([name, uri, email],
xml_target.elements.collect {|e| e.text})
end
end
def assert_atom_category_to_s(target_class)
_wrap_assertion do
term = "music"
scheme = "http://example.com/music"
label = "Music"
category = target_class.new
assert_equal("", category.to_s)
category = target_class.new
category.scheme = scheme
assert_equal("", category.to_s)
category = target_class.new
category.label = label
assert_equal("", category.to_s)
category = target_class.new
category.scheme = scheme
category.label = label
assert_equal("", category.to_s)
category = target_class.new
category.term = term
xml = REXML::Document.new(category.to_s).root
assert_rexml_element([], {"term" => term}, nil, xml)
category = target_class.new
category.term = term
category.scheme = scheme
xml = REXML::Document.new(category.to_s).root
assert_rexml_element([], {"term" => term, "scheme" => scheme}, nil, xml)
category = target_class.new
category.term = term
category.label = label
xml = REXML::Document.new(category.to_s).root
assert_rexml_element([], {"term" => term, "label" => label}, nil, xml)
category = target_class.new
category.term = term
category.scheme = scheme
category.label = label
xml = REXML::Document.new(category.to_s).root
attrs = {"term" => term, "scheme" => scheme, "label" => label}
assert_rexml_element([], attrs, nil, xml)
end
end
def assert_atom_generator_to_s(target_class)
_wrap_assertion do
content = "Feed generator"
uri = "http://example.com/generator"
version = "0.0.1"
generator = target_class.new
assert_equal("", generator.to_s)
generator = target_class.new
generator.uri = uri
assert_equal("", generator.to_s)
generator = target_class.new
generator.version = version
assert_equal("", generator.to_s)
generator = target_class.new
generator.uri = uri
generator.version = version
assert_equal("", generator.to_s)
generator = target_class.new
generator.content = content
xml = REXML::Document.new(generator.to_s).root
assert_rexml_element([], {}, content, xml)
generator = target_class.new
generator.content = content
generator.uri = uri
xml = REXML::Document.new(generator.to_s).root
assert_rexml_element([], {"uri" => uri}, content, xml)
generator = target_class.new
generator.content = content
generator.version = version
xml = REXML::Document.new(generator.to_s).root
assert_rexml_element([], {"version" => version}, content, xml)
generator = target_class.new
generator.content = content
generator.uri = uri
generator.version = version
xml = REXML::Document.new(generator.to_s).root
assert_rexml_element([], {"uri" => uri, "version" => version},
content, xml)
end
end
def assert_atom_icon_to_s(target_class)
_wrap_assertion do
content = "http://example.com/icon.png"
icon = target_class.new
assert_equal("", icon.to_s)
icon = target_class.new
icon.content = content
xml = REXML::Document.new(icon.to_s).root
assert_rexml_element([], {}, content, xml)
end
end
def assert_atom_id_to_s(target_class)
_wrap_assertion do
content = "http://example.com/1"
id = target_class.new
assert_equal("", id.to_s)
id = target_class.new
id.content = content
xml = REXML::Document.new(id.to_s).root
assert_rexml_element([], {}, content, xml)
end
end
def assert_atom_link_to_s(target_class)
_wrap_assertion do
href = "http://example.com/atom.xml"
rel = "self"
type = "application/atom+xml"
hreflang = "ja"
title = "Atom Feed"
length = "801"
link = target_class.new
assert_equal("", link.to_s)
link = target_class.new
link.href = href
xml = REXML::Document.new(link.to_s).root
assert_rexml_element([], {"href" => href}, nil, xml)
optional_arguments = %w(rel type hreflang title length)
optional_arguments.each do |name|
rest = optional_arguments.reject {|x| x == name}
link = target_class.new
link.__send__("#{name}=", eval(name))
assert_equal("", link.to_s)
rest.each do |n|
link.__send__("#{n}=", eval(n))
assert_equal("", link.to_s)
end
link = target_class.new
link.href = href
link.__send__("#{name}=", eval(name))
attrs = [["href", href], [name, eval(name)]]
xml = REXML::Document.new(link.to_s).root
assert_rexml_element([], attrs, nil, xml)
rest.each do |n|
link.__send__("#{n}=", eval(n))
attrs << [n, eval(n)]
xml = REXML::Document.new(link.to_s).root
assert_rexml_element([], attrs, nil, xml)
end
end
end
end
def assert_atom_logo_to_s(target_class)
_wrap_assertion do
content = "http://example.com/logo.png"
logo = target_class.new
assert_equal("", logo.to_s)
logo = target_class.new
logo.content = content
xml = REXML::Document.new(logo.to_s).root
assert_rexml_element([], {}, content, xml)
end
end
def assert_atom_text_construct_to_s(target_class)
_wrap_assertion do
text_content = "plain text"
html_content = "<em>#{text_content}</em>"
xhtml_uri = "http://www.w3.org/1999/xhtml"
xhtml_em = RSS::XML::Element.new("em", nil, xhtml_uri, {}, text_content)
xhtml_content = RSS::XML::Element.new("div", nil, xhtml_uri,
{"xmlns" => xhtml_uri},
[xhtml_em])
text = target_class.new
assert_equal("", text.to_s)
text = target_class.new
text.type = "text"
assert_equal("", text.to_s)
text = target_class.new
text.content = text_content
xml = REXML::Document.new(text.to_s).root
assert_rexml_element([], {}, text_content, xml)
text = target_class.new
text.type = "text"
text.content = text_content
xml = REXML::Document.new(text.to_s).root
assert_rexml_element([], {"type" => "text"}, text_content, xml)
text = target_class.new
text.type = "html"
text.content = html_content
xml = REXML::Document.new(text.to_s).root
assert_rexml_element([], {"type" => "html"}, html_content, xml)
text = target_class.new
text.type = "xhtml"
text.content = xhtml_content
assert_equal("", text.to_s)
text = target_class.new
text.type = "xhtml"
text.__send__(target_class.xml_setter, xhtml_content)
xml = REXML::Document.new(text.to_s).root
assert_rexml_element([[xhtml_uri, "div"]], {"type" => "xhtml"},
nil, xml)
assert_rexml_element([[xhtml_uri, "em"]], nil, nil, xml.elements[1])
assert_rexml_element([], {}, text_content, xml.elements[1].elements[1])
text = target_class.new
text.type = "xhtml"
text.__send__(target_class.xml_setter, xhtml_em)
xml = REXML::Document.new(text.to_s).root
assert_rexml_element([[xhtml_uri, "div"]], {"type" => "xhtml"},
nil, xml)
assert_rexml_element([[xhtml_uri, "em"]], nil, nil, xml.elements[1])
assert_rexml_element([], {}, text_content, xml.elements[1].elements[1])
end
end
def assert_atom_date_construct_to_s(target_class)
_wrap_assertion do
date = target_class.new
assert_equal("", date.to_s)
[
"2003-12-13T18:30:02Z",
"2003-12-13T18:30:02.25Z",
"2003-12-13T18:30:02+01:00",
"2003-12-13T18:30:02.25+01:00",
].each do |content|
date = target_class.new
date.content = content
xml = REXML::Document.new(date.to_s).root
assert_rexml_element([], {}, content, xml, :time)
date = target_class.new
date.content = Time.parse(content)
xml = REXML::Document.new(date.to_s).root
assert_rexml_element([], {}, content, xml, :time)
end
end
end
def assert_atom_content_to_s(target_class)
_wrap_assertion do
assert_atom_text_construct_to_s(target_class)
assert_atom_content_inline_other_xml_to_s(target_class)
assert_atom_content_inline_other_text_to_s(target_class)
assert_atom_content_inline_other_base64_to_s(target_class)
assert_atom_content_out_of_line_to_s(target_class)
end
end
def assert_atom_content_inline_other_xml_to_s(target_class)
_wrap_assertion do
content = target_class.new
content.type = "text/xml"
assert_equal("", content.to_s)
content = target_class.new
content.type = "text/xml"
content.xml = RSS::XML::Element.new("em")
xml = REXML::Document.new(content.to_s).root
assert_rexml_element([["", "em"]], {"type" => "text/xml"}, nil, xml)
end
end
def assert_atom_content_inline_other_text_to_s(target_class)
_wrap_assertion do
content = target_class.new
content.type = "text/plain"
assert_equal("", content.to_s)
content = target_class.new
content.type = "text/plain"
content.xml = RSS::XML::Element.new("em")
assert_equal("", content.to_s)
content = target_class.new
content.type = "text/plain"
content.content = "content"
xml = REXML::Document.new(content.to_s).root
assert_rexml_element([], {"type" => "text/plain"}, "content", xml)
end
end
def assert_atom_content_inline_other_base64_to_s(target_class)
_wrap_assertion do
require "zlib"
text = ""
char = "a"
100.times do |i|
text << char
char.succ!
end
type = "application/zip"
original_content = Zlib::Deflate.deflate(text)
content = target_class.new
content.type = type
content.content = original_content
xml = REXML::Document.new(content.to_s).root
assert_rexml_element([], {"type" => type},
Base64.encode64(original_content), xml)
end
end
def assert_atom_content_out_of_line_to_s(target_class)
_wrap_assertion do
type = "application/zip"
src = "http://example.com/xxx.zip"
content = target_class.new
assert(!content.out_of_line?)
content.src = src
assert(content.out_of_line?)
xml = REXML::Document.new(content.to_s).root
assert_rexml_element([], {"src" => src}, nil, xml)
content = target_class.new
assert(!content.out_of_line?)
content.type = type
assert(!content.out_of_line?)
content.src = src
assert(content.out_of_line?)
xml = REXML::Document.new(content.to_s).root
assert_rexml_element([], {"type" => type, "src" => src}, nil, xml)
end
end
end
end

View file

@ -8,68 +8,148 @@ require "rss/dublincore"
module RSS module RSS
class TestDublinCore < TestCase class TestDublinCore < TestCase
def setup def setup
@prefix = "dc" @rss10_parents = [%w(channel), %w(image), %w(item), %w(textinput)]
@uri = "http://purl.org/dc/elements/1.1/"
@parents = %w(channel image item textinput) @rss10_source = make_RDF(<<-EOR, {DC_PREFIX => DC_URI})
#{make_channel(DC_NODES)}
t = Time.iso8601("2000-01-01T12:00:05+00:00") #{make_image(DC_NODES)}
class << t #{make_item(DC_NODES)}
alias_method(:to_s, :iso8601) #{make_textinput(DC_NODES)}
end
@elems = {
:title => "hoge",
:description =>
" XML is placing increasingly heavy loads on
the existing technical infrastructure of the Internet.",
:creator => "Rael Dornfest (mailto:rael@oreilly.com)",
:subject => "XML",
:publisher => "The O'Reilly Network",
:contributor => "hogehoge",
:type => "fugafuga",
:format => "hohoho",
:identifier => "fufufu",
:source => "barbar",
:language => "ja",
:relation => "cococo",
:rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
:date => t,
}
@dc_nodes = @elems.collect do |name, value|
"<#{@prefix}:#{name}>#{value}</#{@prefix}:#{name}>"
end.join("\n")
@rss_source = make_RDF(<<-EOR, {@prefix => @uri})
#{make_channel(@dc_nodes)}
#{make_image(@dc_nodes)}
#{make_item(@dc_nodes)}
#{make_textinput(@dc_nodes)}
EOR EOR
@rss = Parser.parse(@rss_source) @rss20_parents = [%w(channel), %w(items last)]
@rss20_source = make_rss20(<<-EOR, {DC_PREFIX => DC_URI})
#{make_channel20(DC_NODES + make_item20(DC_NODES))}
EOR
@atom_feed_parents = [[], %w(entries last)]
@atom_feed_source = make_feed(<<-EOR, {DC_PREFIX => DC_URI})
#{DC_NODES}
#{make_entry(DC_NODES)}
EOR
@atom_entry_parents = [[]]
@atom_entry_source = make_entry_document(<<-EOR, {DC_PREFIX => DC_URI})
#{DC_NODES}
EOR
end end
def test_parser def test_parser
assert_nothing_raised do rss10_maker = Proc.new do |content, xmlns|
Parser.parse(@rss_source) make_RDF(<<-EOR, xmlns)
end #{make_channel(content)}
#{make_image(content)}
@elems.each do |tag, value| #{make_item(content)}
rss = nil #{make_textinput(content)}
assert_nothing_raised do
rss = Parser.parse(make_RDF(<<-EOR, {@prefix => @uri}))
#{make_channel(("<" + @prefix + ":" + tag.to_s + ">" +
value.to_s +
"</" + @prefix + ":" + tag.to_s + ">") * 2)}
#{make_item}
EOR EOR
end end
plural_reader = "dc_#{tag}" + (tag == :rights ? "es" : "s") assert_dc_parse(@rss10_source, @rss10_parents, false, &rss10_maker)
values = rss.channel.__send__(plural_reader).collect do |x| assert_dc_parse(@rss10_source, @rss10_parents, true, &rss10_maker)
rss20_maker = Proc.new do |content, xmlns|
make_rss20(<<-EOR, xmlns)
#{make_channel20(content + make_item20(content))}
EOR
end
assert_dc_parse(@rss20_source, @rss20_parents, false, &rss20_maker)
assert_dc_parse(@rss20_source, @rss20_parents, true, &rss20_maker)
atom_feed_maker = Proc.new do |content, xmlns|
make_feed(<<-EOR, xmlns)
#{content}
#{make_entry(content)}
EOR
end
assert_dc_parse(@atom_feed_source, @atom_feed_parents, false,
&atom_feed_maker)
assert_dc_parse(@atom_feed_source, @atom_feed_parents, true,
&atom_feed_maker)
atom_entry_maker = Proc.new do |content, xmlns|
make_entry_document(<<-EOR, xmlns)
#{content}
EOR
end
assert_dc_parse(@atom_entry_source, @atom_entry_parents, false,
&atom_entry_maker)
assert_dc_parse(@atom_entry_source, @atom_entry_parents, true,
&atom_entry_maker)
end
def test_singular_accessor
assert_dc_singular_accessor(@rss10_source, @rss10_parents)
assert_dc_singular_accessor(@rss20_source, @rss20_parents)
assert_dc_singular_accessor(@atom_feed_source, @atom_feed_parents)
assert_dc_singular_accessor(@atom_entry_source, @atom_entry_parents)
end
def test_plural_accessor
assert_dc_plural_accessor(@rss10_source, @rss10_parents, false)
assert_dc_plural_accessor(@rss10_source, @rss10_parents, true)
assert_dc_plural_accessor(@rss20_source, @rss20_parents, false)
assert_dc_plural_accessor(@rss20_source, @rss20_parents, true)
assert_dc_plural_accessor(@atom_feed_source, @atom_feed_parents, false)
assert_dc_plural_accessor(@atom_feed_source, @atom_feed_parents, true)
assert_dc_plural_accessor(@atom_entry_source, @atom_entry_parents, false)
assert_dc_plural_accessor(@atom_entry_source, @atom_entry_parents, true)
end
def test_to_s
assert_dc_to_s(@rss10_source, @rss10_parents, false)
assert_dc_to_s(@rss10_source, @rss10_parents, true)
targets = ["channel", "channel/item[3]"]
assert_dc_to_s(@rss20_source, @rss20_parents, false, targets)
assert_dc_to_s(@rss20_source, @rss20_parents, true, targets)
targets = [".", "entry"]
assert_dc_to_s(@atom_feed_source, @atom_feed_parents, false, targets)
assert_dc_to_s(@atom_feed_source, @atom_feed_parents, true, targets)
targets = ["."]
assert_dc_to_s(@atom_entry_source, @atom_entry_parents, false, targets)
assert_dc_to_s(@atom_entry_source, @atom_entry_parents, true, targets)
end
private
def dc_plural_suffix(name, check_backward_compatibility)
if name == :rights
if check_backward_compatibility
"es"
else
"_list"
end
else
"s"
end
end
def assert_dc_parse(source, parents, check_backward_compatibility, &maker)
assert_nothing_raised do
Parser.parse(source)
end
DC_ELEMENTS.each do |name, value|
parents.each do |parent_readers|
feed = nil
assert_nothing_raised do
tag = "#{DC_PREFIX}:#{name}"
dc_content = "<#{tag}>#{value}</#{tag}>\n"
dc_content *= 2
feed = Parser.parse(maker.call(dc_content, {DC_PREFIX => DC_URI}))
end
parent = chain_reader(feed, parent_readers)
plural_suffix = dc_plural_suffix(name, check_backward_compatibility)
plural_reader = "dc_#{name}#{plural_suffix}"
values = parent.__send__(plural_reader).collect do |x|
val = x.value val = x.value
if val.kind_of?(String) if val.kind_of?(String)
CGI.escapeHTML(val) CGI.escapeHTML(val)
@ -79,15 +159,17 @@ EOR
end end
assert_equal([value, value], values) assert_equal([value, value], values)
end end
end
end end
def test_singular_accessor def assert_dc_singular_accessor(source, parents)
feed = Parser.parse(source)
new_value = "hoge" new_value = "hoge"
@elems.each do |name, value| parents.each do |parent_readers|
@parents.each do |parent| parent = chain_reader(feed, parent_readers)
parsed_value = @rss.__send__(parent).__send__("dc_#{name}") DC_ELEMENTS.each do |name, value|
parsed_value = parent.__send__("dc_#{name}")
if parsed_value.kind_of?(String) if parsed_value.kind_of?(String)
parsed_value = CGI.escapeHTML(parsed_value) parsed_value = CGI.escapeHTML(parsed_value)
end end
@ -97,34 +179,40 @@ EOR
class << t class << t
alias_method(:to_s, :iso8601) alias_method(:to_s, :iso8601)
end end
@rss.__send__(parent).__send__("dc_#{name}=", t.iso8601) parent.__send__("dc_#{name}=", t.iso8601)
assert_equal(t, @rss.__send__(parent).__send__("dc_#{name}")) assert_equal(t, parent.__send__("dc_#{name}"))
assert_equal(t, @rss.__send__(parent).date) if parent.class.method_defined?(:date_without_dc_date=)
assert_nil(parent.date)
@rss.__send__(parent).date = value
assert_equal(value, @rss.__send__(parent).date)
assert_equal(value, @rss.__send__(parent).__send__("dc_#{name}"))
else else
@rss.__send__(parent).__send__("dc_#{name}=", new_value) assert_equal(t, parent.date)
assert_equal(new_value, end
@rss.__send__(parent).__send__("dc_#{name}"))
parent.date = value
assert_equal(value, parent.date)
assert_equal(value, parent.__send__("dc_#{name}"))
else
parent.__send__("dc_#{name}=", new_value)
assert_equal(new_value, parent.__send__("dc_#{name}"))
end end
end end
end end
end end
def test_plural_accessor def assert_dc_plural_accessor(source, parents, check_backward_compatibility)
feed = Parser.parse(source)
new_value = "hoge" new_value = "hoge"
@elems.each do |name, value| DC_ELEMENTS.each do |name, value|
@parents.each do |parent| parents.each do |parent_readers|
parsed_value = @rss.__send__(parent).__send__("dc_#{name}") parent = chain_reader(feed, parent_readers)
parsed_value = parent.__send__("dc_#{name}")
if parsed_value.kind_of?(String) if parsed_value.kind_of?(String)
parsed_value = CGI.escapeHTML(parsed_value) parsed_value = CGI.escapeHTML(parsed_value)
end end
assert_equal(value, parsed_value) assert_equal(value, parsed_value)
plural_reader = "dc_#{name}" + (name == :rights ? "es" : "s") plural_suffix = dc_plural_suffix(name, check_backward_compatibility)
plural_reader = "dc_#{name}#{plural_suffix}"
klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}" klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}"
klass = DublinCoreModel.const_get(klass_name) klass = DublinCoreModel.const_get(klass_name)
if name == :date if name == :date
@ -132,58 +220,60 @@ EOR
class << t class << t
alias_method(:to_s, :iso8601) alias_method(:to_s, :iso8601)
end end
elems = @rss.__send__(parent).__send__(plural_reader) elems = parent.__send__(plural_reader)
elems << klass.new(t.iso8601) elems << klass.new(t.iso8601)
new_elems = @rss.__send__(parent).__send__(plural_reader) new_elems = parent.__send__(plural_reader)
values = new_elems.collect{|x| x.value} values = new_elems.collect{|x| x.value}
assert_equal([@rss.__send__(parent).__send__("dc_#{name}"), t], assert_equal([parent.__send__("dc_#{name}"), t], values)
values)
else else
elems = @rss.__send__(parent).__send__(plural_reader) elems = parent.__send__(plural_reader)
elems << klass.new(new_value) elems << klass.new(new_value)
new_elems = @rss.__send__(parent).__send__(plural_reader) new_elems = parent.__send__(plural_reader)
values = new_elems.collect{|x| x.value} values = new_elems.collect{|x| x.value}
assert_equal([ assert_equal([parent.__send__("dc_#{name}"), new_value],
@rss.__send__(parent).__send__("dc_#{name}"),
new_value
],
values) values)
end end
end end
end end
end end
def test_to_s def assert_dc_to_s(source, parents, check_backward_compatibility,
@elems.each do |name, value| targets=nil)
excepted = "<#{@prefix}:#{name}>#{value}</#{@prefix}:#{name}>" feed = Parser.parse(source)
@parents.each do |parent|
assert_equal(excepted, DC_ELEMENTS.each do |name, value|
@rss.__send__(parent).__send__("dc_#{name}_elements")) excepted = "<#{DC_PREFIX}:#{name}>#{value}</#{DC_PREFIX}:#{name}>"
parents.each do |parent_readers|
parent = chain_reader(feed, parent_readers)
assert_equal(excepted, parent.__send__("dc_#{name}_elements"))
end end
plural_suffix = dc_plural_suffix(name, check_backward_compatibility)
reader = "dc_#{name}#{plural_suffix}"
excepted = Array.new(2, excepted).join("\n") excepted = Array.new(2, excepted).join("\n")
@parents.each do |parent| parents.each do |parent_readers|
reader = "dc_#{name}" + (name == :rights ? "es" : "s") parent = chain_reader(feed, parent_readers)
elems = @rss.__send__(parent).__send__(reader) elems = parent.__send__(reader)
klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}" klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}"
klass = DublinCoreModel.const_get(klass_name) klass = DublinCoreModel.const_get(klass_name)
elems << klass.new(@rss.__send__(parent).__send__("dc_#{name}")) elems << klass.new(parent.__send__("dc_#{name}"))
assert_equal(excepted, assert_equal(excepted, parent.__send__("dc_#{name}_elements"))
@rss.__send__(parent).__send__("dc_#{name}_elements"))
end end
end end
REXML::Document.new(@rss_source).root.each_element do |parent| targets ||= parents.collect do |parent_readers|
if @parents.include?(parent.name) parent_readers.first
end
feed_root = REXML::Document.new(source).root
targets.each do |target_xpath|
parent = feed_root.elements[target_xpath]
parent.each_element do |elem| parent.each_element do |elem|
if elem.namespace == @uri if elem.namespace == DC_URI
assert_equal(CGI.escapeHTML(elem.text), assert_equal(CGI.escapeHTML(elem.text),
@elems[elem.name.intern].to_s) DC_ELEMENTS[elem.name.intern].to_s)
end end
end end
end end
end end
end end
end
end end

View file

@ -11,7 +11,7 @@ module RSS
def setup def setup
@prefix = "image" @prefix = "image"
@uri = "http://web.resource.org/rss/1.0/modules/image/" @uri = "http://purl.org/rss/1.0/modules/image/"
@favicon_attrs = { @favicon_attrs = {
"rdf:about" => "http://www.kuro5hin.org/favicon.ico", "rdf:about" => "http://www.kuro5hin.org/favicon.ico",
@ -75,6 +75,16 @@ EOR
Parser.parse(make_RDF(<<-EOR, @ns)) Parser.parse(make_RDF(<<-EOR, @ns))
#{make_channel(@channel_nodes * 2)} #{make_channel(@channel_nodes * 2)}
#{make_item} #{make_item}
EOR
end
attrs = {"rdf:about" => "http://www.example.org/item.png"}
contents = [["#{@prefix}:width", "80"]] * 5
image_item = make_element("#{@prefix}:item", attrs, contents)
assert_too_much_tag("width", "item") do
Parser.parse(make_RDF(<<-EOR, @ns))
#{make_channel}
#{make_item(image_item)}
EOR EOR
end end
end end
@ -163,19 +173,23 @@ EOR
def test_favicon_to_s def test_favicon_to_s
favicon = @rss.channel.image_favicon favicon = @rss.channel.image_favicon
expected = REXML::Document.new(make_element("#{@prefix}:favicon", expected_xml = image_xmlns_container(make_element("#{@prefix}:favicon",
@favicon_attrs, @favicon_attrs,
@favicon_contents)) @favicon_contents))
actual = REXML::Document.new(favicon.to_s(false, "")) expected = REXML::Document.new(expected_xml)
actual_xml = image_xmlns_container(favicon.to_s(false, ""))
actual = REXML::Document.new(actual_xml)
assert_equal(expected.to_s, actual.to_s) assert_equal(expected.to_s, actual.to_s)
end end
def test_item_to_s def test_item_to_s
@rss.items.each_with_index do |item, i| @rss.items.each_with_index do |item, i|
attrs, contents = @items[i] attrs, contents = @items[i]
expected_s = make_element("#{@prefix}:item", attrs, contents) expected_xml = make_element("#{@prefix}:item", attrs, contents)
expected = REXML::Document.new(expected_s) expected_xml = image_xmlns_container(expected_xml)
actual = REXML::Document.new(item.image_item.to_s(false, "")) expected = REXML::Document.new(expected_xml)
actual_xml = image_xmlns_container(item.image_item.to_s(false, ""))
actual = REXML::Document.new(actual_xml)
assert_equal(expected[0].attributes, actual[0].attributes) assert_equal(expected[0].attributes, actual[0].attributes)
@ -187,5 +201,14 @@ EOR
end end
end end
private
def image_xmlns_container(content)
xmlns_container({
@prefix => @uri,
"dc" => "http://purl.org/dc/elements/1.1/",
"rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
},
content)
end
end end
end end

View file

@ -36,6 +36,5 @@ EOR
assert_equal("#{prefix} #{orig_image.url}", new_image.url) assert_equal("#{prefix} #{orig_image.url}", new_image.url)
assert_equal("#{prefix} #{orig_image.link}", new_image.link) assert_equal("#{prefix} #{orig_image.link}", new_image.link)
end end
end end
end end

347
test/rss/test_itunes.rb Normal file
View file

@ -0,0 +1,347 @@
require "cgi"
require "rexml/document"
require "rss-testcase"
require "rss/2.0"
require "rss/itunes"
module RSS
class TestITunes < TestCase
def test_author
assert_itunes_author(%w(channel)) do |content, xmlns|
make_rss20(make_channel20(content), xmlns)
end
assert_itunes_author(%w(items last)) do |content, xmlns|
make_rss20(make_channel20(make_item20(content)), xmlns)
end
end
def test_block
assert_itunes_block(%w(items last)) do |content, xmlns|
make_rss20(make_channel20(make_item20(content)), xmlns)
end
end
def test_category
assert_itunes_category(%w(channel)) do |content, xmlns|
make_rss20(make_channel20(content), xmlns)
end
end
def test_image
assert_itunes_image(%w(channel)) do |content, xmlns|
make_rss20(make_channel20(content), xmlns)
end
end
def test_duration
assert_itunes_duration(%w(items last)) do |content, xmlns|
make_rss20(make_channel20(make_item20(content)), xmlns)
end
end
def test_explicit
assert_itunes_explicit(%w(channel)) do |content, xmlns|
make_rss20(make_channel20(content), xmlns)
end
assert_itunes_explicit(%w(items last)) do |content, xmlns|
make_rss20(make_channel20(make_item20(content)), xmlns)
end
end
def test_keywords
assert_itunes_keywords(%w(channel)) do |content, xmlns|
make_rss20(make_channel20(content), xmlns)
end
assert_itunes_keywords(%w(items last)) do |content, xmlns|
make_rss20(make_channel20(make_item20(content)), xmlns)
end
end
def test_new_feed_url
assert_itunes_new_feed_url(%w(channel)) do |content, xmlns|
make_rss20(make_channel20(content), xmlns)
end
end
def test_owner
assert_itunes_owner(%w(channel)) do |content, xmlns|
make_rss20(make_channel20(content), xmlns)
end
end
def test_subtitle
assert_itunes_subtitle(%w(channel)) do |content, xmlns|
make_rss20(make_channel20(content), xmlns)
end
assert_itunes_subtitle(%w(items last)) do |content, xmlns|
make_rss20(make_channel20(make_item20(content)), xmlns)
end
end
def test_summary
assert_itunes_summary(%w(channel)) do |content, xmlns|
make_rss20(make_channel20(content), xmlns)
end
assert_itunes_summary(%w(items last)) do |content, xmlns|
make_rss20(make_channel20(make_item20(content)), xmlns)
end
end
private
def itunes_rss20_parse(content, &maker)
xmlns = {"itunes" => "http://www.itunes.com/dtds/podcast-1.0.dtd"}
rss20_xml = maker.call(content, xmlns)
::RSS::Parser.parse(rss20_xml)
end
def assert_itunes_author(readers, &rss20_maker)
_wrap_assertion do
author = "John Lennon"
rss20 = itunes_rss20_parse(tag("itunes:author", author), &rss20_maker)
target = chain_reader(rss20, readers)
assert_equal(author, target.itunes_author)
end
end
def _assert_itunes_block(value, boolean_value, readers, &rss20_maker)
rss20 = itunes_rss20_parse(tag("itunes:block", value), &rss20_maker)
target = chain_reader(rss20, readers)
assert_equal(value, target.itunes_block)
assert_equal(boolean_value, target.itunes_block?)
end
def assert_itunes_block(readers, &rss20_maker)
_wrap_assertion do
_assert_itunes_block("yes", true, readers, &rss20_maker)
_assert_itunes_block("Yes", true, readers, &rss20_maker)
_assert_itunes_block("no", false, readers, &rss20_maker)
_assert_itunes_block("", false, readers, &rss20_maker)
end
end
def _assert_itunes_category(categories, readers, &rss20_maker)
cats = categories.collect do |category|
if category.is_a?(Array)
category, sub_category = category
tag("itunes:category",
tag("itunes:category", nil, {"text" => sub_category}),
{"text" => category})
else
tag("itunes:category", nil, {"text" => category})
end
end.join
rss20 = itunes_rss20_parse(cats, &rss20_maker)
target = chain_reader(rss20, readers)
actual_categories = target.itunes_categories.collect do |category|
cat = category.text
if category.itunes_categories.empty?
cat
else
[cat, *category.itunes_categories.collect {|c| c.text}]
end
end
assert_equal(categories, actual_categories)
end
def assert_itunes_category(readers, &rss20_maker)
_wrap_assertion do
_assert_itunes_category(["Audio Blogs"], readers, &rss20_maker)
_assert_itunes_category([["Arts & Entertainment", "Games"]],
readers, &rss20_maker)
_assert_itunes_category([["Arts & Entertainment", "Games"],
["Technology", "Computers"],
"Audio Blogs"],
readers, &rss20_maker)
end
end
def assert_itunes_image(readers, &rss20_maker)
_wrap_assertion do
url = "http://example.com/podcasts/everything/AllAboutEverything.jpg"
content = tag("itunes:image", nil, {"href" => url})
rss20 = itunes_rss20_parse(content, &rss20_maker)
target = chain_reader(rss20, readers)
assert_not_nil(target.itunes_image)
assert_equal(url, target.itunes_image.href)
assert_missing_attribute("image", "href") do
content = tag("itunes:image")
itunes_rss20_parse(content, &rss20_maker)
end
end
end
def _assert_itunes_duration(hour, minute, second, value,
readers, &rss20_maker)
content = tag("itunes:duration", value)
rss20 = itunes_rss20_parse(content, &rss20_maker)
duration = chain_reader(rss20, readers).itunes_duration
assert_equal(value, duration.content)
assert_equal(hour, duration.hour)
assert_equal(minute, duration.minute)
assert_equal(second, duration.second)
end
def _assert_itunes_duration_not_available_value(value, &rss20_maker)
assert_not_available_value("duration", value) do
content = tag("itunes:duration", value)
itunes_rss20_parse(content, &rss20_maker)
end
end
def assert_itunes_duration(readers, &rss20_maker)
_wrap_assertion do
_assert_itunes_duration(7, 14, 5, "07:14:05", readers, &rss20_maker)
_assert_itunes_duration(7, 14, 5, "7:14:05", readers, &rss20_maker)
_assert_itunes_duration(0, 4, 55, "04:55", readers, &rss20_maker)
_assert_itunes_duration(0, 4, 5, "4:05", readers, &rss20_maker)
_assert_itunes_duration_not_available_value("5", &rss20_maker)
_assert_itunes_duration_not_available_value("09:07:14:05", &rss20_maker)
_assert_itunes_duration_not_available_value("10:5", &rss20_maker)
_assert_itunes_duration_not_available_value("10:03:5", &rss20_maker)
_assert_itunes_duration_not_available_value("10:3:05", &rss20_maker)
_assert_itunes_duration_not_available_value("xx:xx:xx", &rss20_maker)
end
end
def _assert_itunes_explicit(explicit, value, readers, &rss20_maker)
content = tag("itunes:explicit", value)
rss20 = itunes_rss20_parse(content, &rss20_maker)
target = chain_reader(rss20, readers)
assert_equal(value, target.itunes_explicit)
assert_equal(explicit, target.itunes_explicit?)
end
def assert_itunes_explicit(readers, &rss20_maker)
_wrap_assertion do
_assert_itunes_explicit(true, "yes", readers, &rss20_maker)
_assert_itunes_explicit(false, "clean", readers, &rss20_maker)
_assert_itunes_explicit(nil, "no", readers, &rss20_maker)
end
end
def _assert_itunes_keywords(keywords, value, readers, &rss20_maker)
content = tag("itunes:keywords", value)
rss20 = itunes_rss20_parse(content, &rss20_maker)
target = chain_reader(rss20, readers)
assert_equal(keywords, target.itunes_keywords)
end
def assert_itunes_keywords(readers, &rss20_maker)
_wrap_assertion do
_assert_itunes_keywords(["salt"], "salt", readers, &rss20_maker)
_assert_itunes_keywords(["salt"], " salt ", readers, &rss20_maker)
_assert_itunes_keywords(["salt", "pepper", "shaker", "exciting"],
"salt, pepper, shaker, exciting",
readers, &rss20_maker)
_assert_itunes_keywords(["metric", "socket", "wrenches", "toolsalt"],
"metric, socket, wrenches, toolsalt",
readers, &rss20_maker)
_assert_itunes_keywords(["olitics", "red", "blue", "state"],
"olitics, red, blue, state",
readers, &rss20_maker)
end
end
def assert_itunes_new_feed_url(readers, &rss20_maker)
_wrap_assertion do
url = "http://newlocation.com/example.rss"
content = tag("itunes:new-feed-url", url)
rss20 = itunes_rss20_parse(content, &rss20_maker)
target = chain_reader(rss20, readers)
assert_equal(url, target.itunes_new_feed_url)
end
end
def _assert_itunes_owner(name, email, readers, &rss20_maker)
content = tag("itunes:owner",
tag("itunes:name", name) + tag("itunes:email", email))
rss20 = itunes_rss20_parse(content, &rss20_maker)
owner = chain_reader(rss20, readers).itunes_owner
assert_equal(name, owner.itunes_name)
assert_equal(email, owner.itunes_email)
end
def assert_itunes_owner(readers, &rss20_maker)
_wrap_assertion do
_assert_itunes_owner("John Doe", "john.doe@example.com",
readers, &rss20_maker)
assert_missing_tag("name", "owner") do
content = tag("itunes:owner")
itunes_rss20_parse(content, &rss20_maker)
end
assert_missing_tag("name", "owner") do
content = tag("itunes:owner",
tag("itunes:email", "john.doe@example.com"))
itunes_rss20_parse(content, &rss20_maker)
end
assert_missing_tag("email", "owner") do
content = tag("itunes:owner", tag("itunes:name", "John Doe"))
itunes_rss20_parse(content, &rss20_maker)
end
end
end
def _assert_itunes_subtitle(value, readers, &rss20_maker)
content = tag("itunes:subtitle", value)
rss20 = itunes_rss20_parse(content, &rss20_maker)
target = chain_reader(rss20, readers)
assert_equal(value, target.itunes_subtitle)
end
def assert_itunes_subtitle(readers, &rss20_maker)
_wrap_assertion do
_assert_itunes_subtitle("A show about everything", readers, &rss20_maker)
_assert_itunes_subtitle("A short primer on table spices",
readers, &rss20_maker)
_assert_itunes_subtitle("Comparing socket wrenches is fun!",
readers, &rss20_maker)
_assert_itunes_subtitle("Red + Blue != Purple", readers, &rss20_maker)
end
end
def _assert_itunes_summary(value, readers, &rss20_maker)
content = tag("itunes:summary", value)
rss20 = itunes_rss20_parse(content, &rss20_maker)
target = chain_reader(rss20, readers)
assert_equal(value, target.itunes_summary)
end
def assert_itunes_summary(readers, &rss20_maker)
_wrap_assertion do
_assert_itunes_summary("All About Everything is a show about " +
"everything. Each week we dive into any " +
"subject known to man and talk about it as " +
"much as we can. Look for our Podcast in " +
"the iTunes Music Store",
readers, &rss20_maker)
_assert_itunes_summary("This week we talk about salt and pepper " +
"shakers, comparing and contrasting pour " +
"rates, construction materials, and overall " +
"aesthetics. Come and join the party!",
readers, &rss20_maker)
_assert_itunes_summary("This week we talk about metric vs. old " +
"english socket wrenches. Which one is " +
"better? Do you really need both? Get all " +
"of your answers here.",
readers, &rss20_maker)
_assert_itunes_summary("This week we talk about surviving in a " +
"Red state if youre a Blue person. Or " +
"vice versa.",
readers, &rss20_maker)
end
end
end
end

View file

@ -11,17 +11,20 @@ module RSS
rss = RSS::Maker.make("0.9") do |maker| rss = RSS::Maker.make("0.9") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
end end
assert_equal("0.91", rss.rss_version) assert_equal("0.91", rss.rss_version)
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
end end
assert_equal("0.91", rss.rss_version) assert_equal("0.91", rss.rss_version)
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
maker.encoding = "EUC-JP" maker.encoding = "EUC-JP"
end end
@ -30,6 +33,7 @@ module RSS
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
maker.standalone = "yes" maker.standalone = "yes"
end end
@ -38,6 +42,7 @@ module RSS
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
maker.encoding = "EUC-JP" maker.encoding = "EUC-JP"
maker.standalone = "yes" maker.standalone = "yes"
@ -68,6 +73,9 @@ module RSS
pubDate = Time.now pubDate = Time.now
lastBuildDate = Time.now lastBuildDate = Time.now
image_url = "http://example.com/logo.png"
image_title = "Logo"
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
maker.channel.title = title maker.channel.title = title
maker.channel.link = link maker.channel.link = link
@ -91,6 +99,9 @@ module RSS
new_hour.content = hour new_hour.content = hour
end end
end end
maker.image.url = image_url
maker.image.title = image_title
end end
channel = rss.channel channel = rss.channel
@ -115,7 +126,11 @@ module RSS
end end
assert(channel.items.empty?) assert(channel.items.empty?)
assert_nil(channel.image)
assert_equal(image_url, channel.image.url)
assert_equal(image_title, channel.image.title)
assert_equal(link, channel.image.link)
assert_nil(channel.textInput) assert_nil(channel.textInput)
end end
@ -211,7 +226,8 @@ module RSS
height = "400" height = "400"
description = "an image" description = "an image"
rss = RSS::Maker.make("0.91") do |maker| assert_not_set_error("maker.image", %w(title)) do
RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
maker.channel.link = link maker.channel.link = link
@ -221,7 +237,7 @@ module RSS
maker.image.height = height maker.image.height = height
maker.image.description = description maker.image.description = description
end end
assert_nil(rss.channel.image) end
assert_not_set_error("maker.channel", %w(link)) do assert_not_set_error("maker.channel", %w(link)) do
RSS::Maker.make("0.91") do |maker| RSS::Maker.make("0.91") do |maker|
@ -237,7 +253,8 @@ module RSS
end end
end end
rss = RSS::Maker.make("0.91") do |maker| assert_not_set_error("maker.image", %w(url)) do
RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
maker.channel.link = link maker.channel.link = link
@ -247,16 +264,17 @@ module RSS
maker.image.height = height maker.image.height = height
maker.image.description = description maker.image.description = description
end end
assert_nil(rss.channel.image) end
end end
def test_items def test_items(with_convenience_way=true)
title = "TITLE" title = "TITLE"
link = "http://hoge.com/" link = "http://hoge.com/"
description = "text hoge fuga" description = "text hoge fuga"
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
end end
assert(rss.channel.items.empty?) assert(rss.channel.items.empty?)
@ -268,6 +286,8 @@ module RSS
item.link = link item.link = link
# item.description = description # item.description = description
end end
setup_dummy_image(maker)
end end
assert_equal(1, rss.channel.items.size) assert_equal(1, rss.channel.items.size)
item = rss.channel.items.first item = rss.channel.items.first
@ -281,43 +301,55 @@ module RSS
setup_dummy_channel(maker) setup_dummy_channel(maker)
item_size.times do |i| item_size.times do |i|
maker.items.new_item do |item| maker.items.new_item do |_item|
item.title = "#{title}#{i}" _item.title = "#{title}#{i}"
item.link = "#{link}#{i}" _item.link = "#{link}#{i}"
item.description = "#{description}#{i}" _item.description = "#{description}#{i}"
end end
end end
maker.items.do_sort = true maker.items.do_sort = true
setup_dummy_image(maker)
end end
assert_equal(item_size, rss.items.size) assert_equal(item_size, rss.items.size)
rss.channel.items.each_with_index do |item, i| rss.channel.items.each_with_index do |_item, i|
assert_equal("#{title}#{i}", item.title) assert_equal("#{title}#{i}", _item.title)
assert_equal("#{link}#{i}", item.link) assert_equal("#{link}#{i}", _item.link)
assert_equal("#{description}#{i}", item.description) assert_equal("#{description}#{i}", _item.description)
end end
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
item_size.times do |i| item_size.times do |i|
maker.items.new_item do |item| maker.items.new_item do |_item|
item.title = "#{title}#{i}" _item.title = "#{title}#{i}"
item.link = "#{link}#{i}" _item.link = "#{link}#{i}"
item.description = "#{description}#{i}" _item.description = "#{description}#{i}"
end end
end end
maker.items.do_sort = Proc.new do |x, y| maker.items.do_sort = Proc.new do |x, y|
if with_convenience_way
y.title[-1] <=> x.title[-1] y.title[-1] <=> x.title[-1]
else
y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]}
end end
end end
setup_dummy_image(maker)
end
assert_equal(item_size, rss.items.size) assert_equal(item_size, rss.items.size)
rss.channel.items.reverse.each_with_index do |item, i| rss.channel.items.reverse.each_with_index do |_item, i|
assert_equal("#{title}#{i}", item.title) assert_equal("#{title}#{i}", _item.title)
assert_equal("#{link}#{i}", item.link) assert_equal("#{link}#{i}", _item.link)
assert_equal("#{description}#{i}", item.description) assert_equal("#{description}#{i}", _item.description)
end end
end end
def test_items_with_new_api_since_018
test_items(false)
end
def test_textInput def test_textInput
title = "fugafuga" title = "fugafuga"
description = "text hoge fuga" description = "text hoge fuga"
@ -326,6 +358,7 @@ module RSS
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
maker.textinput.title = title maker.textinput.title = title
maker.textinput.description = description maker.textinput.description = description
@ -338,7 +371,9 @@ module RSS
assert_equal(name, textInput.name) assert_equal(name, textInput.name)
assert_equal(link, textInput.link) assert_equal(link, textInput.link)
rss = RSS::Maker.make("0.91") do |maker| assert_not_set_error("maker.channel",
%w(link language description title)) do
RSS::Maker.make("0.91") do |maker|
# setup_dummy_channel(maker) # setup_dummy_channel(maker)
maker.textinput.title = title maker.textinput.title = title
@ -346,7 +381,7 @@ module RSS
maker.textinput.name = name maker.textinput.name = name
maker.textinput.link = link maker.textinput.link = link
end end
assert_nil(rss) end
end end
def test_not_valid_textInput def test_not_valid_textInput
@ -357,6 +392,7 @@ module RSS
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
# maker.textinput.title = title # maker.textinput.title = title
maker.textinput.description = description maker.textinput.description = description
@ -367,6 +403,7 @@ module RSS
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
maker.textinput.title = title maker.textinput.title = title
# maker.textinput.description = description # maker.textinput.description = description
@ -377,6 +414,7 @@ module RSS
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
maker.textinput.title = title maker.textinput.title = title
maker.textinput.description = description maker.textinput.description = description
@ -387,6 +425,7 @@ module RSS
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
maker.textinput.title = title maker.textinput.title = title
maker.textinput.description = description maker.textinput.description = description

View file

@ -8,12 +8,15 @@ module RSS
def test_rdf def test_rdf
rss = RSS::Maker.make("1.0") do |maker| rss = RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_item(maker)
end end
assert_equal("1.0", rss.rss_version) assert_equal("1.0", rss.rss_version)
rss = RSS::Maker.make("1.0") do |maker| rss = RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
maker.encoding = "EUC-JP" maker.encoding = "EUC-JP"
setup_dummy_item(maker)
end end
assert_equal("1.0", rss.rss_version) assert_equal("1.0", rss.rss_version)
assert_equal("EUC-JP", rss.encoding) assert_equal("EUC-JP", rss.encoding)
@ -21,6 +24,8 @@ module RSS
rss = RSS::Maker.make("1.0") do |maker| rss = RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
maker.standalone = "yes" maker.standalone = "yes"
setup_dummy_item(maker)
end end
assert_equal("1.0", rss.rss_version) assert_equal("1.0", rss.rss_version)
assert_equal("yes", rss.standalone) assert_equal("yes", rss.standalone)
@ -29,6 +34,8 @@ module RSS
setup_dummy_channel(maker) setup_dummy_channel(maker)
maker.encoding = "EUC-JP" maker.encoding = "EUC-JP"
maker.standalone = "yes" maker.standalone = "yes"
setup_dummy_item(maker)
end end
assert_equal("1.0", rss.rss_version) assert_equal("1.0", rss.rss_version)
assert_equal("EUC-JP", rss.encoding) assert_equal("EUC-JP", rss.encoding)
@ -49,13 +56,15 @@ module RSS
maker.channel.title = title maker.channel.title = title
maker.channel.link = link maker.channel.link = link
maker.channel.description = description maker.channel.description = description
setup_dummy_item(maker)
end end
channel = rss.channel channel = rss.channel
assert_equal(about, channel.about) assert_equal(about, channel.about)
assert_equal(title, channel.title) assert_equal(title, channel.title)
assert_equal(link, channel.link) assert_equal(link, channel.link)
assert_equal(description, channel.description) assert_equal(description, channel.description)
assert(channel.items.Seq.lis.empty?) assert_equal(1, channel.items.Seq.lis.size)
assert_nil(channel.image) assert_nil(channel.image)
assert_nil(channel.textinput) assert_nil(channel.textinput)
@ -68,13 +77,15 @@ module RSS
setup_dummy_image(maker) setup_dummy_image(maker)
setup_dummy_textinput(maker) setup_dummy_textinput(maker)
setup_dummy_item(maker)
end end
channel = rss.channel channel = rss.channel
assert_equal(about, channel.about) assert_equal(about, channel.about)
assert_equal(title, channel.title) assert_equal(title, channel.title)
assert_equal(link, channel.link) assert_equal(link, channel.link)
assert_equal(description, channel.description) assert_equal(description, channel.description)
assert(channel.items.Seq.lis.empty?) assert_equal(1, channel.items.Seq.lis.size)
assert_equal(rss.image.about, channel.image.resource) assert_equal(rss.image.about, channel.image.resource)
assert_equal(rss.textinput.about, channel.textinput.resource) assert_equal(rss.textinput.about, channel.textinput.resource)
end end
@ -134,6 +145,8 @@ module RSS
maker.image.title = title maker.image.title = title
maker.image.url = url maker.image.url = url
setup_dummy_item(maker)
end end
image = rss.image image = rss.image
assert_equal(url, image.about) assert_equal(url, image.about)
@ -164,6 +177,8 @@ module RSS
# maker.image.url = url # maker.image.url = url
maker.image.title = title maker.image.title = title
setup_dummy_item(maker)
end end
assert_nil(rss.channel.image) assert_nil(rss.channel.image)
assert_nil(rss.image) assert_nil(rss.image)
@ -174,6 +189,8 @@ module RSS
maker.image.url = url maker.image.url = url
# maker.image.title = title # maker.image.title = title
setup_dummy_item(maker)
end end
assert_nil(rss.channel.image) assert_nil(rss.channel.image)
assert_nil(rss.image) assert_nil(rss.image)
@ -186,19 +203,22 @@ module RSS
maker.image.url = url maker.image.url = url
maker.image.title = title maker.image.title = title
setup_dummy_item(maker)
end end
end end
end end
def test_items def test_items(with_convenience_way=true)
title = "TITLE" title = "TITLE"
link = "http://hoge.com/" link = "http://hoge.com/"
description = "text hoge fuga" description = "text hoge fuga"
rss = RSS::Maker.make("1.0") do |maker| assert_not_set_error("maker", %w(items)) do
RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
end end
assert(rss.items.empty?) end
rss = RSS::Maker.make("1.0") do |maker| rss = RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
@ -222,42 +242,46 @@ module RSS
setup_dummy_channel(maker) setup_dummy_channel(maker)
item_size.times do |i| item_size.times do |i|
maker.items.new_item do |item| maker.items.new_item do |_item|
item.title = "#{title}#{i}" _item.title = "#{title}#{i}"
item.link = "#{link}#{i}" _item.link = "#{link}#{i}"
item.description = "#{description}#{i}" _item.description = "#{description}#{i}"
end end
end end
maker.items.do_sort = true maker.items.do_sort = true
end end
assert_equal(item_size, rss.items.size) assert_equal(item_size, rss.items.size)
rss.items.each_with_index do |item, i| rss.items.each_with_index do |_item, i|
assert_equal("#{link}#{i}", item.about) assert_equal("#{link}#{i}", _item.about)
assert_equal("#{title}#{i}", item.title) assert_equal("#{title}#{i}", _item.title)
assert_equal("#{link}#{i}", item.link) assert_equal("#{link}#{i}", _item.link)
assert_equal("#{description}#{i}", item.description) assert_equal("#{description}#{i}", _item.description)
end end
rss = RSS::Maker.make("1.0") do |maker| rss = RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
item_size.times do |i| item_size.times do |i|
maker.items.new_item do |item| maker.items.new_item do |_item|
item.title = "#{title}#{i}" _item.title = "#{title}#{i}"
item.link = "#{link}#{i}" _item.link = "#{link}#{i}"
item.description = "#{description}#{i}" _item.description = "#{description}#{i}"
end end
end end
maker.items.do_sort = Proc.new do |x, y| maker.items.do_sort = Proc.new do |x, y|
if with_convenience_way
y.title[-1] <=> x.title[-1] y.title[-1] <=> x.title[-1]
else
y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]}
end
end end
end end
assert_equal(item_size, rss.items.size) assert_equal(item_size, rss.items.size)
rss.items.reverse.each_with_index do |item, i| rss.items.reverse.each_with_index do |_item, i|
assert_equal("#{link}#{i}", item.about) assert_equal("#{link}#{i}", _item.about)
assert_equal("#{title}#{i}", item.title) assert_equal("#{title}#{i}", _item.title)
assert_equal("#{link}#{i}", item.link) assert_equal("#{link}#{i}", _item.link)
assert_equal("#{description}#{i}", item.description) assert_equal("#{description}#{i}", _item.description)
end end
max_size = item_size / 2 max_size = item_size / 2
@ -265,64 +289,70 @@ module RSS
setup_dummy_channel(maker) setup_dummy_channel(maker)
item_size.times do |i| item_size.times do |i|
maker.items.new_item do |item| maker.items.new_item do |_item|
item.title = "#{title}#{i}" _item.title = "#{title}#{i}"
item.link = "#{link}#{i}" _item.link = "#{link}#{i}"
item.description = "#{description}#{i}" _item.description = "#{description}#{i}"
end end
end end
maker.items.max_size = max_size maker.items.max_size = max_size
end end
assert_equal(max_size, rss.items.size) assert_equal(max_size, rss.items.size)
rss.items.each_with_index do |item, i| rss.items.each_with_index do |_item, i|
assert_equal("#{link}#{i}", item.about) assert_equal("#{link}#{i}", _item.about)
assert_equal("#{title}#{i}", item.title) assert_equal("#{title}#{i}", _item.title)
assert_equal("#{link}#{i}", item.link) assert_equal("#{link}#{i}", _item.link)
assert_equal("#{description}#{i}", item.description) assert_equal("#{description}#{i}", _item.description)
end end
max_size = 0 max_size = 0
rss = RSS::Maker.make("1.0") do |maker| assert_not_set_error("maker", %w(items)) do
RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
item_size.times do |i| item_size.times do |i|
maker.items.new_item do |item| maker.items.new_item do |_item|
item.title = "#{title}#{i}" _item.title = "#{title}#{i}"
item.link = "#{link}#{i}" _item.link = "#{link}#{i}"
item.description = "#{description}#{i}" _item.description = "#{description}#{i}"
end end
end end
maker.items.max_size = max_size maker.items.max_size = max_size
end end
assert_equal(max_size, rss.items.size) end
max_size = -2 max_size = -2
rss = RSS::Maker.make("1.0") do |maker| rss = RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
item_size.times do |i| item_size.times do |i|
maker.items.new_item do |item| maker.items.new_item do |_item|
item.title = "#{title}#{i}" _item.title = "#{title}#{i}"
item.link = "#{link}#{i}" _item.link = "#{link}#{i}"
item.description = "#{description}#{i}" _item.description = "#{description}#{i}"
end end
end end
maker.items.max_size = max_size maker.items.max_size = max_size
end end
assert_equal(item_size + max_size + 1, rss.items.size) assert_equal(item_size + max_size + 1, rss.items.size)
rss.items.each_with_index do |item, i| rss.items.each_with_index do |_item, i|
assert_equal("#{link}#{i}", item.about) assert_equal("#{link}#{i}", _item.about)
assert_equal("#{title}#{i}", item.title) assert_equal("#{title}#{i}", _item.title)
assert_equal("#{link}#{i}", item.link) assert_equal("#{link}#{i}", _item.link)
assert_equal("#{description}#{i}", item.description) assert_equal("#{description}#{i}", _item.description)
end end
end end
def test_items_with_new_api_since_018
test_items(false)
end
def test_not_valid_items def test_not_valid_items
title = "TITLE" title = "TITLE"
link = "http://hoge.com/" link = "http://hoge.com/"
rss = RSS::Maker.make("1.0") do |maker| assert_not_set_error("maker.item", %w(title)) do
RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
maker.items.new_item do |item| maker.items.new_item do |item|
@ -330,9 +360,10 @@ module RSS
item.link = link item.link = link
end end
end end
assert(rss.items.empty?) end
rss = RSS::Maker.make("1.0") do |maker| assert_not_set_error("maker.item", %w(link)) do
RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
maker.items.new_item do |item| maker.items.new_item do |item|
@ -340,7 +371,18 @@ module RSS
# item.link = link # item.link = link
end end
end end
assert(rss.items.empty?) end
assert_not_set_error("maker.item", %w(title link)) do
RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker)
maker.items.new_item do |item|
# item.title = title
# item.link = link
end
end
end
end end
def test_textinput def test_textinput
@ -356,6 +398,8 @@ module RSS
maker.textinput.title = title maker.textinput.title = title
maker.textinput.description = description maker.textinput.description = description
maker.textinput.name = name maker.textinput.name = name
setup_dummy_item(maker)
end end
textinput = rss.textinput textinput = rss.textinput
assert_equal(link, textinput.about) assert_equal(link, textinput.about)
@ -365,7 +409,8 @@ module RSS
assert_equal(description, textinput.description) assert_equal(description, textinput.description)
assert_equal(link, textinput.link) assert_equal(link, textinput.link)
rss = RSS::Maker.make("1.0") do |maker| assert_not_set_error("maker.channel", %w(about link description title)) do
RSS::Maker.make("1.0") do |maker|
# setup_dummy_channel(maker) # setup_dummy_channel(maker)
maker.textinput.link = link maker.textinput.link = link
@ -373,7 +418,7 @@ module RSS
maker.textinput.description = description maker.textinput.description = description
maker.textinput.name = name maker.textinput.name = name
end end
assert_nil(rss) end
end end
def test_not_valid_textinput def test_not_valid_textinput
@ -389,6 +434,8 @@ module RSS
maker.textinput.title = title maker.textinput.title = title
maker.textinput.description = description maker.textinput.description = description
maker.textinput.name = name maker.textinput.name = name
setup_dummy_item(maker)
end end
assert_nil(rss.channel.textinput) assert_nil(rss.channel.textinput)
assert_nil(rss.textinput) assert_nil(rss.textinput)
@ -400,6 +447,8 @@ module RSS
# maker.textinput.title = title # maker.textinput.title = title
maker.textinput.description = description maker.textinput.description = description
maker.textinput.name = name maker.textinput.name = name
setup_dummy_item(maker)
end end
assert_nil(rss.channel.textinput) assert_nil(rss.channel.textinput)
assert_nil(rss.textinput) assert_nil(rss.textinput)
@ -411,6 +460,8 @@ module RSS
maker.textinput.title = title maker.textinput.title = title
# maker.textinput.description = description # maker.textinput.description = description
maker.textinput.name = name maker.textinput.name = name
setup_dummy_item(maker)
end end
assert_nil(rss.channel.textinput) assert_nil(rss.channel.textinput)
assert_nil(rss.textinput) assert_nil(rss.textinput)
@ -422,6 +473,8 @@ module RSS
maker.textinput.title = title maker.textinput.title = title
maker.textinput.description = description maker.textinput.description = description
# maker.textinput.name = name # maker.textinput.name = name
setup_dummy_item(maker)
end end
assert_nil(rss.channel.textinput) assert_nil(rss.channel.textinput)
assert_nil(rss.textinput) assert_nil(rss.textinput)

View file

@ -353,7 +353,7 @@ module RSS
assert_nil(rss.image) assert_nil(rss.image)
end end
def test_items def test_items(with_convenience_way=true)
title = "TITLE" title = "TITLE"
link = "http://hoge.com/" link = "http://hoge.com/"
description = "text hoge fuga" description = "text hoge fuga"
@ -407,7 +407,11 @@ module RSS
end end
end end
maker.items.do_sort = Proc.new do |x, y| maker.items.do_sort = Proc.new do |x, y|
if with_convenience_way
y.title[-1] <=> x.title[-1] y.title[-1] <=> x.title[-1]
else
y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]}
end
end end
end end
assert_equal(item_size, rss.items.size) assert_equal(item_size, rss.items.size)
@ -422,6 +426,10 @@ module RSS
end end
end end
def test_items_with_new_api_since_018
test_items(false)
end
def test_guid def test_guid
isPermaLink = "true" isPermaLink = "true"
content = "http://inessential.com/2002/09/01.php#a2" content = "http://inessential.com/2002/09/01.php#a2"
@ -606,7 +614,8 @@ module RSS
assert_equal(name, textInput.name) assert_equal(name, textInput.name)
assert_equal(link, textInput.link) assert_equal(link, textInput.link)
rss = RSS::Maker.make("2.0") do |maker| assert_not_set_error("maker.channel", %w(link description title)) do
RSS::Maker.make("2.0") do |maker|
# setup_dummy_channel(maker) # setup_dummy_channel(maker)
maker.textinput.title = title maker.textinput.title = title
@ -614,7 +623,7 @@ module RSS
maker.textinput.name = name maker.textinput.name = name
maker.textinput.link = link maker.textinput.link = link
end end
assert_nil(rss) end
end end
def test_not_valid_textInput def test_not_valid_textInput

View file

@ -0,0 +1,367 @@
require "rss-testcase"
require "rss/maker"
module RSS
class TestMakerAtomEntry < TestCase
def test_root_element
entry = Maker.make("atom:entry") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_equal(["atom", "1.0", "entry"], entry.feed_info)
entry = Maker.make("atom:entry") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.encoding = "EUC-JP"
end
assert_equal(["atom", "1.0", "entry"], entry.feed_info)
assert_equal("EUC-JP", entry.encoding)
entry = Maker.make("atom:entry") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.standalone = "yes"
end
assert_equal(["atom", "1.0", "entry"], entry.feed_info)
assert_equal("yes", entry.standalone)
entry = Maker.make("atom:entry") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.encoding = "EUC-JP"
maker.standalone = "yes"
end
assert_equal(["atom", "1.0", "entry"], entry.feed_info)
assert_equal("EUC-JP", entry.encoding)
assert_equal("yes", entry.standalone)
end
def test_invalid_feed
assert_not_set_error("maker.item", %w(id title author updated)) do
Maker.make("atom:entry") do |maker|
end
end
assert_not_set_error("maker.item", %w(id title updated)) do
Maker.make("atom:entry") do |maker|
maker.channel.author = "foo"
end
end
assert_not_set_error("maker.item", %w(title updated)) do
Maker.make("atom:entry") do |maker|
maker.channel.author = "foo"
maker.channel.id = "http://example.com"
end
end
assert_not_set_error("maker.item", %w(updated)) do
Maker.make("atom:entry") do |maker|
maker.channel.author = "foo"
maker.channel.id = "http://example.com"
maker.channel.title = "Atom Feed"
end
end
assert_not_set_error("maker.item", %w(author)) do
Maker.make("atom:entry") do |maker|
maker.channel.id = "http://example.com"
maker.channel.title = "Atom Feed"
maker.channel.updated = Time.now
end
end
entry = Maker.make("atom:entry") do |maker|
maker.channel.author = "Foo"
maker.channel.id = "http://example.com"
maker.channel.title = "Atom Feed"
maker.channel.updated = Time.now
end
assert_not_nil(entry)
end
def test_author
assert_maker_atom_persons("entry",
["channel", "authors"],
["authors"],
"maker.channel.author") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_persons("entry",
["items", "first", "authors"],
["authors"],
"maker.item.author",
"maker.item", ["author"]) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.channel.authors.clear
maker.items.first.authors.clear
end
assert_maker_atom_persons("entry",
["items", "first", "source", "authors"],
["source", "authors"],
"maker.item.source.author") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_category
assert_maker_atom_categories("entry",
["channel", "categories"],
["categories"],
"maker.channel.category") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_categories("entry",
["items", "first", "categories"],
["categories"],
"maker.item.category") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_categories("entry",
["items", "first", "source", "categories"],
["source", "categories"],
"maker.item.source.category") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_content
assert_maker_atom_content("entry",
["items", "first", "content"],
["content"],
"maker.item.content") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_contributor
assert_maker_atom_persons("entry",
["channel", "contributors"],
["contributors"],
"maker.channel.contributor") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_persons("entry",
["items", "first", "contributors"],
["contributors"],
"maker.item.contributor") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_persons("entry",
["items", "first", "source", "contributors"],
["source", "contributors"],
"maker.item.source.contributor") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_link
assert_maker_atom_links("entry",
["channel", "links"],
["links"],
"maker.channel.link") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.channel.links.clear
maker.items.first.links.clear
end
assert_maker_atom_links("entry",
["items", "first", "links"],
["links"],
"maker.item.link") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.channel.links.clear
maker.items.first.links.clear
end
assert_maker_atom_links("entry",
["items", "first", "source", "links"],
["source", "links"],
"maker.item.source.link", true) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_published
assert_maker_atom_date_construct("entry",
["items", "first", "published"],
["published"]
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_rights
assert_maker_atom_text_construct("entry",
["channel", "copyright"],
["rights"]) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_text_construct("entry",
["items", "first", "rights"],
["rights"],
nil, nil, "maker.item.rights"
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_text_construct("entry",
["items", "first", "source", "rights"],
["source", "rights"],
nil, nil, "maker.item.source.rights"
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_source_generator
assert_maker_atom_generator("entry",
["items", "first", "source", "generator"],
["source", "generator"],
"maker.item.source.generator") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_source_icon
assert_maker_atom_icon("entry",
["items", "first", "source", "icon"],
["source", "icon"],
nil, "maker.item.source.icon") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_source_id
assert_maker_atom_id("entry",
["items", "first", "source"],
["source"],
"maker.item.source") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_source_logo
assert_maker_atom_logo("entry",
["items", "first", "source", "logo"],
["source", "logo"],
nil,
"maker.item.source.logo") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_source_subtitle
assert_maker_atom_text_construct("entry",
["items", "first", "source", "subtitle"],
["source", "subtitle"],
nil, nil,
"maker.item.source.subtitle") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_summary
assert_maker_atom_text_construct("entry",
["items", "first", "description"],
["summary"],
nil, nil, "maker.item.description"
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_title
assert_maker_atom_text_construct("entry",
["channel", "title"], ["title"],
"maker.item", ["title"],
"maker.channel.title") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.channel.title = nil
maker.items.first.title = nil
end
assert_maker_atom_text_construct("entry",
["items", "first", "title"],
["title"],
"maker.item", ["title"],
"maker.item.title") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.channel.title = nil
maker.items.first.title = nil
end
assert_maker_atom_text_construct("entry",
["items", "first", "source", "title"],
["source", "title"],
nil, nil, "maker.item.source.title"
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_updated
assert_maker_atom_date_construct("entry",
["channel", "updated"], ["updated"],
"maker.item", ["updated"]) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.channel.updated = nil
maker.items.first.updated = nil
end
assert_maker_atom_date_construct("entry",
["items", "first", "updated"],
["updated"],
"maker.item", ["updated"]) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.channel.updated = nil
maker.items.first.updated = nil
end
assert_maker_atom_date_construct("entry",
["items", "first", "source", "updated"],
["source", "updated"]) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
end
end

View file

@ -0,0 +1,389 @@
require "rss-testcase"
require "rss/maker"
module RSS
class TestMakerAtomFeed < TestCase
def test_root_element
feed = Maker.make("atom") do |maker|
setup_dummy_channel_atom(maker)
end
assert_equal(["atom", "1.0", "feed"], feed.feed_info)
feed = Maker.make("atom") do |maker|
setup_dummy_channel_atom(maker)
maker.encoding = "EUC-JP"
end
assert_equal(["atom", "1.0", "feed"], feed.feed_info)
assert_equal("EUC-JP", feed.encoding)
feed = Maker.make("atom") do |maker|
setup_dummy_channel_atom(maker)
maker.standalone = "yes"
end
assert_equal(["atom", "1.0", "feed"], feed.feed_info)
assert_equal("yes", feed.standalone)
feed = Maker.make("atom") do |maker|
setup_dummy_channel_atom(maker)
maker.encoding = "EUC-JP"
maker.standalone = "yes"
end
assert_equal(["atom", "1.0", "feed"], feed.feed_info)
assert_equal("EUC-JP", feed.encoding)
assert_equal("yes", feed.standalone)
end
def test_invalid_feed
assert_not_set_error("maker.channel", %w(id title author updated)) do
Maker.make("atom") do |maker|
end
end
assert_not_set_error("maker.channel", %w(id title updated)) do
Maker.make("atom") do |maker|
maker.channel.author = "foo"
end
end
assert_not_set_error("maker.channel", %w(title updated)) do
Maker.make("atom") do |maker|
maker.channel.author = "foo"
maker.channel.id = "http://example.com"
end
end
assert_not_set_error("maker.channel", %w(updated)) do
Maker.make("atom") do |maker|
maker.channel.author = "foo"
maker.channel.id = "http://example.com"
maker.channel.title = "Atom Feed"
end
end
assert_not_set_error("maker.channel", %w(author)) do
Maker.make("atom") do |maker|
maker.channel.id = "http://example.com"
maker.channel.title = "Atom Feed"
maker.channel.updated = Time.now
end
end
feed = Maker.make("atom") do |maker|
maker.channel.author = "Foo"
maker.channel.id = "http://example.com"
maker.channel.title = "Atom Feed"
maker.channel.updated = Time.now
end
assert_not_nil(feed)
end
def test_author
assert_maker_atom_persons("feed",
["channel", "authors"],
["authors"],
"maker.channel.author") do |maker|
setup_dummy_channel_atom(maker)
end
assert_not_set_error("maker.channel", %w(author)) do
RSS::Maker.make("atom") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.channel.authors.clear
end
end
assert_maker_atom_persons("feed",
["items", "first", "authors"],
["entries", "first", "authors"],
"maker.item.author") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_persons("feed",
["items", "first", "source", "authors"],
["entries", "first", "source", "authors"],
"maker.item.source.author") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_category
assert_maker_atom_categories("feed",
["channel", "categories"],
["categories"],
"maker.channel.category") do |maker|
setup_dummy_channel_atom(maker)
end
assert_maker_atom_categories("feed",
["items", "first", "categories"],
["entries", "first", "categories"],
"maker.item.category") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_categories("feed",
["items", "first", "source", "categories"],
["entries", "first", "source", "categories"],
"maker.item.source.category") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_contributor
assert_maker_atom_persons("feed",
["channel", "contributors"],
["contributors"],
"maker.channel.contributor") do |maker|
setup_dummy_channel_atom(maker)
end
assert_maker_atom_persons("feed",
["items", "first", "contributors"],
["entries", "first", "contributors"],
"maker.item.contributor") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_persons("feed",
["items", "first", "source", "contributors"],
["entries", "first", "source", "contributors"],
"maker.item.source.contributor") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_generator
assert_maker_atom_generator("feed",
["channel", "generator"],
["generator"]) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_generator("feed",
["items", "first", "source", "generator"],
["entries", "first", "source", "generator"],
"maker.item.source.generator") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_icon
assert_maker_atom_icon("feed", ["channel"], ["icon"], "icon") do |maker|
setup_dummy_channel_atom(maker)
end
assert_maker_atom_icon("feed",
["items", "first", "source", "icon"],
["entries", "first", "source", "icon"],
nil, "maker.item.source.icon") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_link
assert_maker_atom_links("feed",
["channel", "links"],
["links"],
"maker.channel.link") do |maker|
setup_dummy_channel_atom(maker)
end
assert_maker_atom_links("feed",
["items", "first", "links"],
["entries", "first", "links"],
"maker.item.link") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_links("feed",
["items", "first", "source", "links"],
["entries", "first", "source", "links"],
"maker.item.source.link", true) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_logo
assert_maker_atom_logo("feed", ["channel"], ["logo"], "logo") do |maker|
setup_dummy_channel_atom(maker)
end
assert_maker_atom_logo("feed", ["image"], ["logo"], "url") do |maker|
setup_dummy_channel_atom(maker)
end
assert_maker_atom_logo("feed",
["items", "first", "source", "logo"],
["entries", "first", "source", "logo"],
nil, "maker.item.source.logo") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_rights
assert_maker_atom_text_construct("feed",
["channel", "copyright"],
["rights"]) do |maker|
setup_dummy_channel_atom(maker)
end
assert_maker_atom_text_construct("feed",
["items", "first", "rights"],
["entries", "first", "rights"],
nil, nil, "maker.item.rights"
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_maker_atom_text_construct("feed",
["items", "first", "source", "rights"],
["entries", "first", "source", "rights"],
nil, nil, "maker.item.source.rights"
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_subtitle
assert_maker_atom_text_construct("feed",
["channel", "subtitle"],
["subtitle"],
nil, nil,
"maker.channel.description") do |maker|
setup_dummy_channel_atom(maker)
maker.channel.description = nil
end
assert_maker_atom_text_construct("feed",
["channel", "subtitle"],
["subtitle"],
nil, nil,
"maker.channel.description") do |maker|
setup_dummy_channel_atom(maker)
maker.channel.description {|d| d.content = nil}
end
assert_maker_atom_text_construct("feed",
["items", "first", "source", "subtitle"],
["entries", "first",
"source", "subtitle"],
nil, nil,
"maker.item.source.subtitle") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_title
assert_maker_atom_text_construct("feed",
["channel", "title"], ["title"],
"maker.channel", ["title"]) do |maker|
setup_dummy_channel_atom(maker)
maker.channel.title = nil
end
assert_maker_atom_text_construct("feed",
["items", "first", "title"],
["entries", "first", "title"],
"maker.item", ["title"],
"maker.item.title") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.items.first.title = nil
end
assert_maker_atom_text_construct("feed",
["items", "first", "source", "title"],
["entries", "first", "source", "title"],
nil, nil, "maker.item.source.title"
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_updated
assert_maker_atom_date_construct("feed",
["channel", "updated"], ["updated"],
"maker.channel", ["updated"]) do |maker|
setup_dummy_channel_atom(maker)
maker.channel.updated = nil
end
assert_maker_atom_date_construct("feed",
["items", "first", "updated"],
["entries", "first", "updated"],
"maker.item", ["updated"]) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
maker.items.first.updated = nil
end
assert_maker_atom_date_construct("feed",
["items", "first", "source", "updated"],
["entries", "first", "source", "updated"]
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_published
assert_maker_atom_date_construct("feed",
["items", "first", "published"],
["entries", "first", "published"]
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_summary
assert_maker_atom_text_construct("feed",
["items", "first", "description"],
["entries", "first", "summary"],
nil, nil, "maker.item.description"
) do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_content
assert_maker_atom_content("feed",
["items", "first", "content"],
["entries", "first", "content"],
"maker.item.content") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
def test_id
assert_maker_atom_id("feed",
["items", "first", "source"],
["entries", "first", "source"],
"maker.item.source") do |maker|
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
end
end
end

View file

@ -57,9 +57,14 @@ module RSS
end end
def test_rss10_multiple def test_rss10_multiple
assert_multiple_dublin_core_rss10("_list")
assert_multiple_dublin_core_rss10("es")
end
def assert_multiple_dublin_core_rss10(multiple_rights_suffix)
elems = [] elems = []
@elements.each do |name, value| @elements.each do |name, value|
plural = name.to_s + (name == :rights ? "es" : "s") plural = name.to_s + (name == :rights ? multiple_rights_suffix : "s")
values = [value] values = [value]
if name == :date if name == :date
values << value + 60 values << value + 60

View file

@ -0,0 +1,471 @@
require "rss-testcase"
require "rss/maker"
module RSS
class TestMakerITunes < TestCase
def test_author
assert_maker_itunes_author(%w(channel))
assert_maker_itunes_author(%w(items last))
end
def test_block
assert_maker_itunes_block(%w(channel))
assert_maker_itunes_block(%w(items last))
end
def test_category
assert_maker_itunes_category(%w(channel))
end
def test_image
assert_maker_itunes_image(%w(channel))
end
def test_duration
assert_maker_itunes_duration(%w(items last))
end
def test_explicit
assert_maker_itunes_explicit(%w(channel))
assert_maker_itunes_explicit(%w(items last))
end
def test_keywords
assert_maker_itunes_keywords(%w(channel))
assert_maker_itunes_keywords(%w(items last))
end
def test_new_feed_url
assert_maker_itunes_new_feed_url(%w(channel))
end
def test_owner
assert_maker_itunes_owner(%w(channel))
end
def test_subtitle
assert_maker_itunes_subtitle(%w(channel))
assert_maker_itunes_subtitle(%w(items last))
end
def test_summary
assert_maker_itunes_summary(%w(channel))
assert_maker_itunes_summary(%w(items last))
end
private
def assert_maker_itunes_author(maker_readers, feed_readers=nil)
_wrap_assertion do
feed_readers ||= maker_readers
author = "John Doe"
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
target.itunes_author = author
end
target = chain_reader(rss20, feed_readers)
assert_equal(author, target.itunes_author)
end
end
def _assert_maker_itunes_block(value, boolean_value, maker_readers,
feed_readers)
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
target.itunes_block = value
assert_equal(value, target.itunes_block)
assert_equal(boolean_value, target.itunes_block?)
end
target = chain_reader(rss20, feed_readers)
if [true, false].include?(value)
feed_expected_value = value = value ? "yes" : "no"
else
feed_expected_value = value
end
assert_equal(value, target.itunes_block)
assert_equal(boolean_value, target.itunes_block?)
end
def assert_maker_itunes_block(maker_readers, feed_readers=nil)
_wrap_assertion do
feed_readers ||= maker_readers
_assert_maker_itunes_block("yes", true, maker_readers, feed_readers)
_assert_maker_itunes_block("Yes", true, maker_readers, feed_readers)
_assert_maker_itunes_block("no", false, maker_readers, feed_readers)
_assert_maker_itunes_block("", false, maker_readers, feed_readers)
_assert_maker_itunes_block(true, true, maker_readers, feed_readers)
_assert_maker_itunes_block(false, false, maker_readers, feed_readers)
_assert_maker_itunes_block(nil, false, maker_readers, feed_readers)
end
end
def _assert_maker_itunes_category(categories, maker_readers, feed_readers)
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
categories.each do |category|
sub_target = target.itunes_categories
if category.is_a?(Array)
category.each do |sub_category|
sub_target = sub_target.new_category
sub_target.text = sub_category
end
else
sub_target.new_category.text = category
end
end
end
target = chain_reader(rss20, feed_readers)
actual_categories = target.itunes_categories.collect do |category|
cat = category.text
if category.itunes_categories.empty?
cat
else
[cat, *category.itunes_categories.collect {|c| c.text}]
end
end
assert_equal(categories, actual_categories)
end
def assert_maker_itunes_category(maker_readers, feed_readers=nil)
_wrap_assertion do
feed_readers ||= maker_readers
_assert_maker_itunes_category(["Audio Blogs"],
maker_readers, feed_readers)
_assert_maker_itunes_category([["Arts & Entertainment", "Games"]],
maker_readers, feed_readers)
_assert_maker_itunes_category([["Arts & Entertainment", "Games"],
["Technology", "Computers"],
"Audio Blogs"],
maker_readers, feed_readers)
end
end
def assert_maker_itunes_image(maker_readers, feed_readers=nil)
_wrap_assertion do
feed_readers ||= maker_readers
url = "http://example.com/podcasts/everything/AllAboutEverything.jpg"
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
target.itunes_image = url
end
target = chain_reader(rss20, feed_readers)
assert_not_nil(target.itunes_image)
assert_equal(url, target.itunes_image.href)
end
end
def _assert_maker_itunes_duration(hour, minute, second, value,
maker_readers, feed_readers)
_assert_maker_itunes_duration_by_value(hour, minute, second, value,
maker_readers, feed_readers)
_assert_maker_itunes_duration_by_hour_minute_second(hour, minute, second,
value,
maker_readers,
feed_readers)
end
def _assert_maker_itunes_duration_by(hour, minute, second, value,
maker_readers, feed_readers)
expected_value = nil
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
expected_value = yield(target)
assert_equal(expected_value, target.itunes_duration)
target.itunes_duration do |duration|
assert_equal([hour, minute, second, expected_value],
[duration.hour, duration.minute,
duration.second, duration.content])
end
end
target = chain_reader(rss20, feed_readers)
duration = target.itunes_duration
assert_not_nil(duration)
assert_equal([hour, minute, second, expected_value],
[duration.hour, duration.minute,
duration.second, duration.content])
end
def _assert_maker_itunes_duration_by_value(hour, minute, second, value,
maker_readers, feed_readers)
_assert_maker_itunes_duration_by(hour, minute, second, value,
maker_readers, feed_readers) do |target|
target.itunes_duration = value
value
end
end
def _assert_maker_itunes_duration_by_hour_minute_second(hour, minute, second,
value,
maker_readers,
feed_readers)
_assert_maker_itunes_duration_by(hour, minute, second, value,
maker_readers, feed_readers) do |target|
target.itunes_duration do |duration|
duration.hour = hour
duration.minute = minute
duration.second = second
end
value.split(":").collect {|v| "%02d" % v.to_i}.join(":")
end
end
def _assert_maker_itunes_duration_invalid_value(value, maker_readers)
assert_raise(ArgumentError) do
::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
target.itunes_duration = value
end
end
end
def assert_maker_itunes_duration(maker_readers, feed_readers=nil)
_wrap_assertion do
feed_readers ||= maker_readers
_assert_maker_itunes_duration(7, 14, 5, "07:14:05", maker_readers,
feed_readers)
_assert_maker_itunes_duration(7, 14, 5, "7:14:05", maker_readers,
feed_readers)
_assert_maker_itunes_duration(0, 4, 55, "04:55", maker_readers,
feed_readers)
_assert_maker_itunes_duration(0, 4, 5, "4:05", maker_readers,
feed_readers)
_assert_maker_itunes_duration_invalid_value("5", maker_readers)
_assert_maker_itunes_duration_invalid_value("09:07:14:05", maker_readers)
_assert_maker_itunes_duration_invalid_value("10:5", maker_readers)
_assert_maker_itunes_duration_invalid_value("10:03:5", maker_readers)
_assert_maker_itunes_duration_invalid_value("10:3:05", maker_readers)
_assert_maker_itunes_duration_invalid_value("xx:xx:xx", maker_readers)
end
end
def _assert_maker_itunes_explicit(explicit, value,
maker_readers, feed_readers)
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
target.itunes_explicit = value
assert_equal(explicit, target.itunes_explicit?)
end
target = chain_reader(rss20, feed_readers)
assert_equal(value, target.itunes_explicit)
assert_equal(explicit, target.itunes_explicit?)
end
def assert_maker_itunes_explicit(maker_readers, feed_readers=nil)
_wrap_assertion do
feed_readers ||= maker_readers
_assert_maker_itunes_explicit(true, "yes", maker_readers, feed_readers)
_assert_maker_itunes_explicit(false, "clean",
maker_readers, feed_readers)
_assert_maker_itunes_explicit(nil, "no", maker_readers, feed_readers)
end
end
def _assert_maker_itunes_keywords(keywords, value,
maker_readers, feed_readers)
_assert_maker_itunes_keywords_by_value(keywords, value,
maker_readers, feed_readers)
_assert_maker_itunes_keywords_by_keywords(keywords, maker_readers,
feed_readers)
end
def _assert_maker_itunes_keywords_by(keywords, maker_readers, feed_readers)
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
yield(target)
end
assert_nothing_raised do
rss20 = ::RSS::Parser.parse(rss20.to_s)
end
target = chain_reader(rss20, feed_readers)
assert_equal(keywords, target.itunes_keywords)
end
def _assert_maker_itunes_keywords_by_value(keywords, value,
maker_readers, feed_readers)
_assert_maker_itunes_keywords_by(keywords, maker_readers,
feed_readers) do |target|
target.itunes_keywords = value
end
end
def _assert_maker_itunes_keywords_by_keywords(keywords,
maker_readers, feed_readers)
_assert_maker_itunes_keywords_by(keywords, maker_readers,
feed_readers) do |target|
target.itunes_keywords = keywords
end
end
def assert_maker_itunes_keywords(maker_readers, feed_readers=nil)
_wrap_assertion do
feed_readers ||= maker_readers
_assert_maker_itunes_keywords(["salt"], "salt",
maker_readers, feed_readers)
_assert_maker_itunes_keywords(["salt"], " salt ",
maker_readers, feed_readers)
_assert_maker_itunes_keywords(["salt", "pepper", "shaker", "exciting"],
"salt, pepper, shaker, exciting",
maker_readers, feed_readers)
_assert_maker_itunes_keywords(["metric", "socket", "wrenches",
"toolsalt"],
"metric, socket, wrenches, toolsalt",
maker_readers, feed_readers)
_assert_maker_itunes_keywords(["olitics", "red", "blue", "state"],
"olitics, red, blue, state",
maker_readers, feed_readers)
end
end
def assert_maker_itunes_new_feed_url(maker_readers, feed_readers=nil)
feed_readers ||= maker_readers
url = "http://newlocation.com/example.rss"
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
target.itunes_new_feed_url = url
end
target = chain_reader(rss20, feed_readers)
assert_equal(url, target.itunes_new_feed_url)
end
def _assert_maker_itunes_owner(name, email, maker_readers, feed_readers)
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
owner = target.itunes_owner
owner.itunes_name = name
owner.itunes_email = email
end
owner = chain_reader(rss20, feed_readers).itunes_owner
if name.nil? and email.nil?
assert_nil(owner)
else
assert_not_nil(owner)
assert_equal(name, owner.itunes_name)
assert_equal(email, owner.itunes_email)
end
end
def assert_maker_itunes_owner(maker_readers, feed_readers=nil)
_wrap_assertion do
feed_readers ||= maker_readers
_assert_maker_itunes_owner("John Doe", "john.doe@example.com",
maker_readers, feed_readers)
not_set_name = (["maker"] + maker_readers + ["itunes_owner"]).join(".")
assert_not_set_error(not_set_name, ["itunes_name"]) do
_assert_maker_itunes_owner(nil, "john.doe@example.com",
maker_readers, feed_readers)
end
assert_not_set_error(not_set_name, ["itunes_email"]) do
_assert_maker_itunes_owner("John Doe", nil,
maker_readers, feed_readers)
end
_assert_maker_itunes_owner(nil, nil, maker_readers, feed_readers)
end
end
def _assert_maker_itunes_subtitle(subtitle, maker_readers, feed_readers)
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
target.itunes_subtitle = subtitle
end
target = chain_reader(rss20, feed_readers)
assert_equal(subtitle, target.itunes_subtitle)
end
def assert_maker_itunes_subtitle(maker_readers, feed_readers=nil)
_wrap_assertion do
feed_readers ||= maker_readers
_assert_maker_itunes_subtitle("A show about everything",
maker_readers, feed_readers)
_assert_maker_itunes_subtitle("A short primer on table spices",
maker_readers, feed_readers)
_assert_maker_itunes_subtitle("Comparing socket wrenches is fun!",
maker_readers, feed_readers)
_assert_maker_itunes_subtitle("Red + Blue != Purple",
maker_readers, feed_readers)
end
end
def _assert_maker_itunes_summary(summary, maker_readers, feed_readers)
rss20 = ::RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
target = chain_reader(maker, maker_readers)
target.itunes_summary = summary
end
target = chain_reader(rss20, feed_readers)
assert_equal(summary, target.itunes_summary)
end
def assert_maker_itunes_summary(maker_readers, feed_readers=nil)
_wrap_assertion do
feed_readers ||= maker_readers
_assert_maker_itunes_summary("All About Everything is a show about " +
"everything. Each week we dive into any " +
"subject known to man and talk about it " +
"as much as we can. Look for our Podcast " +
"in the iTunes Music Store",
maker_readers, feed_readers)
_assert_maker_itunes_summary("This week we talk about salt and pepper " +
"shakers, comparing and contrasting pour " +
"rates, construction materials, and " +
"overall aesthetics. Come and join the " +
"party!",
maker_readers, feed_readers)
_assert_maker_itunes_summary("This week we talk about metric vs. old " +
"english socket wrenches. Which one is " +
"better? Do you really need both? Get " +
"all of your answers here.",
maker_readers, feed_readers)
_assert_maker_itunes_summary("This week we talk about surviving in a " +
"Red state if youre a Blue person. Or " +
"vice versa.",
maker_readers, feed_readers)
end
end
end
end

View file

@ -0,0 +1,37 @@
require "rss-testcase"
require "rss/maker"
module RSS
class TestMakerSlash < TestCase
def setup
@elements = {
"section" => "articles",
"department" => "not-an-ocean-unless-there-are-lobsters",
"comments" => 177,
"hit_parades" => [177, 155, 105, 33, 6, 3, 0],
}
end
def test_rss10
rss = RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
item = maker.items.last
@elements.each do |name, value|
item.send("slash_#{name}=", value)
end
end
item = rss.items.last
assert_not_nil(item)
assert_slash_elements(item)
end
private
def assert_slash_elements(target)
super(@elements, target)
end
end
end

View file

@ -24,6 +24,7 @@ module RSS
rss = RSS::Maker.make("1.0") do |maker| rss = RSS::Maker.make("1.0") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
set_elements(maker.channel) set_elements(maker.channel)
setup_dummy_item(maker)
end end
assert_syndication(@elements, rss.channel) assert_syndication(@elements, rss.channel)
end end

View file

@ -24,6 +24,7 @@ module RSS
end end
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_item(maker)
end end
xss = rss.xml_stylesheets.first xss = rss.xml_stylesheets.first
@ -38,11 +39,12 @@ module RSS
href = 'http://example.com/index.xsl' href = 'http://example.com/index.xsl'
type = 'text/xsl' type = 'text/xsl'
rss = RSS::Maker.make("1.0") do |maker| rss = RSS::Maker.make("1.0") do |maker|
maker.xml_stylesheets.new_xml_stylesheet do |xss| maker.xml_stylesheets.new_xml_stylesheet do |_xss|
xss.href = href _xss.href = href
end end
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_item(maker)
end end
xss = rss.xml_stylesheets.first xss = rss.xml_stylesheets.first
@ -61,6 +63,7 @@ module RSS
end end
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_item(maker)
end end
assert(rss.xml_stylesheets.empty?) assert(rss.xml_stylesheets.empty?)
@ -71,6 +74,7 @@ module RSS
end end
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_item(maker)
end end
assert(rss.xml_stylesheets.empty?) assert(rss.xml_stylesheets.empty?)
end end

View file

@ -1,14 +1,4 @@
begin require "fileutils"
require "fileutils"
rescue LoadError
module FileUtils
module_function
def rm_f(target)
File.unlink(target)
rescue Errno::ENOENT
end
end
end
require "rss-testcase" require "rss-testcase"

View file

@ -498,6 +498,14 @@ EOR
Parser.parse(rss, true, false) Parser.parse(rss, true, false)
end end
end end
def test_unknown_duplicated_element
xmlns = {"test" => "http://localhost/test"}
assert_parse(make_RDF(<<-EOR, xmlns), :nothing_raised)
#{make_channel("<test:string/>")}
#{make_item}
#{make_image}
EOR
end
end end
end end

View file

@ -0,0 +1,163 @@
require "rss-testcase"
require "rss/atom"
module RSS
class TestParserAtom < TestCase
def test_entry_validation
assert_ns("", Atom::URI) do
Parser.parse(<<-EOA)
<entry/>
EOA
end
assert_ns("", Atom::URI) do
Parser.parse(<<-EOA)
<entry xmlns="hoge"/>
EOA
end
assert_parse(<<-EOA, :missing_tag, "id", "entry") do
<entry xmlns="#{Atom::URI}"/>
EOA
end
assert_parse(<<-EOA, :missing_tag, "title", "entry") do
<entry xmlns="#{Atom::URI}">
<id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
</entry>
EOA
end
assert_parse(<<-EOA, :missing_tag, "updated", "entry") do
<entry xmlns="#{Atom::URI}">
<id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
<title>Example Entry</title>
</entry>
EOA
end
assert_parse(<<-EOA, :missing_tag, "author", "entry") do
<entry xmlns="#{Atom::URI}">
<id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
<title>Example Entry</title>
<updated>2003-10-10T18:30:02Z</updated>
</entry>
EOA
end
assert_parse(<<-EOA, :nothing_raised) do
<entry xmlns="#{Atom::URI}">
<id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
<title>Example Entry</title>
<updated>2003-10-10T18:30:02Z</updated>
<author>
<name>A person</name>
</author>
</entry>
EOA
end
end
def test_entry
entry = RSS::Parser.parse(<<-EOA)
<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom">
<author>
<name>A person</name>
</author>
<title>Atom-Powered Robots Run Amok</title>
<link href="http://example.org/2003/12/13/atom03"/>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2003-12-13T18:30:02Z</updated>
<summary>Some text.</summary>
</entry>
EOA
assert_not_nil(entry)
assert_equal("Atom-Powered Robots Run Amok", entry.title.content)
assert_equal("http://example.org/2003/12/13/atom03", entry.link.href)
assert_equal("urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a",
entry.id.content)
assert_equal(Time.parse("2003-12-13T18:30:02Z"), entry.updated.content)
assert_equal("Some text.", entry.summary.content)
end
def test_entry_author
assert_atom_person("author", method(:make_entry_document)) do |entry|
assert_equal(2, entry.authors.size)
entry.authors.last
end
end
def test_entry_category
assert_atom_category(method(:make_entry_document)) do |entry|
assert_equal(1, entry.categories.size)
entry.category
end
end
def test_entry_content_text
assert_atom_content(method(:make_entry_document)) do |entry|
entry.content
end
end
def test_entry_contributor
assert_atom_person("contributor", method(:make_entry_document)) do |entry|
assert_equal(1, entry.contributors.size)
entry.contributor
end
end
def test_entry_id
entry = RSS::Parser.parse(make_entry_document)
assert_equal(ENTRY_ID, entry.id.content)
end
def test_entry_link
assert_atom_link(method(:make_entry_document)) do |entry|
assert_equal(1, entry.links.size)
entry.link
end
end
def test_published
generator = method(:make_entry_document)
assert_atom_date_construct("published", generator) do |entry|
entry.published
end
end
def test_entry_rights
generator = method(:make_entry_document)
assert_atom_text_construct("rights", generator) do |entry|
entry.rights
end
end
def test_entry_source
generator = method(:make_entry_document_with_open_source)
assert_atom_source(generator) do |entry|
assert_not_nil(entry.source)
entry.source
end
end
def test_entry_summary
generator = method(:make_entry_document)
assert_atom_text_construct("summary", generator) do |entry|
entry.summary
end
end
def test_entry_title
entry = RSS::Parser.parse(make_entry_document)
assert_equal(ENTRY_TITLE, entry.title.content)
end
def test_entry_updated
entry = RSS::Parser.parse(make_entry_document)
assert_equal(Time.parse(ENTRY_UPDATED), entry.updated.content)
end
end
end

View file

@ -0,0 +1,276 @@
require "rss-testcase"
require "rss/atom"
module RSS
class TestParserAtomFeed < TestCase
def test_feed_validation
assert_ns("", Atom::URI) do
Parser.parse(<<-EOA)
<feed/>
EOA
end
assert_ns("", Atom::URI) do
Parser.parse(<<-EOA)
<feed xmlns="hoge"/>
EOA
end
assert_parse(<<-EOA, :missing_tag, "id", "feed") do
<feed xmlns="#{Atom::URI}"/>
EOA
end
assert_parse(<<-EOA, :missing_tag, "title", "feed") do
<feed xmlns="#{Atom::URI}">
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
</feed>
EOA
end
assert_parse(<<-EOA, :missing_tag, "updated", "feed") do
<feed xmlns="#{Atom::URI}">
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<title>Example Feed</title>
</feed>
EOA
end
assert_parse(<<-EOA, :missing_tag, "author", "feed") do
<feed xmlns="#{Atom::URI}">
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<title>Example Feed</title>
<updated>2003-12-13T18:30:02Z</updated>
</feed>
EOA
end
assert_parse(<<-EOA, :nothing_raised) do
<feed xmlns="#{Atom::URI}">
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<title>Example Feed</title>
<updated>2003-12-13T18:30:02Z</updated>
<author>
<name>A person</name>
</author>
</feed>
EOA
end
end
def test_lang
feed = RSS::Parser.parse(<<-EOA)
<feed xmlns="#{Atom::URI}" xml:lang="ja">
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<title xml:lang="en">Example Feed</title>
<updated>2003-12-13T18:30:02Z</updated>
<author xml:lang="en">
<name>A person</name>
</author>
</feed>
EOA
assert_equal("ja", feed.lang)
assert_equal("ja", feed.id.lang)
assert_equal("en", feed.title.lang)
assert_equal("ja", feed.updated.lang)
assert_equal("en", feed.author.lang)
assert_equal("en", feed.author.name.lang)
end
def test_base
feed = RSS::Parser.parse(<<-EOA)
<feed xmlns="#{Atom::URI}" xml:base="http://example.com/">
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<title xml:lang="en">Example Feed</title>
<updated>2003-12-13T18:30:02Z</updated>
<generator uri="generator">Generator</generator>
<link hreflang="ja" href="http://example.org/link1"/>
<link hreflang="en" href="link2"/>
<link hreflang="fr" xml:base="http://example.net/" href="link3"/>
<author>
<name>A person</name>
<uri>person</uri>
</author>
</feed>
EOA
assert_equal("http://example.com/", feed.base)
assert_equal("http://example.com/", feed.id.base)
assert_equal("http://example.com/", feed.title.base)
assert_equal("http://example.com/", feed.updated.base)
assert_equal("http://example.com/", feed.generator.base)
assert_equal("http://example.com/generator", feed.generator.uri)
assert_equal("http://example.com/", feed.links[0].base)
assert_equal("http://example.org/link1", feed.links[0].href)
assert_equal("http://example.com/", feed.links[1].base)
assert_equal("http://example.com/link2", feed.links[1].href)
assert_equal("http://example.net/", feed.links[2].base)
assert_equal("http://example.net/link3", feed.links[2].href)
assert_equal("http://example.com/person", feed.author.uri.content)
end
def test_feed_author
assert_atom_person("author", method(:make_feed)) do |feed|
assert_equal(2, feed.authors.size)
feed.authors[1]
end
end
def test_entry_author
generator = method(:make_feed_with_open_entry)
assert_atom_person("author", generator) do |feed|
assert_equal(1, feed.entries.size)
assert_equal(1, feed.entry.authors.size)
feed.entry.author
end
end
def test_feed_category
assert_atom_category(method(:make_feed)) do |feed|
assert_equal(1, feed.categories.size)
feed.category
end
end
def test_entry_category
assert_atom_category(method(:make_feed_with_open_entry)) do |feed|
assert_equal(1, feed.entries.size)
assert_equal(1, feed.entry.categories.size)
feed.entry.category
end
end
def test_entry_content
assert_atom_content(method(:make_feed_with_open_entry)) do |feed|
assert_equal(1, feed.entries.size)
feed.entry.content
end
end
def test_feed_contributor
assert_atom_person("contributor", method(:make_feed)) do |feed|
assert_equal(1, feed.contributors.size)
feed.contributor
end
end
def test_entry_contributor
generator = method(:make_feed_with_open_entry)
assert_atom_person("contributor", generator) do |feed|
assert_equal(1, feed.entries.size)
assert_equal(1, feed.entry.contributors.size)
feed.entry.contributor
end
end
def test_feed_generator
assert_atom_generator(method(:make_feed)) do |feed|
feed.generator
end
end
def test_feed_icon
assert_atom_icon(method(:make_feed)) do |feed|
feed.icon
end
end
def test_feed_id
feed = RSS::Parser.parse(make_feed(''))
assert_equal(FEED_ID, feed.id.content)
end
def test_entry_id
feed = RSS::Parser.parse(make_feed(''))
assert_equal(ENTRY_ID, feed.entry.id.content)
end
def test_feed_link
assert_atom_link(method(:make_feed)) do |feed|
assert_equal(1, feed.links.size)
feed.link
end
end
def test_entry_link
assert_atom_link(method(:make_feed_with_open_entry)) do |feed|
assert_equal(1, feed.entries.size)
assert_equal(1, feed.entry.links.size)
feed.entry.link
end
end
def test_feed_logo
assert_atom_logo(method(:make_feed)) do |feed|
feed.logo
end
end
def test_feed_rights
assert_atom_text_construct("rights", method(:make_feed)) do |feed|
feed.rights
end
end
def test_entry_rights
generator = method(:make_feed_with_open_entry)
assert_atom_text_construct("rights", generator) do |feed|
assert_equal(1, feed.entries.size)
feed.entry.rights
end
end
def test_entry_source
assert_atom_source(method(:make_feed_with_open_entry_source)) do |feed|
assert_equal(1, feed.entries.size)
assert_not_nil(feed.entry.source)
feed.entry.source
end
end
def test_feed_subtitle
assert_atom_text_construct("subtitle", method(:make_feed)) do |feed|
feed.subtitle
end
end
def test_feed_title
feed = RSS::Parser.parse(make_feed(''))
assert_equal(FEED_TITLE, feed.title.content)
end
def test_entry_title
feed = RSS::Parser.parse(make_feed(''))
assert_equal(ENTRY_TITLE, feed.entry.title.content)
end
def test_feed_updated
feed = RSS::Parser.parse(make_feed(''))
assert_equal(Time.parse(FEED_UPDATED), feed.updated.content)
end
def test_entry_updated
feed = RSS::Parser.parse(make_feed(''))
assert_equal(Time.parse(ENTRY_UPDATED), feed.entry.updated.content)
end
def test_entry_published
generator = method(:make_feed_with_open_entry)
assert_atom_date_construct("published", generator) do |feed|
assert_equal(1, feed.entries.size)
feed.entry.published
end
end
def test_entry_summary
generator = method(:make_feed_with_open_entry)
assert_atom_text_construct("summary", generator) do |feed|
assert_equal(1, feed.entries.size)
feed.entry.summary
end
end
end
end

View file

@ -49,10 +49,19 @@ module RSS
new_hour.content = hour new_hour.content = hour
end end
end end
setup_dummy_image(maker)
end
assert_not_set_error("maker.image", %w(title url)) do
RSS::Maker.make("0.91") do |maker|
rss.channel.setup_maker(maker)
end
end end
new_rss = RSS::Maker.make("0.91") do |maker| new_rss = RSS::Maker.make("0.91") do |maker|
rss.channel.setup_maker(maker) rss.channel.setup_maker(maker)
setup_dummy_image(maker)
end end
channel = new_rss.channel channel = new_rss.channel
@ -76,7 +85,6 @@ module RSS
end end
assert(channel.items.empty?) assert(channel.items.empty?)
assert_nil(channel.image)
assert_nil(channel.textInput) assert_nil(channel.textInput)
end end
@ -121,6 +129,7 @@ module RSS
rss = RSS::Maker.make("0.91") do |maker| rss = RSS::Maker.make("0.91") do |maker|
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
maker.textinput.title = title maker.textinput.title = title
maker.textinput.description = description maker.textinput.description = description
@ -130,6 +139,7 @@ module RSS
new_rss = RSS::Maker.make("0.91") do |maker| new_rss = RSS::Maker.make("0.91") do |maker|
rss.channel.setup_maker(maker) rss.channel.setup_maker(maker)
rss.image.setup_maker(maker)
rss.textinput.setup_maker(maker) rss.textinput.setup_maker(maker)
end end
@ -157,6 +167,8 @@ module RSS
item.description = "#{description}#{i}" item.description = "#{description}#{i}"
end end
end end
setup_dummy_image(maker)
end end
new_rss = RSS::Maker.make("0.91") do |maker| new_rss = RSS::Maker.make("0.91") do |maker|
@ -169,6 +181,8 @@ module RSS
item.setup_maker(maker.items) item.setup_maker(maker.items)
end end
end end
rss.image.setup_maker(maker)
end end
assert_equal(item_size, new_rss.items.size) assert_equal(item_size, new_rss.items.size)
@ -177,7 +191,6 @@ module RSS
assert_equal("#{link}#{i}", item.link) assert_equal("#{link}#{i}", item.link)
assert_equal("#{description}#{i}", item.description) assert_equal("#{description}#{i}", item.description)
end end
end end
def test_setup_maker_items_backward_compatibility def test_setup_maker_items_backward_compatibility
@ -209,6 +222,7 @@ module RSS
end end
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_image(maker)
end end
new_rss = RSS::Maker.make("0.91") do |maker| new_rss = RSS::Maker.make("0.91") do |maker|
@ -228,6 +242,5 @@ module RSS
assert_equal(charset, xss.charset) assert_equal(charset, xss.charset)
assert_equal(alternate, xss.alternate) assert_equal(alternate, xss.alternate)
end end
end end
end end

View file

@ -87,10 +87,15 @@ module RSS
@sy_elems.each do |var, value| @sy_elems.each do |var, value|
maker.channel.__send__("sy_#{var}=", value) maker.channel.__send__("sy_#{var}=", value)
end end
setup_dummy_item(maker)
end end
new_rss = RSS::Maker.make("1.0") do |maker| new_rss = RSS::Maker.make("1.0") do |maker|
rss.channel.setup_maker(maker) rss.channel.setup_maker(maker)
rss.items.each do |item|
item.setup_maker(maker)
end
end end
channel = new_rss.channel channel = new_rss.channel
@ -98,7 +103,7 @@ module RSS
assert_equal(title, channel.title) assert_equal(title, channel.title)
assert_equal(link, channel.link) assert_equal(link, channel.link)
assert_equal(description, channel.description) assert_equal(description, channel.description)
assert_equal(true, channel.items.Seq.lis.empty?) assert_equal(1, channel.items.Seq.lis.size)
assert_nil(channel.image) assert_nil(channel.image)
assert_nil(channel.textinput) assert_nil(channel.textinput)
@ -128,11 +133,16 @@ module RSS
@dc_elems.each do |var, value| @dc_elems.each do |var, value|
maker.image.__send__("dc_#{var}=", value) maker.image.__send__("dc_#{var}=", value)
end end
setup_dummy_item(maker)
end end
new_rss = RSS::Maker.make("1.0") do |maker| new_rss = RSS::Maker.make("1.0") do |maker|
rss.channel.setup_maker(maker) rss.channel.setup_maker(maker)
rss.image.setup_maker(maker) rss.image.setup_maker(maker)
rss.items.each do |item|
item.setup_maker(maker)
end
end end
image = new_rss.image image = new_rss.image
@ -164,11 +174,16 @@ module RSS
@dc_elems.each do |var, value| @dc_elems.each do |var, value|
maker.textinput.__send__("dc_#{var}=", value) maker.textinput.__send__("dc_#{var}=", value)
end end
setup_dummy_item(maker)
end end
new_rss = RSS::Maker.make("1.0") do |maker| new_rss = RSS::Maker.make("1.0") do |maker|
rss.channel.setup_maker(maker) rss.channel.setup_maker(maker)
rss.textinput.setup_maker(maker) rss.textinput.setup_maker(maker)
rss.items.each do |item|
item.setup_maker(maker)
end
end end
textinput = new_rss.textinput textinput = new_rss.textinput
@ -247,8 +262,8 @@ module RSS
assert_equal(@trackback_elems[:ping], item.trackback_ping) assert_equal(@trackback_elems[:ping], item.trackback_ping)
assert_equal(@trackback_elems[:about].size, item.trackback_abouts.size) assert_equal(@trackback_elems[:about].size, item.trackback_abouts.size)
item.trackback_abouts.each_with_index do |about, i| item.trackback_abouts.each_with_index do |about, j|
assert_equal(@trackback_elems[:about][i], about.value) assert_equal(@trackback_elems[:about][j], about.value)
end end
end end
end end
@ -333,6 +348,7 @@ module RSS
end end
setup_dummy_channel(maker) setup_dummy_channel(maker)
setup_dummy_item(maker)
end end
new_rss = RSS::Maker.make("1.0") do |maker| new_rss = RSS::Maker.make("1.0") do |maker|
@ -522,8 +538,8 @@ module RSS
assert_equal(@trackback_elems[:ping], item.trackback_ping) assert_equal(@trackback_elems[:ping], item.trackback_ping)
assert_equal(@trackback_elems[:about].size, item.trackback_abouts.size) assert_equal(@trackback_elems[:about].size, item.trackback_abouts.size)
item.trackback_abouts.each_with_index do |about, i| item.trackback_abouts.each_with_index do |about, j|
assert_equal(@trackback_elems[:about][i], about.value) assert_equal(@trackback_elems[:about][j], about.value)
end end
end end

View file

@ -0,0 +1,409 @@
require "rss-testcase"
require "rss/maker"
module RSS
class TestSetupMakerAtomEntry < TestCase
def setup
t = Time.iso8601("2000-01-01T12:00:05+00:00")
class << t
alias_method(:to_s, :iso8601)
end
@dc_elems = {
:title => "hoge",
:description =>
" XML is placing increasingly heavy loads on
the existing technical infrastructure of the Internet.",
:creator => "Rael Dornfest (mailto:rael@oreilly.com)",
:subject => "XML",
:publisher => "The O'Reilly Network",
:contributor => "hogehoge",
:type => "fugafuga",
:format => "hohoho",
:identifier => "fufufu",
:source => "barbar",
:language => "ja",
:relation => "cococo",
:rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
:date => t,
}
end
def test_setup_maker_entry(with_dc=true)
authors = [
{
:name => "Bob",
:uri => "http://example.com/~bob/",
:email => "bob@example.com",
},
{
:name => "Alice",
:uri => "http://example.com/~alice/",
:email => "alice@example.com",
},
]
categories = [
{
:term => "music",
:label => "Music",
},
{
:term => "book",
:scheme => "http://example.com/category/book/",
:label => "Book",
},
]
contributors = [
{
:name => "Chris",
:email => "chris@example.com",
},
{
:name => "Eva",
:uri => "http://example.com/~eva/",
},
]
id = "urn:uuid:8b105336-7e20-45fc-bb78-37fb3e1db25a"
link = "http://hoge.com"
published = Time.now - 60 * 3600
rights = "Copyrights (c) 2007 Alice and Bob"
description = "fugafugafugafuga"
title = "fugafuga"
updated = Time.now
feed = RSS::Maker.make("atom:entry") do |maker|
maker.items.new_item do |item|
authors.each do |author_info|
item.authors.new_author do |author|
author_info.each do |key, value|
author.__send__("#{key}=", value)
end
end
end
categories.each do |category_info|
item.categories.new_category do |category|
category_info.each do |key, value|
category.__send__("#{key}=", value)
end
end
end
contributors.each do |contributor_info|
item.contributors.new_contributor do |contributor|
contributor_info.each do |key, value|
contributor.__send__("#{key}=", value)
end
end
end
item.id = id
item.link = link
item.published = published
item.rights = rights
item.description = description
item.title = title
item.updated = updated
if with_dc
@dc_elems.each do |var, value|
if var == :date
item.new_dc_date(value)
else
item.__send__("dc_#{var}=", value)
end
end
end
end
end
assert_not_nil(feed)
new_feed = RSS::Maker.make("atom:entry") do |maker|
feed.setup_maker(maker)
end
assert_not_nil(new_feed)
new_authors = new_feed.authors.collect do |author|
{
:name => author.name.content,
:uri => author.uri.content,
:email => author.email.content,
}
end
assert_equal(authors, new_authors)
new_categories = new_feed.categories.collect do |category|
{
:term => category.term,
:scheme => category.scheme,
:label => category.label,
}.reject {|key, value| value.nil?}
end
assert_equal(categories, new_categories)
new_contributors = new_feed.contributors.collect do |contributor|
info = {}
info[:name] = contributor.name.content
info[:uri] = contributor.uri.content if contributor.uri
info[:email] = contributor.email.content if contributor.email
info
end
assert_equal(contributors, new_contributors)
assert_equal(id, new_feed.id.content)
assert_equal(link, new_feed.link.href)
assert_equal(published, new_feed.published.content)
assert_equal(rights, new_feed.rights.content)
assert_equal(description, new_feed.summary.content)
assert_equal(title, new_feed.title.content)
assert_equal(updated, new_feed.updated.content)
if with_dc
@dc_elems.each do |var, value|
if var == :date
assert_equal([updated, value],
new_feed.dc_dates.collect {|date| date.value})
else
assert_equal(value, new_feed.__send__("dc_#{var}"))
end
end
end
assert_equal(1, new_feed.items.size)
end
def test_setup_maker_entry_without_dc
test_setup_maker_entry(false)
end
def test_setup_maker_items(for_backward_compatibility=false)
title = "TITLE"
link = "http://hoge.com/"
description = "text hoge fuga"
updated = Time.now
item_size = 5
feed = RSS::Maker.make("atom:entry") do |maker|
setup_dummy_channel_atom(maker)
item_size.times do |i|
maker.items.new_item do |item|
item.title = "#{title}#{i}"
item.link = "#{link}#{i}"
item.description = "#{description}#{i}"
item.updated = updated + i * 60
end
end
end
new_feed = RSS::Maker.make("atom:entry") do |maker|
feed.items.each do |item|
if for_backward_compatibility
item.setup_maker(maker)
else
item.setup_maker(maker.items)
end
end
feed.items.clear
feed.setup_maker(maker)
end
assert_equal(1, new_feed.items.size)
new_feed.items[0..1].each_with_index do |item, i|
assert_equal("#{title}#{i}", item.title.content)
assert_equal("#{link}#{i}", item.link.href)
assert_equal("#{description}#{i}", item.summary.content)
assert_equal(updated + i * 60, item.updated.content)
end
end
def test_setup_maker_items_sort
title = "TITLE"
link = "http://hoge.com/"
summary = "text hoge fuga"
updated = Time.now
feed_size = 5
feed = RSS::Maker.make("atom:entry") do |maker|
setup_dummy_channel_atom(maker)
feed_size.times do |i|
entry_class = RSS::Atom::Entry
entry = entry_class.new
entry.title = entry_class::Title.new(:content => "#{title}#{i}")
entry.links << entry_class::Link.new(:href => "#{link}#{i}")
entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
entry.updated = entry_class::Updated.new(:content => updated + i * 60)
entry.setup_maker(maker.items)
end
maker.items.do_sort = false
end
assert_equal(1, feed.items.size)
assert_equal("#{title}0", feed.title.content)
assert_equal("#{link}0", feed.link.href)
assert_equal("#{summary}0", feed.summary.content)
feed = RSS::Maker.make("atom:entry") do |maker|
setup_dummy_channel_atom(maker)
feed_size.times do |i|
entry_class = RSS::Atom::Entry
entry = entry_class.new
entry.title = entry_class::Title.new(:content => "#{title}#{i}")
entry.links << entry_class::Link.new(:href => "#{link}#{i}")
entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
entry.updated = entry_class::Updated.new(:content => updated + i * 60)
entry.setup_maker(maker.items)
end
maker.items.do_sort = true
end
assert_equal(1, feed.items.size)
assert_equal("#{title}#{feed_size - 1}", feed.title.content)
assert_equal("#{link}#{feed_size - 1}", feed.link.href)
assert_equal("#{summary}#{feed_size - 1}", feed.summary.content)
end
def test_setup_maker_items_backward_compatibility
test_setup_maker_items(true)
end
def test_setup_maker
encoding = "EUC-JP"
standalone = true
href = 'a.xsl'
type = 'text/xsl'
title = 'sample'
media = 'printer'
charset = 'UTF-8'
alternate = 'yes'
feed = RSS::Maker.make("atom:entry") do |maker|
maker.encoding = encoding
maker.standalone = standalone
maker.xml_stylesheets.new_xml_stylesheet do |xss|
xss.href = href
xss.type = type
xss.title = title
xss.media = media
xss.charset = charset
xss.alternate = alternate
end
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_not_nil(feed)
new_feed = RSS::Maker.make("atom:entry") do |maker|
feed.setup_maker(maker)
end
assert_equal(["atom", "1.0", "entry"], new_feed.feed_info)
assert_equal(encoding, new_feed.encoding)
assert_equal(standalone, new_feed.standalone)
xss = new_feed.xml_stylesheets.first
assert_equal(1, new_feed.xml_stylesheets.size)
assert_equal(href, xss.href)
assert_equal(type, xss.type)
assert_equal(title, xss.title)
assert_equal(media, xss.media)
assert_equal(charset, xss.charset)
assert_equal(alternate, xss.alternate)
end
def test_setup_maker_full
encoding = "EUC-JP"
standalone = true
href = 'a.xsl'
type = 'text/xsl'
title = 'sample'
media = 'printer'
charset = 'UTF-8'
alternate = 'yes'
channel_about = "http://hoge.com"
channel_title = "fugafuga"
channel_link = "http://hoge.com"
channel_description = "fugafugafugafuga"
channel_author = "Bob"
image_url = "http://hoge.com/hoge.png"
item_title = "TITLE"
item_link = "http://hoge.com/"
item_description = "text hoge fuga"
entry_size = 5
feed = RSS::Maker.make("atom:entry") do |maker|
maker.encoding = encoding
maker.standalone = standalone
maker.xml_stylesheets.new_xml_stylesheet do |xss|
xss.href = href
xss.type = type
xss.title = title
xss.media = media
xss.charset = charset
xss.alternate = alternate
end
maker.channel.about = channel_about
maker.channel.title = channel_title
maker.channel.link = channel_link
maker.channel.description = channel_description
maker.channel.author = channel_author
@dc_elems.each do |var, value|
maker.channel.__send__("dc_#{var}=", value)
end
maker.image.url = image_url
entry_size.times do |i|
maker.items.new_item do |item|
item.title = "#{item_title}#{i}"
item.link = "#{item_link}#{i}"
item.description = "#{item_description}#{i}"
@dc_elems.each do |var, value|
item.__send__("dc_#{var}=", value)
end
end
end
end
new_feed = RSS::Maker.make("atom:entry") do |maker|
feed.setup_maker(maker)
end
assert_equal(["atom", "1.0", "entry"], new_feed.feed_info)
assert_equal(encoding, new_feed.encoding)
assert_equal(standalone, new_feed.standalone)
xss = new_feed.xml_stylesheets.first
assert_equal(1, new_feed.xml_stylesheets.size)
assert_equal(href, xss.href)
assert_equal(type, xss.type)
assert_equal(title, xss.title)
assert_equal(media, xss.media)
assert_equal(charset, xss.charset)
assert_equal(alternate, xss.alternate)
assert_equal("#{item_title}0", new_feed.title.content)
assert_equal("#{item_link}0", new_feed.link.href)
assert_equal("#{item_description}0", new_feed.summary.content)
@dc_elems.each do |var, value|
assert_equal(value, new_feed.__send__("dc_#{var}"))
end
assert_equal(1, new_feed.items.size)
end
end
end

View file

@ -0,0 +1,445 @@
require "rss-testcase"
require "rss/maker"
module RSS
class TestSetupMakerAtomFeed < TestCase
def setup
t = Time.iso8601("2000-01-01T12:00:05+00:00")
class << t
alias_method(:to_s, :iso8601)
end
@dc_elems = {
:title => "hoge",
:description =>
" XML is placing increasingly heavy loads on
the existing technical infrastructure of the Internet.",
:creator => "Rael Dornfest (mailto:rael@oreilly.com)",
:subject => "XML",
:publisher => "The O'Reilly Network",
:contributor => "hogehoge",
:type => "fugafuga",
:format => "hohoho",
:identifier => "fufufu",
:source => "barbar",
:language => "ja",
:relation => "cococo",
:rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
:date => t,
}
end
def test_setup_maker_feed(with_dc=true)
authors = [
{
:name => "Bob",
:uri => "http://example.com/~bob/",
:email => "bob@example.com",
},
{
:name => "Alice",
:uri => "http://example.com/~alice/",
:email => "alice@example.com",
},
]
categories = [
{
:term => "music",
:label => "Music",
},
{
:term => "book",
:scheme => "http://example.com/category/book/",
:label => "Book",
},
]
contributors = [
{
:name => "Chris",
:email => "chris@example.com",
},
{
:name => "Eva",
:uri => "http://example.com/~eva/",
},
]
generator = {
:uri => "http://example.com/generator/",
:version => "0.0.1",
:content => "Feed Generator",
}
icon = "http://example.com/icon.png"
about = "http://hoge.com"
title = "fugafuga"
link = "http://hoge.com"
logo = "http://example.com/logo.png"
rights = "Copyrights (c) 2007 Alice and Bob"
description = "fugafugafugafuga"
updated = Time.now
feed = RSS::Maker.make("atom") do |maker|
authors.each do |author_info|
maker.channel.authors.new_author do |author|
author_info.each do |key, value|
author.__send__("#{key}=", value)
end
end
end
categories.each do |category_info|
maker.channel.categories.new_category do |category|
category_info.each do |key, value|
category.__send__("#{key}=", value)
end
end
end
contributors.each do |contributor_info|
maker.channel.contributors.new_contributor do |contributor|
contributor_info.each do |key, value|
contributor.__send__("#{key}=", value)
end
end
end
generator.each do |key, value|
maker.channel.generator do |g|
g.__send__("#{key}=", value)
end
end
maker.channel.icon = icon
maker.channel.about = about
maker.channel.link = link
maker.channel.logo = logo
maker.channel.rights = rights
maker.channel.title = title
maker.channel.description = description
maker.channel.updated = updated
if with_dc
@dc_elems.each do |var, value|
if var == :date
maker.channel.new_dc_date(value)
else
maker.channel.__send__("dc_#{var}=", value)
end
end
end
setup_dummy_item_atom(maker)
end
assert_not_nil(feed)
new_feed = RSS::Maker.make("atom") do |maker|
feed.setup_maker(maker)
end
assert_not_nil(new_feed)
new_authors = new_feed.authors.collect do |author|
{
:name => author.name.content,
:uri => author.uri.content,
:email => author.email.content,
}
end
assert_equal(authors, new_authors)
new_categories = new_feed.categories.collect do |category|
{
:term => category.term,
:scheme => category.scheme,
:label => category.label,
}.reject {|key, value| value.nil?}
end
assert_equal(categories, new_categories)
new_contributors = new_feed.contributors.collect do |contributor|
info = {}
info[:name] = contributor.name.content
info[:uri] = contributor.uri.content if contributor.uri
info[:email] = contributor.email.content if contributor.email
info
end
assert_equal(contributors, new_contributors)
new_generator = {
:uri => new_feed.generator.uri,
:version => new_feed.generator.version,
:content => new_feed.generator.content,
}
assert_equal(generator, new_generator)
assert_equal(icon, new_feed.icon.content)
assert_equal(about, new_feed.id.content)
assert_equal(link, new_feed.link.href)
assert_equal(logo, new_feed.logo.content)
assert_equal(rights, new_feed.rights.content)
assert_equal(description, new_feed.subtitle.content)
assert_equal(title, new_feed.title.content)
assert_equal(updated, new_feed.updated.content)
if with_dc
@dc_elems.each do |var, value|
if var == :date
assert_equal([updated, value],
new_feed.dc_dates.collect {|date| date.value})
else
assert_equal(value, new_feed.__send__("dc_#{var}"))
end
end
end
assert_equal(1, new_feed.items.size)
end
def test_setup_maker_feed_without_dc
test_setup_maker_feed(false)
end
def test_setup_maker_items(for_backward_compatibility=false)
title = "TITLE"
link = "http://hoge.com/"
description = "text hoge fuga"
updated = Time.now
item_size = 5
feed = RSS::Maker.make("atom") do |maker|
setup_dummy_channel_atom(maker)
item_size.times do |i|
maker.items.new_item do |item|
item.title = "#{title}#{i}"
item.link = "#{link}#{i}"
item.description = "#{description}#{i}"
item.updated = updated + i * 60
end
end
end
new_feed = RSS::Maker.make("atom") do |maker|
feed.items.each do |item|
if for_backward_compatibility
item.setup_maker(maker)
else
item.setup_maker(maker.items)
end
end
feed.items.clear
feed.setup_maker(maker)
end
assert_equal(item_size, new_feed.items.size)
new_feed.items.each_with_index do |item, i|
assert_equal("#{title}#{i}", item.title.content)
assert_equal("#{link}#{i}", item.link.href)
assert_equal("#{description}#{i}", item.summary.content)
assert_equal(updated + i * 60, item.updated.content)
end
end
def test_setup_maker_items_sort
title = "TITLE"
link = "http://hoge.com/"
summary = "text hoge fuga"
updated = Time.now
feed_size = 5
feed = RSS::Maker.make("atom") do |maker|
setup_dummy_channel_atom(maker)
feed_size.times do |i|
entry_class = RSS::Atom::Feed::Entry
entry = entry_class.new
entry.title = entry_class::Title.new(:content => "#{title}#{i}")
entry.links << entry_class::Link.new(:href => "#{link}#{i}")
entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
entry.updated = entry_class::Updated.new(:content => updated + i * 60)
entry.setup_maker(maker.items)
end
maker.items.do_sort = false
end
assert_equal(feed_size, feed.entries.size)
feed.entries.each_with_index do |entry, i|
assert_equal("#{title}#{i}", entry.title.content)
assert_equal("#{link}#{i}", entry.link.href)
assert_equal("#{summary}#{i}", entry.summary.content)
end
feed = RSS::Maker.make("atom") do |maker|
setup_dummy_channel_atom(maker)
feed_size.times do |i|
entry_class = RSS::Atom::Feed::Entry
entry = entry_class.new
entry.title = entry_class::Title.new(:content => "#{title}#{i}")
entry.links << entry_class::Link.new(:href => "#{link}#{i}")
entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
entry.updated = entry_class::Updated.new(:content => updated + i * 60)
entry.setup_maker(maker.items)
end
maker.items.do_sort = true
end
assert_equal(feed_size, feed.entries.size)
feed.entries.reverse.each_with_index do |entry, i|
assert_equal("#{title}#{i}", entry.title.content)
assert_equal("#{link}#{i}", entry.link.href)
assert_equal("#{summary}#{i}", entry.summary.content)
end
end
def test_setup_maker_items_backward_compatibility
test_setup_maker_items(true)
end
def test_setup_maker
encoding = "EUC-JP"
standalone = true
href = 'a.xsl'
type = 'text/xsl'
title = 'sample'
media = 'printer'
charset = 'UTF-8'
alternate = 'yes'
feed = RSS::Maker.make("atom") do |maker|
maker.encoding = encoding
maker.standalone = standalone
maker.xml_stylesheets.new_xml_stylesheet do |xss|
xss.href = href
xss.type = type
xss.title = title
xss.media = media
xss.charset = charset
xss.alternate = alternate
end
setup_dummy_channel_atom(maker)
setup_dummy_item_atom(maker)
end
assert_not_nil(feed)
new_feed = RSS::Maker.make("atom") do |maker|
feed.setup_maker(maker)
end
assert_equal(["atom", "1.0", "feed"], new_feed.feed_info)
assert_equal(encoding, new_feed.encoding)
assert_equal(standalone, new_feed.standalone)
xss = new_feed.xml_stylesheets.first
assert_equal(1, new_feed.xml_stylesheets.size)
assert_equal(href, xss.href)
assert_equal(type, xss.type)
assert_equal(title, xss.title)
assert_equal(media, xss.media)
assert_equal(charset, xss.charset)
assert_equal(alternate, xss.alternate)
end
def test_setup_maker_full
encoding = "EUC-JP"
standalone = true
href = 'a.xsl'
type = 'text/xsl'
title = 'sample'
media = 'printer'
charset = 'UTF-8'
alternate = 'yes'
channel_about = "http://hoge.com"
channel_title = "fugafuga"
channel_link = "http://hoge.com"
channel_description = "fugafugafugafuga"
channel_author = "Bob"
image_url = "http://hoge.com/hoge.png"
item_title = "TITLE"
item_link = "http://hoge.com/"
item_description = "text hoge fuga"
entry_size = 5
feed = RSS::Maker.make("atom") do |maker|
maker.encoding = encoding
maker.standalone = standalone
maker.xml_stylesheets.new_xml_stylesheet do |xss|
xss.href = href
xss.type = type
xss.title = title
xss.media = media
xss.charset = charset
xss.alternate = alternate
end
maker.channel.about = channel_about
maker.channel.title = channel_title
maker.channel.link = channel_link
maker.channel.description = channel_description
maker.channel.author = channel_author
@dc_elems.each do |var, value|
maker.channel.__send__("dc_#{var}=", value)
end
maker.image.url = image_url
entry_size.times do |i|
maker.items.new_item do |item|
item.title = "#{item_title}#{i}"
item.link = "#{item_link}#{i}"
item.description = "#{item_description}#{i}"
@dc_elems.each do |var, value|
item.__send__("dc_#{var}=", value)
end
end
end
end
new_feed = RSS::Maker.make("atom") do |maker|
feed.setup_maker(maker)
end
assert_equal(["atom", "1.0", "feed"], new_feed.feed_info)
assert_equal(encoding, new_feed.encoding)
assert_equal(standalone, new_feed.standalone)
xss = new_feed.xml_stylesheets.first
assert_equal(1, new_feed.xml_stylesheets.size)
assert_equal(href, xss.href)
assert_equal(type, xss.type)
assert_equal(title, xss.title)
assert_equal(media, xss.media)
assert_equal(charset, xss.charset)
assert_equal(alternate, xss.alternate)
assert_equal(channel_title, new_feed.title.content)
assert_equal(channel_link, new_feed.link.href)
assert_equal(channel_description, new_feed.subtitle.content)
assert_equal(channel_author, new_feed.author.name.content)
assert_equal(image_url, new_feed.logo.content)
@dc_elems.each do |var, value|
assert_equal(value, new_feed.__send__("dc_#{var}"))
end
assert_equal(entry_size, new_feed.entries.size)
new_feed.entries.each_with_index do |entry, i|
assert_equal("#{item_title}#{i}", entry.title.content)
assert_equal("#{item_link}#{i}", entry.link.href)
assert_equal("#{item_description}#{i}", entry.summary.content)
@dc_elems.each do |var, value|
assert_equal(value, entry.__send__("dc_#{var}"))
end
end
end
end
end

View file

@ -0,0 +1,144 @@
require "rss-testcase"
require "rss/maker"
module RSS
class TestSetupMakerITunes < TestCase
def test_setup_maker_simple
author = "John Doe"
block = true
categories = ["Audio Blogs"]
image = "http://example.com/podcasts/everything/AllAboutEverything.jpg"
duration = "4:05"
duration_components = [0, 4, 5]
explicit = true
keywords = ["salt", "pepper", "shaker", "exciting"]
new_feed_url = "http://newlocation.com/example.rss"
owner = {:name => "John Doe", :email => "john.doe@example.com"}
subtitle = "A show about everything"
summary = "All About Everything is a show about " +
"everything. Each week we dive into any " +
"subject known to man and talk about it " +
"as much as we can. Look for our Podcast " +
"in the iTunes Music Store"
feed = RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
channel = maker.channel
channel.itunes_author = author
channel.itunes_block = block
categories.each do |category|
channel.itunes_categories.new_category.text = category
end
channel.itunes_image = image
channel.itunes_explicit = explicit
channel.itunes_keywords = keywords
channel.itunes_owner.itunes_name = owner[:name]
channel.itunes_owner.itunes_email = owner[:email]
channel.itunes_subtitle = subtitle
channel.itunes_summary = summary
item = maker.items.last
item.itunes_author = author
item.itunes_block = block
item.itunes_duration = duration
item.itunes_explicit = explicit
item.itunes_keywords = keywords
item.itunes_subtitle = subtitle
item.itunes_summary = summary
end
assert_not_nil(feed)
new_feed = RSS::Maker.make("rss2.0") do |maker|
feed.setup_maker(maker)
end
assert_not_nil(new_feed)
channel = new_feed.channel
item = new_feed.items.last
assert_equal(author, channel.itunes_author)
assert_equal(author, item.itunes_author)
assert_equal(block, channel.itunes_block?)
assert_equal(block, item.itunes_block?)
assert_equal(categories,
collect_itunes_categories(channel.itunes_categories))
assert_equal(image, channel.itunes_image.href)
assert_equal(duration_components,
[item.itunes_duration.hour,
item.itunes_duration.minute,
item.itunes_duration.second])
assert_equal(explicit, channel.itunes_explicit?)
assert_equal(explicit, item.itunes_explicit?)
assert_equal(keywords, channel.itunes_keywords)
assert_equal(keywords, item.itunes_keywords)
assert_equal(owner,
{
:name => channel.itunes_owner.itunes_name,
:email => channel.itunes_owner.itunes_email
})
assert_equal(subtitle, channel.itunes_subtitle)
assert_equal(subtitle, item.itunes_subtitle)
assert_equal(summary, channel.itunes_summary)
assert_equal(summary, item.itunes_summary)
end
def test_setup_maker_with_nested_categories
categories = [["Arts & Entertainment", "Games"],
["Technology", "Computers"],
"Audio Blogs"]
feed = RSS::Maker.make("rss2.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
channel = maker.channel
categories.each do |category|
target = channel.itunes_categories
if category.is_a?(Array)
category.each do |sub_category|
target = target.new_category
target.text = sub_category
end
else
target.new_category.text = category
end
end
end
assert_not_nil(feed)
new_feed = RSS::Maker.make("rss2.0") do |maker|
feed.setup_maker(maker)
end
assert_not_nil(new_feed)
channel = new_feed.channel
assert_equal(categories,
collect_itunes_categories(channel.itunes_categories))
end
private
def collect_itunes_categories(categories)
categories.collect do |c|
rest = collect_itunes_categories(c.itunes_categories)
if rest.empty?
c.text
else
[c.text, *rest]
end
end
end
end
end

View file

@ -0,0 +1,38 @@
require "rss-testcase"
require "rss/maker"
module RSS
class TestSetupMakerSlash < TestCase
def test_setup_maker
elements = {
"section" => "articles",
"department" => "not-an-ocean-unless-there-are-lobsters",
"comments" => 177,
"hit_parades" => [177, 155, 105, 33, 6, 3, 0],
}
rss = RSS::Maker.make("rss1.0") do |maker|
setup_dummy_channel(maker)
setup_dummy_item(maker)
item = maker.items.last
item.slash_section = elements["section"]
item.slash_department = elements["department"]
item.slash_comments = elements["comments"]
item.slash_hit_parade = elements["hit_parades"].join(",")
end
assert_not_nil(rss)
new_rss = RSS::Maker.make("rss1.0") do |maker|
rss.setup_maker(maker)
end
assert_not_nil(new_rss)
item = new_rss.items.last
assert_not_nil(item)
assert_slash_elements(elements, item)
end
end
end

64
test/rss/test_slash.rb Normal file
View file

@ -0,0 +1,64 @@
require "cgi"
require "rexml/document"
require "rss-testcase"
require "rss/1.0"
require "rss/slash"
module RSS
class TestSlash < TestCase
def setup
@elements = {
"section" => "articles",
"department" => "not-an-ocean-unless-there-are-lobsters",
"comments" => 177,
"hit_parades" => [177, 155, 105, 33, 6, 3, 0],
}
slash_nodes = @elements.collect do |name, value|
if name == "hit_parades"
name = "hit_parade"
value = value.join(",")
end
"<slash:#{name}>#{value}</slash:#{name}>"
end.join("\n")
slash_ns = {"slash" => "http://purl.org/rss/1.0/modules/slash/"}
@source = make_RDF(<<-EOR, slash_ns)
#{make_channel}
#{make_image}
#{make_item(slash_nodes)}
#{make_textinput}
EOR
end
def test_parser
rss = RSS::Parser.parse(@source)
assert_not_nil(rss)
item = rss.items[0]
assert_not_nil(item)
assert_slash_elements(item)
end
def test_to_s
rss = RSS::Parser.parse(@source)
rss = RSS::Parser.parse(rss.to_s)
assert_not_nil(rss)
item = rss.items[0]
assert_not_nil(item)
assert_slash_elements(item)
end
private
def assert_slash_elements(target)
super(@elements, target)
end
end
end

View file

@ -93,7 +93,7 @@ EOR
%w(-2 0.3 -0.4).each do |x| %w(-2 0.3 -0.4).each do |x|
@parents.each do |parent| @parents.each do |parent|
assert_not_available_value("updateBase", x) do assert_not_available_value("sy:updateBase", x) do
@rss.__send__(parent).sy_updateBase = x @rss.__send__(parent).sy_updateBase = x
end end
end end
@ -120,8 +120,6 @@ EOR
end end
end end
end end
end end
end end
end end

View file

@ -144,8 +144,10 @@ EOR
end end
@topic_nodes.each_with_index do |node, i| @topic_nodes.each_with_index do |node, i|
expected = REXML::Document.new(node).root expected_xml = taxo_xmlns_container(node)
actual = REXML::Document.new(@rss.taxo_topics[i].to_s(true, "")).root expected = REXML::Document.new(expected_xml).root.elements[1]
actual_xml = taxo_xmlns_container(@rss.taxo_topics[i].to_s(true, ""))
actual = REXML::Document.new(actual_xml).root.elements[1]
expected_elems = expected.reject {|x| x.is_a?(REXML::Text)} expected_elems = expected.reject {|x| x.is_a?(REXML::Text)}
actual_elems = actual.reject {|x| x.is_a?(REXML::Text)} actual_elems = actual.reject {|x| x.is_a?(REXML::Text)}
expected_elems.sort! {|x, y| x.name <=> y.name} expected_elems.sort! {|x, y| x.name <=> y.name}
@ -155,6 +157,16 @@ EOR
assert_equal(expected.attributes.sort, actual.attributes.sort) assert_equal(expected.attributes.sort, actual.attributes.sort)
end end
end end
private
def taxo_xmlns_container(content)
xmlns_container({
@prefix => @uri,
"dc" => "http://purl.org/dc/elements/1.1/",
"rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
},
content)
end
end end
end end

View file

@ -12,7 +12,6 @@ require "rss/trackback"
module RSS module RSS
class TestToS < TestCase class TestToS < TestCase
def setup def setup
@image_url = "http://example.com/foo.png" @image_url = "http://example.com/foo.png"
@textinput_link = "http://example.com/search.cgi" @textinput_link = "http://example.com/search.cgi"
@ -436,5 +435,236 @@ module RSS
end end
end end
def assert_channel10(attrs, channel)
_wrap_assertion do
n_attrs = normalized_attrs(attrs)
names = %w(about title link description)
assert_attributes(attrs, names, channel)
%w(image items textinput).each do |name|
value = n_attrs[name]
if value
target = channel.__send__(name)
__send__("assert_channel10_#{name}", value, target)
end
end
end
end
def assert_channel10_image(attrs, image)
_wrap_assertion do
assert_attributes(attrs, %w(resource), image)
end
end
def assert_channel10_textinput(attrs, textinput)
_wrap_assertion do
assert_attributes(attrs, %w(resource), textinput)
end
end
def assert_channel10_items(attrs, items)
_wrap_assertion do
assert_equal(items.resources, items.Seq.lis.collect {|x| x.resource})
items.Seq.lis.each_with_index do |li, i|
assert_attributes(attrs[i], %w(resource), li)
end
end
end
def assert_image10(attrs, image)
_wrap_assertion do
names = %w(about title url link)
assert_attributes(attrs, names, image)
end
end
def assert_items10(attrs, items)
_wrap_assertion do
names = %w(about title link description)
items.each_with_index do |item, i|
assert_attributes(attrs[i], names, item)
end
end
end
def assert_textinput10(attrs, textinput)
_wrap_assertion do
names = %w(about title description name link)
assert_attributes(attrs, names, textinput)
end
end
def assert_channel09(attrs, channel)
_wrap_assertion do
n_attrs = normalized_attrs(attrs)
names = %w(title description link language rating
copyright pubDate lastBuildDate docs
managingEditor webMaster)
assert_attributes(attrs, names, channel)
%w(skipHours skipDays).each do |name|
value = n_attrs[name]
if value
target = channel.__send__(name)
__send__("assert_channel09_#{name}", value, target)
end
end
end
end
def assert_channel09_skipDays(contents, skipDays)
_wrap_assertion do
days = skipDays.days
contents.each_with_index do |content, i|
assert_equal(content, days[i].content)
end
end
end
def assert_channel09_skipHours(contents, skipHours)
_wrap_assertion do
hours = skipHours.hours
contents.each_with_index do |content, i|
assert_equal(content.to_i, hours[i].content)
end
end
end
def assert_image09(attrs, image)
_wrap_assertion do
names = %w(url link title description)
names << ["width", :integer]
names << ["height", :integer]
assert_attributes(attrs, names, image)
end
end
def assert_items09(attrs, items)
_wrap_assertion do
names = %w(title link description)
items.each_with_index do |item, i|
assert_attributes(attrs[i], names, item)
end
end
end
def assert_textinput09(attrs, textinput)
_wrap_assertion do
names = %w(title description name link)
assert_attributes(attrs, names, textinput)
end
end
def assert_channel20(attrs, channel)
_wrap_assertion do
n_attrs = normalized_attrs(attrs)
names = %w(title link description language copyright
managingEditor webMaster pubDate
lastBuildDate generator docs rating)
names << ["ttl", :integer]
assert_attributes(attrs, names, channel)
%w(cloud categories skipHours skipDays).each do |name|
value = n_attrs[name]
if value
target = channel.__send__(name)
__send__("assert_channel20_#{name}", value, target)
end
end
end
end
def assert_channel20_skipDays(contents, skipDays)
assert_channel09_skipDays(contents, skipDays)
end
def assert_channel20_skipHours(contents, skipHours)
assert_channel09_skipHours(contents, skipHours)
end
def assert_channel20_cloud(attrs, cloud)
_wrap_assertion do
names = %w(domain path registerProcedure protocol)
names << ["port", :integer]
assert_attributes(attrs, names, cloud)
end
end
def assert_channel20_categories(attrs, categories)
_wrap_assertion do
names = %w(domain content)
categories.each_with_index do |category, i|
assert_attributes(attrs[i], names, category)
end
end
end
def assert_image20(attrs, image)
_wrap_assertion do
names = %w(url link title description)
names << ["width", :integer]
names << ["height", :integer]
assert_attributes(attrs, names, image)
end
end
def assert_items20(attrs, items)
_wrap_assertion do
names = %w(about title link description)
items.each_with_index do |item, i|
assert_attributes(attrs[i], names, item)
n_attrs = normalized_attrs(attrs[i])
%w(source enclosure categories guid).each do |name|
value = n_attrs[name]
if value
target = item.__send__(name)
__send__("assert_items20_#{name}", value, target)
end
end
end
end
end
def assert_items20_source(attrs, source)
_wrap_assertion do
assert_attributes(attrs, %w(url content), source)
end
end
def assert_items20_enclosure(attrs, enclosure)
_wrap_assertion do
names = ["url", ["length", :integer], "type"]
assert_attributes(attrs, names, enclosure)
end
end
def assert_items20_categories(attrs, categories)
_wrap_assertion do
assert_channel20_categories(attrs, categories)
end
end
def assert_items20_guid(attrs, guid)
_wrap_assertion do
names = [["isPermaLink", :boolean], ["content"]]
assert_attributes(attrs, names, guid)
end
end
def assert_textinput20(attrs, textinput)
_wrap_assertion do
names = %w(title description name link)
assert_attributes(attrs, names, textinput)
end
end
end end
end end

View file

@ -3,7 +3,7 @@ require "rss-testcase"
module RSS module RSS
class TestVersion < TestCase class TestVersion < TestCase
def test_version def test_version
assert_equal("0.1.6", ::RSS::VERSION) assert_equal("0.2.0", ::RSS::VERSION)
end end
end end
end end

View file

@ -14,7 +14,7 @@ module RSS
{:media => "print", :title => "FOO"}, {:media => "print", :title => "FOO"},
{:charset => "UTF-8", :alternate => "yes"}, {:charset => "UTF-8", :alternate => "yes"},
].each do |attrs| ].each do |attrs|
assert_xml_stylesheet_attrs(attrs, XMLStyleSheet.new(*attrs)) assert_xml_stylesheet_attrs(attrs, XMLStyleSheet.new(attrs))
end end
end end
@ -35,8 +35,8 @@ module RSS
:media => "printer", :charset => "UTF-8", :media => "printer", :charset => "UTF-8",
:alternate => "yes"}, :alternate => "yes"},
].each do |attrs| ].each do |attrs|
target, contents = parse_pi(XMLStyleSheet.new(*attrs).to_s) target, contents = parse_pi(XMLStyleSheet.new(attrs).to_s)
assert_xml_stylesheet(target, attrs, XMLStyleSheet.new(*contents)) assert_xml_stylesheet(target, attrs, XMLStyleSheet.new(contents))
end end
end end

View file

@ -1,7 +1,7 @@
#define RUBY_VERSION "1.8.6" #define RUBY_VERSION "1.8.6"
#define RUBY_RELEASE_DATE "2007-10-15" #define RUBY_RELEASE_DATE "2007-10-21"
#define RUBY_VERSION_CODE 186 #define RUBY_VERSION_CODE 186
#define RUBY_RELEASE_CODE 20071015 #define RUBY_RELEASE_CODE 20071021
#define RUBY_PATCHLEVEL 5000 #define RUBY_PATCHLEVEL 5000
#define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MAJOR 1
@ -9,7 +9,7 @@
#define RUBY_VERSION_TEENY 6 #define RUBY_VERSION_TEENY 6
#define RUBY_RELEASE_YEAR 2007 #define RUBY_RELEASE_YEAR 2007
#define RUBY_RELEASE_MONTH 10 #define RUBY_RELEASE_MONTH 10
#define RUBY_RELEASE_DAY 15 #define RUBY_RELEASE_DAY 21
#ifdef RUBY_EXTERN #ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[]; RUBY_EXTERN const char ruby_version[];