* 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>
* 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.
#
# Author:: Kouhei Sutou <kou@cozmixng.org>
@ -6,11 +6,14 @@
require 'rss/1.0'
require 'rss/2.0'
require 'rss/atom'
require 'rss/content'
require 'rss/dublincore'
require 'rss/image'
require 'rss/itunes'
require 'rss/slash'
require 'rss/syndication'
#require 'rss/taxonomy'
require 'rss/taxonomy'
require 'rss/trackback'
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)
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
@feed_type = "rss"
end
def items
@ -57,12 +60,14 @@ module RSS
items.each do |item|
item.setup_maker(maker.items)
end
image.setup_maker(maker) if image
textinput.setup_maker(maker) if textinput
end
private
def _attrs
[
["version", true, "rss_version"],
["version", true, "feed_version"],
]
end
@ -400,21 +405,22 @@ module RSS
end
RSS09::ELEMENTS.each do |name|
BaseListener.install_get_text_element("", name, "#{name}=")
BaseListener.install_get_text_element("", name, name)
end
module ListenerMixin
private
def start_rss(tag_name, prefix, attrs, ns)
def initial_start_rss(tag_name, prefix, attrs, ns)
check_ns(tag_name, prefix, ns, "")
@rss = Rss.new(attrs['version'], @version, @encoding, @standalone)
@rss.do_validate = @do_validate
@rss.xml_stylesheets = @xml_stylesheets
@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
}
end
@proc_stack.push(pr)
end
end

View file

@ -45,10 +45,10 @@ module RSS
__send__("install_have_#{type}_element", tag, ::RSS::URI, occurs)
end
attr_accessor :rss_version, :version, :encoding, :standalone
alias_method(:rss_version, :feed_version)
def initialize(version=nil, encoding=nil, standalone=nil)
super('1.0', version, encoding, standalone)
@feed_type = "rss"
end
def full_name
@ -430,21 +430,22 @@ module RSS
end
RSS10::ELEMENTS.each do |name|
BaseListener.install_get_text_element(URI, name, "#{name}=")
BaseListener.install_get_text_element(URI, name, name)
end
module ListenerMixin
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)
@rss = RDF.new(@version, @encoding, @standalone)
@rss.do_validate = @do_validate
@rss.xml_stylesheets = @xml_stylesheets
@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
}
end
@proc_stack.push(pr)
end
end

View file

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

View file

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

View file

@ -1,12 +1,9 @@
require "rss/1.0"
require "rss/rss"
module RSS
DC_PREFIX = 'dc'
DC_URI = "http://purl.org/dc/elements/1.1/"
RDF.install_ns(DC_PREFIX, DC_URI)
module BaseDublinCoreModel
def append_features(klass)
super
@ -36,8 +33,20 @@ module RSS
EOC
end
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=
end
# For backward compatibility
alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list
EOC
end
end
@ -61,7 +70,7 @@ module RSS
"language" => nil,
"relation" => nil,
"coverage" => nil,
"rights" => "rightses" # FIXME
"rights" => "rights_list"
}
DATE_ELEMENTS = {
@ -122,12 +131,13 @@ module RSS
end
DATE_ELEMENTS.each do |name, type|
tag_name = "#{DC_PREFIX}:#{name}"
module_eval(<<-EOC, *get_file_and_line_from_caller(0))
class DublinCore#{Utils.to_class_name(name)} < Element
remove_method(:content=)
remove_method(:value=)
date_writer("content", #{type.dump}, #{name.dump})
date_writer("content", #{type.dump}, #{tag_name.dump})
alias_method(:value=, :content=)
end
@ -138,13 +148,6 @@ module RSS
# For backward compatibility
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|
class_name = Utils.to_class_name(name)
BaseListener.install_class_name(DC_URI, name, "DublinCore#{class_name}")
@ -152,3 +155,7 @@ module RSS
DublinCoreModel::ELEMENTS.collect! {|name| "#{DC_PREFIX}_#{name}"}
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
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)
@ -69,7 +69,7 @@ module RSS
disp_name = "#{IMAGE_PREFIX}:#{tag}"
install_text_element(tag, IMAGE_URI, "?",
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
alias width= image_width=
@ -142,8 +142,8 @@ module RSS
end
AVAILABLE_SIZES = %w(small medium large)
alias_method :_size=, :size=
private :_size=
alias_method :set_size, :size=
private :set_size
def size=(new_value)
if @do_validate and !new_value.nil?
new_value = new_value.strip
@ -152,7 +152,7 @@ module RSS
raise NotAvailableValueError.new(full_name, new_value, attr_name)
end
end
__send__(:_size=, new_value)
set_size(new_value)
end
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"
module RSS
module Maker
MAKERS = {}
class << self
def make(version, &block)
maker(version).make(&block)
m = maker(version)
raise UnsupportedMakerVersionError.new(version) if m.nil?
m.make(&block)
end
def maker(version)
@ -19,19 +19,26 @@ module RSS
MAKERS[version] = maker
end
def filename_to_version(filename)
File.basename(filename, ".*")
end
end
def versions
MAKERS.keys.uniq.sort
end
def makers
MAKERS.values.uniq
end
end
end
end
require "rss/maker/1.0"
require "rss/maker/2.0"
require "rss/maker/feed"
require "rss/maker/entry"
require "rss/maker/content"
require "rss/maker/dublincore"
require "rss/maker/slash"
require "rss/maker/syndication"
require "rss/maker/taxonomy"
require "rss/maker/trackback"
require "rss/maker/image"
require "rss/maker/itunes"

View file

@ -7,13 +7,14 @@ module RSS
class RSS09 < RSSBase
def initialize(rss_version="0.91")
def initialize(feed_version="0.91")
super
@feed_type = "rss"
end
private
def make_rss
Rss.new(@rss_version, @version, @encoding, @standalone)
def make_feed
Rss.new(@feed_version, @version, @encoding, @standalone)
end
def setup_elements(rss)
@ -21,41 +22,34 @@ module RSS
end
class Channel < ChannelBase
def to_rss(rss)
def to_feed(rss)
channel = Rss::Channel.new
set = setup_values(channel)
if set
_not_set_required_variables = not_set_required_variables
if _not_set_required_variables.empty?
rss.channel = channel
set_parent(channel, rss)
setup_items(rss)
setup_image(rss)
setup_textinput(rss)
setup_other_elements(rss)
if rss.channel.image
setup_other_elements(rss, channel)
rss
else
nil
raise NotSetError.new("maker.channel", _not_set_required_variables)
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
private
def setup_items(rss)
@maker.items.to_rss(rss)
@maker.items.to_feed(rss)
end
def setup_image(rss)
@maker.image.to_rss(rss)
@maker.image.to_feed(rss)
end
def setup_textinput(rss)
@maker.textinput.to_rss(rss)
@maker.textinput.to_feed(rss)
end
def variables
@ -63,162 +57,405 @@ module RSS
end
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
class SkipDays < SkipDaysBase
def to_rss(rss, channel)
def to_feed(rss, channel)
unless @days.empty?
skipDays = Rss::Channel::SkipDays.new
channel.skipDays = skipDays
set_parent(skipDays, channel)
@days.each do |day|
day.to_rss(rss, skipDays.days)
day.to_feed(rss, skipDays.days)
end
end
end
class Day < DayBase
def to_rss(rss, days)
def to_feed(rss, days)
day = Rss::Channel::SkipDays::Day.new
set = setup_values(day)
if set
days << day
setup_other_elements(rss)
set_parent(day, days)
setup_other_elements(rss, day)
end
end
def have_required_values?
@content
private
def required_variable_names
%w(content)
end
end
end
class SkipHours < SkipHoursBase
def to_rss(rss, channel)
def to_feed(rss, channel)
unless @hours.empty?
skipHours = Rss::Channel::SkipHours.new
channel.skipHours = skipHours
set_parent(skipHours, channel)
@hours.each do |hour|
hour.to_rss(rss, skipHours.hours)
hour.to_feed(rss, skipHours.hours)
end
end
end
class Hour < HourBase
def to_rss(rss, hours)
def to_feed(rss, hours)
hour = Rss::Channel::SkipHours::Hour.new
set = setup_values(hour)
if set
hours << hour
setup_other_elements(rss)
set_parent(hour, hours)
setup_other_elements(rss, hour)
end
end
def have_required_values?
@content
private
def required_variable_names
%w(content)
end
end
end
class Cloud < CloudBase
def to_rss(*args)
def to_feed(*args)
end
end
class Categories < CategoriesBase
def to_rss(*args)
def to_feed(*args)
end
class Category < CategoryBase
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
class Image < ImageBase
def to_rss(rss)
def to_feed(rss)
image = Rss::Channel::Image.new
set = setup_values(image)
if set
image.link = link
rss.channel.image = image
setup_other_elements(rss)
end
end
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)
set_parent(image, rss.channel)
setup_other_elements(rss, image)
elsif required_element?
raise NotSetError.new("maker.image", not_set_required_variables)
end
end
private
def have_required_values?
@title and @link
def required_variable_names
%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
class Guid < GuidBase
def to_rss(*args)
def to_feed(*args)
end
end
class Enclosure < EnclosureBase
def to_rss(*args)
def to_feed(*args)
end
end
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
class Categories < CategoriesBase
def to_rss(*args)
def to_feed(*args)
end
class Category < CategoryBase
end
end
class Contributors < ContributorsBase
def to_feed(*args)
end
class Contributor < ContributorBase
end
end
class Textinput < TextinputBase
def to_rss(rss)
textInput = Rss::Channel::TextInput.new
set = setup_values(textInput)
if set
rss.channel.textInput = textInput
setup_other_elements(rss)
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(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
private
def have_required_values?
@title and @description and @name and @link
def required_variable_names
%w(href)
end
end
end
add_maker(filename_to_version(__FILE__), RSS09)
add_maker(filename_to_version(__FILE__) + "1", RSS09)
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
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

View file

@ -9,10 +9,11 @@ module RSS
def initialize
super("1.0")
@feed_type = "rss"
end
private
def make_rss
def make_feed
RDF.new(@version, @encoding, @standalone)
end
@ -25,43 +26,46 @@ module RSS
class Channel < ChannelBase
def to_rss(rss)
set = false
if @about
def to_feed(rss)
set_default_values do
_not_set_required_variables = not_set_required_variables
if _not_set_required_variables.empty?
channel = RDF::Channel.new(@about)
set = setup_values(channel)
if set
channel.dc_dates.clear
rss.channel = channel
set_parent(channel, rss)
setup_items(rss)
setup_image(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
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
private
def setup_items(rss)
items = RDF::Channel::Items.new
seq = items.Seq
@maker.items.normalize.each do |item|
seq.lis << RDF::Channel::Items::Seq::Li.new(item.link)
set_parent(items, seq)
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
rss.channel.items = items
set_parent(rss.channel, items)
end
def setup_image(rss)
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
@ -69,15 +73,23 @@ module RSS
if @maker.textinput.have_required_values?
textinput = RDF::Channel::Textinput.new(@maker.textinput.link)
rss.channel.textinput = textinput
set_parent(textinput, rss.channel)
end
end
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
class SkipDays < SkipDaysBase
def to_rss(*args)
def to_feed(*args)
end
class Day < DayBase
@ -85,7 +97,7 @@ module RSS
end
class SkipHours < SkipHoursBase
def to_rss(*args)
def to_feed(*args)
end
class Hour < HourBase
@ -93,112 +105,330 @@ module RSS
end
class Cloud < CloudBase
def to_rss(*args)
def to_feed(*args)
end
end
class Categories < CategoriesBase
def to_rss(*args)
def to_feed(*args)
end
class Category < CategoryBase
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
class Image < ImageBase
def to_rss(rss)
def to_feed(rss)
if @url
image = RDF::Image.new(@url)
set = setup_values(image)
if set
rss.image = image
setup_other_elements(rss)
set_parent(image, rss)
setup_other_elements(rss, image)
end
end
end
def have_required_values?
@url and @title and link and @maker.channel.have_required_values?
super and @maker.channel.have_required_values?
end
private
def variables
super + ["link"]
end
def required_variable_names
%w(url title link)
end
end
class Items < ItemsBase
def to_rss(rss)
def to_feed(rss)
if rss.channel
normalize.each do |item|
item.to_rss(rss)
item.to_feed(rss)
end
setup_other_elements(rss)
setup_other_elements(rss, rss.items)
end
end
class Item < ItemBase
def to_rss(rss)
if @link
item = RDF::Item.new(@link)
def to_feed(rss)
set_default_values do
item = RDF::Item.new(link)
set = setup_values(item)
if set
item.dc_dates.clear
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
def have_required_values?
@title and @link
private
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
class Guid < GuidBase
def to_rss(*args)
def to_feed(*args)
end
end
class Enclosure < EnclosureBase
def to_rss(*args)
def to_feed(*args)
end
end
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
class Categories < CategoriesBase
def to_rss(*args)
def to_feed(*args)
end
class Category < CategoryBase
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
class Textinput < TextinputBase
def to_rss(rss)
def to_feed(rss)
if @link
textinput = RDF::Textinput.new(@link)
set = setup_values(textinput)
if set
rss.textinput = textinput
setup_other_elements(rss)
set_parent(textinput, rss)
setup_other_elements(rss, textinput)
end
end
end
def have_required_values?
@title and @description and @name and @link and
@maker.channel.have_required_values?
super and @maker.channel.have_required_values?
end
private
def required_variable_names
%w(title description name link)
end
end
end
add_maker(filename_to_version(__FILE__), RSS10)
add_maker("1.0", RSS10)
add_maker("rss1.0", RSS10)
end
end

View file

@ -7,18 +7,15 @@ module RSS
class RSS20 < RSS09
def initialize(rss_version="2.0")
def initialize(feed_version="2.0")
super
end
class Channel < RSS09::Channel
def have_required_values?
@title and @link and @description
end
private
def required_variable_names
%w(title link description)
%w(link)
end
class SkipDays < RSS09::Channel::SkipDays
@ -32,137 +29,186 @@ module RSS
end
class Cloud < RSS09::Channel::Cloud
def to_rss(rss, channel)
def to_feed(rss, channel)
cloud = Rss::Channel::Cloud.new
set = setup_values(cloud)
if set
channel.cloud = cloud
setup_other_elements(rss)
set_parent(cloud, channel)
setup_other_elements(rss, cloud)
end
end
def have_required_values?
@domain and @port and @path and
@registerProcedure and @protocol
private
def required_variable_names
%w(domain port path registerProcedure protocol)
end
end
class Categories < RSS09::Channel::Categories
def to_rss(rss, channel)
def to_feed(rss, channel)
@categories.each do |category|
category.to_rss(rss, channel)
category.to_feed(rss, channel)
end
end
class Category < RSS09::Channel::Categories::Category
def to_rss(rss, channel)
def to_feed(rss, channel)
category = Rss::Channel::Category.new
set = setup_values(category)
if set
channel.categories << category
setup_other_elements(rss)
set_parent(category, channel)
setup_other_elements(rss, category)
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
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
super + ["pubDate"]
end
class Guid < RSS09::Items::Item::Guid
def to_rss(rss, item)
def to_feed(rss, item)
guid = Rss::Channel::Item::Guid.new
set = setup_values(guid)
if set
item.guid = guid
setup_other_elements(rss)
set_parent(guid, item)
setup_other_elements(rss, guid)
end
end
def have_required_values?
@content
private
def required_variable_names
%w(content)
end
end
class Enclosure < RSS09::Items::Item::Enclosure
def to_rss(rss, item)
def to_feed(rss, item)
enclosure = Rss::Channel::Item::Enclosure.new
set = setup_values(enclosure)
if set
item.enclosure = enclosure
setup_other_elements(rss)
set_parent(enclosure, item)
setup_other_elements(rss, enclosure)
end
end
def have_required_values?
@url and @length and @type
private
def required_variable_names
%w(url length type)
end
end
class Source < RSS09::Items::Item::Source
def to_rss(rss, item)
def to_feed(rss, item)
source = Rss::Channel::Item::Source.new
set = setup_values(source)
if set
item.source = source
setup_other_elements(rss)
set_parent(source, item)
setup_other_elements(rss, source)
end
end
def have_required_values?
@url and @content
private
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
class Categories < RSS09::Items::Item::Categories
def to_rss(rss, item)
def to_feed(rss, item)
@categories.each do |category|
category.to_rss(rss, item)
category.to_feed(rss, item)
end
end
class Category < RSS09::Items::Item::Categories::Category
def to_rss(rss, item)
def to_feed(rss, item)
category = Rss::Channel::Item::Category.new
set = setup_values(category)
if set
item.categories << category
set_parent(category, item)
setup_other_elements(rss)
end
end
def have_required_values?
@content
end
private
def required_variable_names
%w(content)
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
class Textinput < RSS09::Textinput
end
end
add_maker(filename_to_version(__FILE__), RSS20)
add_maker("2.0", RSS20)
add_maker("rss2.0", RSS20)
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)
super
::RSS::ContentModel::ELEMENTS.each do |element|
klass.add_need_initialize_variable(element)
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
::RSS::ContentModel::ELEMENTS.each do |name|
klass.def_other_element(name)
end
end
end

View file

@ -15,60 +15,40 @@ module RSS
plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
full_plural_klass_name = "self.class::#{plural_klass_name}"
full_klass_name = "#{full_plural_klass_name}::#{klass_name}"
klass.add_need_initialize_variable(full_plural_name,
"make_#{full_plural_name}")
klass.add_other_element(full_plural_name)
klass.def_classed_elements(full_name, "value", plural_klass_name,
full_plural_name, name)
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
attr_accessor :#{full_plural_name}
def make_#{full_plural_name}
#{full_plural_klass_name}.new(@maker)
def new_#{full_name}(value=nil)
_#{full_name} = #{full_plural_name}.new_#{name}
_#{full_name}.value = value
if block_given?
yield _#{full_name}
else
_#{full_name}
end
def setup_#{full_plural_name}(rss, current)
@#{full_plural_name}.to_rss(rss, current)
end
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
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
# For backward compatibility
alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list
EOC
end
::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
plural_name ||= "#{name}s"
full_name ||= "#{DC_PREFIX}_#{name}"
full_plural_name ||= "#{DC_PREFIX}_#{plural_name}"
klass_name = Utils.to_class_name(name)
full_klass_name = "DublinCore#{klass_name}"
plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
module_eval(<<-EOC, __FILE__, __LINE__)
class #{plural_klass_name}Base
include Base
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
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class #{plural_klass_name}Base < Base
def_array_element(#{name.dump}, #{full_plural_name.dump},
#{full_klass_name.dump})
class #{full_klass_name}Base < Base
attr_accessor :value
add_need_initialize_variable("value")
alias_method(:content, :value)
@ -77,8 +57,16 @@ EOC
def have_required_values?
@value
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
#{klass_name}Base = #{full_klass_name}Base
end
EOC
end
@ -86,18 +74,13 @@ EOC
::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
plural_name ||= "#{name}s"
klass_name = Utils.to_class_name(name)
plural_klass_name = "DublinCore#{Utils.to_class_name(plural_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 #{klass_name} < #{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
class #{full_klass_name} < #{full_klass_name}Base
end
#{klass_name} = #{full_klass_name}
end
EOC
end
@ -106,47 +89,18 @@ EOC
class ChannelBase
include DublinCoreModel
remove_method(:date)
remove_method(:date=)
alias_method(:date, :dc_date)
alias_method(:date=, :dc_date=)
end
class ImageBase; include DublinCoreModel; end
class ItemsBase
class ItemBase
include DublinCoreModel
remove_method(:date)
remove_method(:date=)
alias_method(:date, :dc_date)
alias_method(:date=, :dc_date=)
end
end
class TextinputBase; include DublinCoreModel; end
class RSS10
class Channel
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
makers.each do |maker|
maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class Channel
DublinCoreModel.install_dublin_core(self)
end
@ -164,6 +118,7 @@ EOC
class Textinput
DublinCoreModel.install_dublin_core(self)
end
EOC
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
name = "#{RSS::IMAGE_PREFIX}_item"
klass.add_need_initialize_variable(name, "make_#{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
klass.def_classed_element(name)
end
def make_#{name}
self.class::#{Utils.to_class_name(name)}.new(@maker)
def self.install_image_item(klass)
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class ImageItem < ImageItemBase
DublinCoreModel.install_dublin_core(self)
end
EOC
end
class ImageItemBase
include Base
class ImageItemBase < Base
include Maker::DublinCoreModel
attr_accessor :about, :resource, :image_width, :image_height
@ -42,6 +36,15 @@ EOC
def have_required_values?
@about
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
@ -50,24 +53,18 @@ EOC
super
name = "#{RSS::IMAGE_PREFIX}_favicon"
klass.add_need_initialize_variable(name, "make_#{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
klass.def_classed_element(name)
end
def make_#{name}
self.class::#{Utils.to_class_name(name)}.new(@maker)
def self.install_image_favicon(klass)
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class ImageFavicon < ImageFaviconBase
DublinCoreModel.install_dublin_core(self)
end
EOC
end
class ImageFaviconBase
include Base
class ImageFaviconBase < Base
include Maker::DublinCoreModel
attr_accessor :about, :image_size
@ -79,6 +76,15 @@ EOC
def have_required_values?
@about and @image_size
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
@ -88,58 +94,18 @@ EOC
class ItemBase; include Maker::ImageItemModel; 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 Item
class ImageItem < ImageItemBase
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
ImageItemModel.install_image_item(self)
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

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)
super
::RSS::SyndicationModel::ELEMENTS.each do |element|
klass.add_need_initialize_variable(element)
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
::RSS::SyndicationModel::ELEMENTS.each do |name|
klass.def_other_element(name)
end
end
end

View file

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

View file

@ -8,57 +8,15 @@ module RSS
def self.append_features(klass)
super
name = "#{RSS::TRACKBACK_PREFIX}_ping"
klass.add_need_initialize_variable(name)
klass.add_other_element(name)
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)
klass.def_other_element("#{RSS::TRACKBACK_PREFIX}_ping")
klass.def_classed_elements("#{RSS::TRACKBACK_PREFIX}_about", "value",
"TrackBackAbouts")
end
def setup_#{name}(rss, current)
@#{name}.to_rss(rss, current)
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 TrackBackAboutsBase < Base
def_array_element("about", nil, "TrackBackAbout")
class TrackBackAboutBase < Base
attr_accessor :value
add_need_initialize_variable("value")
@ -71,6 +29,14 @@ module RSS
@value
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
@ -79,52 +45,17 @@ module RSS
class ItemBase; include TrackBackModel; end
end
class RSS10
makers.each do |maker|
maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
class Items
class Item
class TrackBackAbouts < TrackBackAboutsBase
class TrackBackAbout < TrackBackAboutBase
def to_rss(rss, current)
if resource
about = ::RSS::TrackBackModel10::TrackBackAbout.new(resource)
current.trackback_abouts << about
end
end
end
end
EOC
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

View file

@ -2,6 +2,7 @@ require "forwardable"
require "open-uri"
require "rss/rss"
require "rss/xml"
module RSS
@ -118,7 +119,7 @@ module RSS
return rss if rss.is_a?(::URI::Generic)
begin
URI(rss)
::URI.parse(rss)
rescue ::URI::Error
rss
end
@ -173,24 +174,28 @@ module RSS
class << self
@@setters = {}
@@accessor_bases = {}
@@registered_uris = {}
@@class_names = {}
# return the setter for the uri, tag_name pair, or nil.
def setter(uri, tag_name)
begin
@@setters[uri][tag_name]
rescue NameError
_getter = getter(uri, tag_name)
if _getter
"#{_getter}="
else
nil
end
end
def getter(uri, tag_name)
(@@accessor_bases[uri] || {})[tag_name]
end
# return the tag_names for setters associated with uri
def available_tags(uri)
begin
@@setters[uri].keys
@@accessor_bases[uri].keys
rescue NameError
[]
end
@ -223,8 +228,8 @@ module RSS
end
end
def install_get_text_element(uri, name, setter)
install_setter(uri, name, setter)
def install_get_text_element(uri, name, accessor_base)
install_accessor_base(uri, name, accessor_base)
def_get_text_element(uri, name, *get_file_and_line_from_caller(1))
end
@ -233,35 +238,31 @@ module RSS
end
private
# set the setter for the uri, tag_name pair
def install_setter(uri, tag_name, setter)
@@setters[uri] ||= {}
@@setters[uri][tag_name] = setter
# set the accessor for the uri, tag_name pair
def install_accessor_base(uri, tag_name, accessor_base)
@@accessor_bases[uri] ||= {}
@@accessor_bases[uri][tag_name] = accessor_base.chomp("=")
end
def def_get_text_element(uri, name, file, line)
register_uri(uri, name)
unless private_instance_methods(false).include?("start_#{name}")
module_eval(<<-EOT, file, line)
def start_#{name}(name, prefix, attrs, ns)
def def_get_text_element(uri, element_name, file, line)
register_uri(uri, element_name)
method_name = "start_#{element_name}"
unless private_method_defined?(method_name)
define_method(method_name) do |name, prefix, attrs, ns|
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)
else
start_else_element(name, prefix, attrs, ns)
end
end
EOT
__send__("private", "start_#{name}")
private(method_name)
end
end
end
end
module ListenerMixin
attr_reader :rss
attr_accessor :ignore_unknown_element
@ -271,13 +272,16 @@ module RSS
@rss = nil
@ignore_unknown_element = true
@do_validate = true
@ns_stack = [{}]
@ns_stack = [{"xml" => :xml}]
@tag_stack = [[]]
@text_stack = ['']
@proc_stack = []
@last_element = nil
@version = @encoding = @standalone = nil
@xml_stylesheets = []
@xml_child_mode = false
@xml_element = nil
@last_xml_element = nil
end
# set instance vars for version, encoding, standalone
@ -289,7 +293,7 @@ module RSS
if name == "xml-stylesheet"
params = parse_pi_content(content)
if params.has_key?("href")
@xml_stylesheets << XMLStyleSheet.new(*params)
@xml_stylesheets << XMLStyleSheet.new(params)
end
end
end
@ -311,12 +315,41 @@ module RSS
prefix, local = split_name(name)
@tag_stack.last.push([_ns(ns, prefix), local])
@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)
else
start_else_element(local, prefix, attrs, ns.dup)
end
end
end
def tag_end(name)
if DEBUG
@ -331,8 +364,12 @@ module RSS
end
def text(data)
if @xml_child_mode
@last_xml_element << data if @last_xml_element
else
@text_stack.last << data
end
end
private
def _ns(ns, prefix)
@ -354,7 +391,8 @@ module RSS
def start_else_element(local, prefix, attrs, ns)
class_name = self.class.class_name(_ns(ns, prefix), local)
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)
start_have_something_element(local, prefix, attrs, ns, next_class)
else
@ -377,19 +415,26 @@ module RSS
end
def check_ns(tag_name, prefix, ns, require_uri)
unless _ns(ns, prefix) == require_uri
if @do_validate
if _ns(ns, prefix) == require_uri
#ns.delete(prefix)
else
raise NSError.new(tag_name, prefix, require_uri)
else
# Force bind required URI with prefix
@ns_stack.last[prefix] = require_uri
end
end
end
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)
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)
else
if @do_validate and !@ignore_unknown_element
@ -397,7 +442,8 @@ module RSS
@last_element.tag_name)
end
end
}
end
@proc_stack.push(pr)
end
def start_have_something_element(tag_name, prefix, attrs, ns, klass)
@ -438,16 +484,32 @@ module RSS
previous = @last_element
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
@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
@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
@last_element.validate_for_stream(tags, @ignore_unknown_element)
end
@last_element = previous
}
end
@proc_stack.push(pr)
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)?)?
\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 << $7.to_f * 1000000 if $7
if $8
Time.utc(*datetime) - zone_offset($8)
usec = 0
usec = $7.to_f * 1000000 if $7
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
datetime << usec
Time.local(*datetime)
end
else
@ -25,8 +33,15 @@ class Time
end
end
unless instance_methods.include?("w3cdtf")
alias w3cdtf iso8601
unless method_defined?(:w3cdtf)
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
@ -37,7 +52,7 @@ require "rss/xml-stylesheet"
module RSS
VERSION = "0.1.6"
VERSION = "0.2.0"
URI = "http://purl.org/rss/1.0/"
@ -137,16 +152,25 @@ module RSS
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
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
add_need_initialize_variable(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|
<<-EOC
if @#{n}
@ -164,7 +188,7 @@ EOC
plural_name ||= "#{name}s"
add_have_children_element(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)
install_element(name, "s") do |n, elem_name|
@ -179,20 +203,26 @@ EOC
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
disp_name ||= name
self::ELEMENTS << name
add_need_initialize_variable(name)
install_model(tag_name, uri, occurs, name)
def_corresponded_attr_writer name, type, disp_name
convert_attr_reader name
def_corresponded_attr_writer(name, type, disp_name)
def_corresponded_attr_reader(name, type || :convert)
install_element(name) do |n, elem_name|
<<-EOC
if @#{n}
if respond_to?(:#{n}_content)
content = #{n}_content
else
content = @#{n}
end
if content
rv = "\#{indent}<#{elem_name}>"
value = html_escape(@#{n})
value = html_escape(content)
if need_convert
rv << convert(value)
else
@ -252,15 +282,99 @@ EOC
EOC
end
def inherit_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_inherit
convert(@#{attr})
end
def #{attr}
if @#{attr}
#{attr}_without_inherit
elsif @parent
@parent.#{attr}
else
nil
end
end
EOC
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}
if @converter
@converter.convert(@#{attr})
else
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
@ -270,8 +384,10 @@ EOC
def date_writer(name, type, disp_name=name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{name}=(new_value)
if new_value.nil? or new_value.kind_of?(Time)
if new_value.nil?
@#{name} = new_value
elsif new_value.kind_of?(Time)
@#{name} = new_value.dup
else
if @do_validate
begin
@ -283,7 +399,9 @@ EOC
@#{name} = nil
if /\\A\\s*\\z/ !~ new_value.to_s
begin
unless Date._parse(new_value, false).empty?
@#{name} = Time.parse(new_value)
end
rescue ArgumentError
end
end
@ -364,6 +482,68 @@ EOC
EOC
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)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{plural_name}
@ -379,10 +559,12 @@ EOC
end
def #{accessor_name}=(*args)
receiver = self.class.name
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. " \
"Use `#{plural_name} << XXX' instead of them.")
"Use `\#{receiver}\##{plural_name} << XXX' instead of them.")
if args.size == 1
@#{accessor_name}.push(args[0])
else
@ -394,10 +576,61 @@ EOC
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
include Utils
extend Utils::InheritedReader
include SetupMaker
INDENT = " "
@ -410,29 +643,31 @@ EOC
PLURAL_FORMS = {}
class << self
def must_call_validators
MUST_CALL_VALIDATORS
inherited_hash_reader("MUST_CALL_VALIDATORS")
end
def models
MODELS
inherited_array_reader("MODELS")
end
def get_attributes
GET_ATTRIBUTES
inherited_array_reader("GET_ATTRIBUTES")
end
def have_children_elements
HAVE_CHILDREN_ELEMENTS
inherited_array_reader("HAVE_CHILDREN_ELEMENTS")
end
def to_element_methods
TO_ELEMENT_METHODS
inherited_array_reader("TO_ELEMENT_METHODS")
end
def need_initialize_variables
NEED_INITIALIZE_VARIABLES
inherited_array_reader("NEED_INITIALIZE_VARIABLES")
end
def plural_forms
PLURAL_FORMS
inherited_hash_reader("PLURAL_FORMS")
end
def inherited_base
::RSS::Element
end
def inherited(klass)
klass.const_set("MUST_CALL_VALIDATORS", {})
@ -443,64 +678,42 @@ EOC
klass.const_set("NEED_INITIALIZE_VARIABLES", [])
klass.const_set("PLURAL_FORMS", {})
klass.module_eval(<<-EOC)
public
@tag_name = name.split(/::/).last
@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)
tag_name = klass.name.split(/::/).last
tag_name[0, 1] = tag_name[0, 1].downcase
klass.instance_variable_set("@tag_name", tag_name)
klass.instance_variable_set("@have_content", false)
end
def self.install_must_call_validator(prefix, uri)
MUST_CALL_VALIDATORS[uri] = prefix
def install_must_call_validator(prefix, uri)
self::MUST_CALL_VALIDATORS[uri] = prefix
end
def self.install_model(tag, uri, occurs=nil, getter=nil)
def install_model(tag, uri, occurs=nil, getter=nil, plural=false)
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
else
MODELS << [tag, uri, occurs, getter]
self::MODELS << [tag, uri, occurs, getter, plural]
end
end
def self.install_get_attribute(name, uri, required=true,
def install_get_attribute(name, uri, required=true,
type=nil, disp_name=nil,
element_name=nil)
disp_name ||= name
element_name ||= name
def_corresponded_attr_writer name, type, disp_name
convert_attr_reader name
writer_type, reader_type = type
def_corresponded_attr_writer name, writer_type, disp_name
def_corresponded_attr_reader name, reader_type
if type == :boolean and /^is/ =~ name
alias_method "\#{$POSTMATCH}?", name
alias_method "#{$POSTMATCH}?", name
end
GET_ATTRIBUTES << [name, uri, required, element_name]
self::GET_ATTRIBUTES << [name, uri, required, element_name]
add_need_initialize_variable(disp_name)
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
when :integer
integer_writer name, disp_name
@ -510,38 +723,67 @@ EOC
boolean_writer name, disp_name
when :w3cdtf, :rfc822, :rfc2822
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
attr_writer name
end
end
def self.content_setup(type=nil)
def_corresponded_attr_writer "content", type
convert_attr_reader :content
def def_corresponded_attr_reader(name, type=nil)
case type
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
end
def self.have_content?
def have_content?
@have_content
end
def self.add_have_children_element(variable_name, plural_name)
HAVE_CHILDREN_ELEMENTS << [variable_name, plural_name]
def add_have_children_element(variable_name, plural_name)
self::HAVE_CHILDREN_ELEMENTS << [variable_name, plural_name]
end
def self.add_to_element_method(method_name)
TO_ELEMENT_METHODS << method_name
def add_to_element_method(method_name)
self::TO_ELEMENT_METHODS << method_name
end
def self.add_need_initialize_variable(variable_name)
NEED_INITIALIZE_VARIABLES << variable_name
def add_need_initialize_variable(variable_name)
self::NEED_INITIALIZE_VARIABLES << variable_name
end
def self.add_plural_form(singular, plural)
PLURAL_FORMS[singular] = plural
end
EOC
def add_plural_form(singular, plural)
self::PLURAL_FORMS[singular] = plural
end
def required_prefix
@ -552,6 +794,10 @@ EOC
""
end
def need_parent?
false
end
def install_ns(prefix, uri)
if self::NSPOOL.has_key?(prefix)
raise OverlappedPrefixError.new(prefix)
@ -564,12 +810,16 @@ EOC
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
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
initialize_variables(attrs)
initialize_variables(attrs || {})
end
def tag_name
@ -599,9 +849,20 @@ EOC
end
end
def valid?(ignore_unknown_element=true)
validate(ignore_unknown_element)
true
rescue RSS::Error
false
end
def validate(ignore_unknown_element=true)
do_validate = @do_validate
@do_validate = true
validate_attribute
__validate(ignore_unknown_element)
ensure
@do_validate = do_validate
end
def validate_for_stream(tags, ignore_unknown_element=true)
@ -609,20 +870,15 @@ EOC
__validate(ignore_unknown_element, tags, false)
end
def setup_maker(maker)
target = maker_target(maker)
unless target.nil?
setup_maker_attributes(target)
setup_maker_element(target)
setup_maker_elements(target)
end
end
def to_s(need_convert=true, indent='')
if self.class.have_content?
return "" unless @content
return "" if !empty_content? and !content_is_set?
rv = tag(indent) do |next_indent|
h(@content)
if empty_content?
""
else
xmled_content
end
end
else
rv = tag(indent) do |next_indent|
@ -635,6 +891,44 @@ EOC
rv
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
def initialize_variables(attrs)
normalized_attrs = {}
@ -646,16 +940,16 @@ EOC
if value
__send__("#{variable_name}=", value)
else
instance_eval("@#{variable_name} = nil")
instance_variable_set("@#{variable_name}", nil)
end
end
initialize_have_children_elements
@content = "" if self.class.have_content?
@content = normalized_attrs["content"] if self.class.have_content?
end
def initialize_have_children_elements
self.class.have_children_elements.each do |variable_name, plural_name|
instance_eval("@#{variable_name} = []")
instance_variable_set("@#{variable_name}", [])
end
end
@ -665,8 +959,10 @@ EOC
attrs = collect_attrs
return "" if attrs.nil?
return "" unless have_required_elements?
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
content = block.call(next_indent)
@ -681,6 +977,7 @@ EOC
else
content = content.reject{|x| x.empty?}
if content.empty?
return "" if attrs.empty?
end_tag = "/>"
else
start_tag << ">\n"
@ -722,56 +1019,6 @@ EOC
''
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
rv = []
self.class.models.each do |name, uri, occurs, getter|
@ -787,10 +1034,10 @@ EOC
def _tags
rv = []
self.class.models.each do |name, uri, occurs, getter|
self.class.models.each do |name, uri, occurs, getter, plural|
value = __send__(getter)
next if value.nil?
if value.is_a?(Array)
if plural and value.is_a?(Array)
rv.concat([[uri, name]] * value.size)
else
rv << [uri, name]
@ -817,7 +1064,7 @@ EOC
must_call_validators.each do |uri, prefix|
_validate(ignore_unknown_element, tags[uri], uri)
meth = "#{prefix}_validate"
if respond_to?(meth, true)
if !prefix.empty? and respond_to?(meth, true)
__send__(meth, ignore_unknown_element, tags[uri], uri)
end
end
@ -825,9 +1072,11 @@ EOC
def validate_attribute
_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)
end
__send__("#{alias_name || a_name}=", value)
end
end
@ -843,6 +1092,7 @@ EOC
tags = tags.sort_by {|x| element_names.index(x) || tags_size}
end
_tags = tags.dup if tags
models.each_with_index do |model, i|
name, model_uri, occurs, getter = model
@ -933,6 +1183,27 @@ EOC
rv
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
module RootElementMixin
@ -940,16 +1211,23 @@ EOC
include XMLStyleSheetMixin
attr_reader :output_encoding
def initialize(rss_version, version=nil, encoding=nil, standalone=nil)
attr_reader :feed_type, :feed_subtype, :feed_version
attr_accessor :version, :encoding, :standalone
def initialize(feed_version, version=nil, encoding=nil, standalone=nil)
super()
@rss_version = rss_version
@feed_type = nil
@feed_subtype = nil
@feed_version = feed_version
@version = version || '1.0'
@encoding = encoding
@standalone = standalone
@output_encoding = nil
end
def feed_info
[@feed_type, @feed_version, @feed_subtype]
end
def output_encoding=(enc)
@output_encoding = enc
self.converter = Converter.new(@output_encoding, @encoding)
@ -964,25 +1242,48 @@ EOC
xss.setup_maker(maker)
end
setup_maker_elements(maker)
super
end
def to_xml(version=nil, &block)
if version.nil? or version == @rss_version
to_s
else
RSS::Maker.make(version) do |maker|
def to_feed(type, &block)
Maker.make(type) do |maker|
setup_maker(maker)
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
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)
rv = xmldecl + xml_stylesheet_pi
rv << super(indent, ns_declarations.merge(attrs), &block)
rv
rv = super(indent, ns_declarations.merge(attrs), &block)
return rv if rv.empty?
"#{xmldecl}#{xml_stylesheet_pi}#{rv}"
end
def xmldecl
@ -1004,12 +1305,8 @@ EOC
decls
end
def setup_maker_elements(maker)
channel.setup_maker(maker) if channel
image.setup_maker(maker) if image
textinput.setup_maker(maker) if textinput
super(maker)
def maker_target(target)
target
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|
install_date_element(name, SY_URI, "?",
"#{SY_PREFIX}_#{name}", 'w3cdtf', name)
"#{SY_PREFIX}_#{name}", 'w3cdtf',
"#{SY_PREFIX}:#{name}")
end
end
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
alias_method(:_sy_updatePeriod=, :sy_updatePeriod=)
def sy_updatePeriod=(new_value)
new_value = new_value.strip
validate_sy_updatePeriod(new_value) if @do_validate
self._sy_updatePeriod = new_value
end
end
EOC
end
private
@ -58,7 +61,7 @@ module RSS
SyndicationModel::ELEMENTS.uniq!
SyndicationModel::ELEMENTS.each do |full_name|
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

View file

@ -12,7 +12,7 @@ module RSS
%w(link).each do |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}"
end

View file

@ -4,14 +4,16 @@ module RSS
# Convert a name_with_underscores to CamelCase.
def to_class_name(name)
name.split(/_/).collect do |part|
name.split(/[_\-]/).collect do |part|
"#{part[0, 1].upcase}#{part[1..-1]}"
end.join("")
end
def get_file_and_line_from_caller(i=0)
file, line, = caller[i].split(':')
[file, line.to_i]
line = line.to_i
line += 1 if i.zero?
[file, line]
end
# escape '&', '"', '<' and '>' for use in HTML.
@ -33,5 +35,77 @@ module RSS
def element_initialize_arguments?(args)
[true, false].include?(args[0]) and args[1].is_a?(Hash)
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

View file

@ -35,6 +35,10 @@ module RSS
attr_accessor(*ATTRIBUTES)
attr_accessor(:do_validate)
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
ATTRIBUTES.each do |attr|
__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)
end
end
maker.items.each do |item|
item.title ||= "UNKNOWN"
item.link ||= "UNKNOWN"
end
maker.items.do_sort = true
maker.items.max_size = 15
end

View file

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

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

@ -56,9 +56,18 @@ ARGV.each do |fname|
rescue RSS::UnknownConversionMethodError
error($!) if verbose
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|
item.title ||= "Unknown"
channels[rss.channel.title] ||= []
channels[rss.channel.title] << item if item.description
end

View file

@ -29,16 +29,16 @@ ARGV.each do |fname|
read = false
begin
rss = RSS::Parser.parse(source)
puts "Re-read valid RSS: #{fname}"
puts "Re-read valid feed: #{fname}"
RSS::Parser.parse(rss.to_s)
read = true
rescue RSS::InvalidRSSError
error($!) if verbose
## do non validate parse for invalid RSS 1.0
## do non validate parse for invalid feed
begin
rss = RSS::Parser.parse(source, false)
rescue RSS::Error
## invalid RSS.
## invalid feed
error($!) if verbose
end
rescue RSS::Error
@ -46,9 +46,9 @@ ARGV.each do |fname|
end
if rss.nil?
puts "Invalid RSS: #{fname}"
puts "Invalid feed: #{fname}"
elsif !read
puts "Re-read invalid RSS: #{fname}"
puts "Re-read invalid feed: #{fname}"
begin
RSS::Parser.parse(rss.to_s)
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
error($!) if verbose
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|
if item.respond_to?(:pubDate) and item.pubDate
class << item
alias_method(:dc_date, :pubDate)
end
end
if item.respond_to?(:dc_date) and item.dc_date
items << [rss.channel, item]
end
items << [rss.channel, item] if item.dc_date
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 'rss-assertions'
require "rss"
module RSS
class TestCase < Test::Unit::TestCase
include ERB::Util
@ -42,6 +44,45 @@ module RSS
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
# This class isn't tested
end
@ -205,6 +246,82 @@ EOC
EOR
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)
attrs_str = attrs.collect do |name, value|
"#{h name}='#{h value}'"
@ -216,11 +333,60 @@ EOR
"<#{h elem_name} #{attrs_str}>\n#{contents_str}\n</#{h elem_name}>"
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
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)
about = "http://hoge.com"
title = "fugafuga"
link = "http://hoge.com"
link = "http://hoge.com/feed.xml"
description = "fugafugafugafuga"
language = "ja"
@ -231,6 +397,17 @@ EOR
maker.channel.language = language
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)
title = "fugafuga"
link = "http://hoge.com"
@ -263,6 +440,14 @@ EOR
item.link = link
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)
topics.each do |topic|
taxo_topic = target.taxo_topics.new_taxo_topic

View file

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

View file

@ -2,8 +2,6 @@ require "rexml/document"
require "rss-testcase"
require "rss/2.0"
module RSS
class TestRSS20Core < TestCase
@ -17,6 +15,7 @@ module RSS
standalone = false
rss = Rss.new(@rss_version, version, encoding, standalone)
setup_rss20(rss)
doc = REXML::Document.new(rss.to_s(false))
@ -48,7 +47,9 @@ module RSS
{:href => "a.css", :type => "text/css"},
],
].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
@ -253,6 +254,10 @@ module RSS
pubDate = Time.parse("Sat, 07 Sep 2002 00:00:01 GMT")
channel = Rss::Channel.new
channel.title = "title"
channel.link = "http://example.com/"
channel.description = "description"
item = Rss::Channel::Item.new
channel.items << item
@ -378,13 +383,28 @@ module RSS
rss = RSS::Parser.parse(make_sample_rss20)
assert_equal(rss.to_s, rss.to_xml)
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)
rss10 = rss.to_xml("1.0") do |maker|
maker.channel.about = "http://www.example.com/index.rdf"
end
rss10 = RSS::Parser.parse(rss10)
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

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
class TestDublinCore < TestCase
def setup
@prefix = "dc"
@uri = "http://purl.org/dc/elements/1.1/"
@rss10_parents = [%w(channel), %w(image), %w(item), %w(textinput)]
@parents = %w(channel image item textinput)
t = Time.iso8601("2000-01-01T12:00:05+00:00")
class << t
alias_method(:to_s, :iso8601)
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)}
@rss10_source = make_RDF(<<-EOR, {DC_PREFIX => DC_URI})
#{make_channel(DC_NODES)}
#{make_image(DC_NODES)}
#{make_item(DC_NODES)}
#{make_textinput(DC_NODES)}
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
def test_parser
assert_nothing_raised do
Parser.parse(@rss_source)
end
@elems.each do |tag, value|
rss = nil
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}
rss10_maker = Proc.new do |content, xmlns|
make_RDF(<<-EOR, xmlns)
#{make_channel(content)}
#{make_image(content)}
#{make_item(content)}
#{make_textinput(content)}
EOR
end
plural_reader = "dc_#{tag}" + (tag == :rights ? "es" : "s")
values = rss.channel.__send__(plural_reader).collect do |x|
assert_dc_parse(@rss10_source, @rss10_parents, false, &rss10_maker)
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
if val.kind_of?(String)
CGI.escapeHTML(val)
@ -79,15 +159,17 @@ EOR
end
assert_equal([value, value], values)
end
end
end
def test_singular_accessor
def assert_dc_singular_accessor(source, parents)
feed = Parser.parse(source)
new_value = "hoge"
@elems.each do |name, value|
@parents.each do |parent|
parsed_value = @rss.__send__(parent).__send__("dc_#{name}")
parents.each do |parent_readers|
parent = chain_reader(feed, parent_readers)
DC_ELEMENTS.each do |name, value|
parsed_value = parent.__send__("dc_#{name}")
if parsed_value.kind_of?(String)
parsed_value = CGI.escapeHTML(parsed_value)
end
@ -97,34 +179,40 @@ EOR
class << t
alias_method(:to_s, :iso8601)
end
@rss.__send__(parent).__send__("dc_#{name}=", t.iso8601)
assert_equal(t, @rss.__send__(parent).__send__("dc_#{name}"))
assert_equal(t, @rss.__send__(parent).date)
@rss.__send__(parent).date = value
assert_equal(value, @rss.__send__(parent).date)
assert_equal(value, @rss.__send__(parent).__send__("dc_#{name}"))
parent.__send__("dc_#{name}=", t.iso8601)
assert_equal(t, parent.__send__("dc_#{name}"))
if parent.class.method_defined?(:date_without_dc_date=)
assert_nil(parent.date)
else
@rss.__send__(parent).__send__("dc_#{name}=", new_value)
assert_equal(new_value,
@rss.__send__(parent).__send__("dc_#{name}"))
assert_equal(t, parent.date)
end
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
def test_plural_accessor
def assert_dc_plural_accessor(source, parents, check_backward_compatibility)
feed = Parser.parse(source)
new_value = "hoge"
@elems.each do |name, value|
@parents.each do |parent|
parsed_value = @rss.__send__(parent).__send__("dc_#{name}")
DC_ELEMENTS.each do |name, value|
parents.each do |parent_readers|
parent = chain_reader(feed, parent_readers)
parsed_value = parent.__send__("dc_#{name}")
if parsed_value.kind_of?(String)
parsed_value = CGI.escapeHTML(parsed_value)
end
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 = DublinCoreModel.const_get(klass_name)
if name == :date
@ -132,58 +220,60 @@ EOR
class << t
alias_method(:to_s, :iso8601)
end
elems = @rss.__send__(parent).__send__(plural_reader)
elems = parent.__send__(plural_reader)
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}
assert_equal([@rss.__send__(parent).__send__("dc_#{name}"), t],
values)
assert_equal([parent.__send__("dc_#{name}"), t], values)
else
elems = @rss.__send__(parent).__send__(plural_reader)
elems = parent.__send__(plural_reader)
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}
assert_equal([
@rss.__send__(parent).__send__("dc_#{name}"),
new_value
],
assert_equal([parent.__send__("dc_#{name}"), new_value],
values)
end
end
end
end
def test_to_s
@elems.each do |name, value|
excepted = "<#{@prefix}:#{name}>#{value}</#{@prefix}:#{name}>"
@parents.each do |parent|
assert_equal(excepted,
@rss.__send__(parent).__send__("dc_#{name}_elements"))
def assert_dc_to_s(source, parents, check_backward_compatibility,
targets=nil)
feed = Parser.parse(source)
DC_ELEMENTS.each do |name, value|
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
plural_suffix = dc_plural_suffix(name, check_backward_compatibility)
reader = "dc_#{name}#{plural_suffix}"
excepted = Array.new(2, excepted).join("\n")
@parents.each do |parent|
reader = "dc_#{name}" + (name == :rights ? "es" : "s")
elems = @rss.__send__(parent).__send__(reader)
parents.each do |parent_readers|
parent = chain_reader(feed, parent_readers)
elems = parent.__send__(reader)
klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}"
klass = DublinCoreModel.const_get(klass_name)
elems << klass.new(@rss.__send__(parent).__send__("dc_#{name}"))
assert_equal(excepted,
@rss.__send__(parent).__send__("dc_#{name}_elements"))
elems << klass.new(parent.__send__("dc_#{name}"))
assert_equal(excepted, parent.__send__("dc_#{name}_elements"))
end
end
REXML::Document.new(@rss_source).root.each_element do |parent|
if @parents.include?(parent.name)
targets ||= parents.collect do |parent_readers|
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|
if elem.namespace == @uri
if elem.namespace == DC_URI
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

View file

@ -11,7 +11,7 @@ module RSS
def setup
@prefix = "image"
@uri = "http://web.resource.org/rss/1.0/modules/image/"
@uri = "http://purl.org/rss/1.0/modules/image/"
@favicon_attrs = {
"rdf:about" => "http://www.kuro5hin.org/favicon.ico",
@ -75,6 +75,16 @@ EOR
Parser.parse(make_RDF(<<-EOR, @ns))
#{make_channel(@channel_nodes * 2)}
#{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
end
end
@ -163,19 +173,23 @@ EOR
def test_favicon_to_s
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_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)
end
def test_item_to_s
@rss.items.each_with_index do |item, i|
attrs, contents = @items[i]
expected_s = make_element("#{@prefix}:item", attrs, contents)
expected = REXML::Document.new(expected_s)
actual = REXML::Document.new(item.image_item.to_s(false, ""))
expected_xml = make_element("#{@prefix}:item", attrs, contents)
expected_xml = image_xmlns_container(expected_xml)
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)
@ -187,5 +201,14 @@ EOR
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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -498,6 +498,14 @@ EOR
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

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

View file

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

View file

@ -144,8 +144,10 @@ EOR
end
@topic_nodes.each_with_index do |node, i|
expected = REXML::Document.new(node).root
actual = REXML::Document.new(@rss.taxo_topics[i].to_s(true, "")).root
expected_xml = taxo_xmlns_container(node)
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)}
actual_elems = actual.reject {|x| x.is_a?(REXML::Text)}
expected_elems.sort! {|x, y| x.name <=> y.name}
@ -155,6 +157,16 @@ EOR
assert_equal(expected.attributes.sort, actual.attributes.sort)
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

View file

@ -12,7 +12,6 @@ require "rss/trackback"
module RSS
class TestToS < TestCase
def setup
@image_url = "http://example.com/foo.png"
@textinput_link = "http://example.com/search.cgi"
@ -436,5 +435,236 @@ module RSS
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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
#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_RELEASE_CODE 20071015
#define RUBY_RELEASE_CODE 20071021
#define RUBY_PATCHLEVEL 5000
#define RUBY_VERSION_MAJOR 1
@ -9,7 +9,7 @@
#define RUBY_VERSION_TEENY 6
#define RUBY_RELEASE_YEAR 2007
#define RUBY_RELEASE_MONTH 10
#define RUBY_RELEASE_DAY 15
#define RUBY_RELEASE_DAY 21
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];