atom-tools 2.0.3 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +63 -70
- data/bin/atom-post +1 -0
- data/lib/atom/element.rb +42 -4
- data/lib/atom/entry.rb +15 -40
- data/lib/atom/feed.rb +4 -0
- data/lib/atom/http.rb +1 -1
- data/spec/entry_spec.rb +353 -0
- data/spec/ext_spec.rb +42 -0
- data/spec/feed_spec.rb +20 -0
- data/spec/fixtures/entry-w-ext.xml +15 -0
- data/spec/fixtures/entry.xml +42 -0
- data/spec/fixtures/feed-w-ext.xml +33 -0
- data/spec/fixtures/service-w-xhtml-ns.xml +21 -0
- data/spec/fixtures/service.xml +36 -0
- data/spec/service_spec.rb +108 -0
- data/spec/spec_helper.rb +9 -0
- metadata +24 -9
data/Rakefile
CHANGED
@@ -7,81 +7,74 @@ require "spec/rake/spectask"
|
|
7
7
|
require "rake/clean"
|
8
8
|
|
9
9
|
NAME = "atom-tools"
|
10
|
-
VERS = "2.0.
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
VERS = "2.0.4"
|
11
|
+
|
12
|
+
task :default => [:spec]
|
13
|
+
|
14
|
+
# For historical reasons, atom-tools has both rspec specs and test/unit tests.
|
15
|
+
# This is silly (and there's a lot of duplication), but I have better things to
|
16
|
+
# do than rewrite the tests.
|
17
|
+
#
|
18
|
+
# Ideally all the tests should be runnable with one command, but for now you
|
19
|
+
# have to run "rake test" and "rake spec"
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
# spec task
|
22
|
+
desc 'Run all specs (see also "test" task)'
|
23
|
+
Spec::Rake::SpecTask.new('spec')
|
24
|
+
|
25
|
+
# test task
|
26
|
+
Rake::TestTask.new do |t|
|
27
|
+
t.libs << "test"
|
28
|
+
t.test_files = FileList['test/test*.rb']
|
29
|
+
t.verbose = true
|
29
30
|
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
spec = Gem::Specification.new do |s|
|
37
|
-
s.name = pkg_name
|
38
|
-
s.version = pkg_version
|
39
|
-
s.platform = Gem::Platform::RUBY
|
40
|
-
s.author = author
|
41
|
-
s.email = 'whateley@gmail.com'
|
42
|
-
s.homepage = 'http://code.necronomicorp.com/atom-tools'
|
43
|
-
s.rubyforge_project = 'ibes'
|
44
|
-
s.summary = summary
|
45
|
-
s.test_file = test_file
|
46
|
-
s.has_rdoc = true
|
47
|
-
s.extra_rdoc_files = [ "README" ]
|
48
|
-
dependencies.each do |dep|
|
49
|
-
s.add_dependency(*dep)
|
50
|
-
end
|
51
|
-
s.files = %w(COPYING README Rakefile setup.rb) +
|
52
|
-
Dir.glob("{bin,doc,test,lib}/**/*") +
|
53
|
-
Dir.glob("ext/**/*.{h,c,rb}") +
|
54
|
-
Dir.glob("examples/**/*.rb") +
|
55
|
-
Dir.glob("tools/*.rb")
|
56
|
-
|
57
|
-
s.require_path = "lib"
|
58
|
-
s.extensions = FileList["ext/**/extconf.rb"].to_a
|
59
|
-
|
60
|
-
s.bindir = "bin"
|
61
|
-
end
|
62
|
-
|
63
|
-
Rake::GemPackageTask.new(spec) do |p|
|
64
|
-
p.gem_spec = spec
|
65
|
-
p.need_tar = true
|
66
|
-
end
|
67
|
-
|
68
|
-
task :install do
|
69
|
-
sh %{rake package}
|
70
|
-
sh %{gem install pkg/#{pkg_name}-#{pkg_version}}
|
71
|
-
end
|
32
|
+
Rake::RDocTask.new do |rdoc|
|
33
|
+
rdoc.title = 'atom-tools documentation'
|
34
|
+
rdoc.main = 'README'
|
35
|
+
rdoc.rdoc_files.include 'README', 'lib/**/*.rb'
|
36
|
+
rdoc.rdoc_dir = 'doc'
|
72
37
|
end
|
73
38
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
39
|
+
spec = Gem::Specification.new do |s|
|
40
|
+
s.name = NAME
|
41
|
+
s.version = VERS
|
42
|
+
s.platform = Gem::Platform::RUBY
|
43
|
+
s.author = "Brendan Taylor"
|
44
|
+
s.email = 'whateley@gmail.com'
|
45
|
+
s.homepage = 'http://github.com/bct/atom-tools/wikis'
|
46
|
+
|
47
|
+
s.rubyforge_project = 'ibes'
|
48
|
+
|
49
|
+
s.summary = 'Tools for working with Atom Entries, Feeds and Collections.'
|
50
|
+
s.description = 'atom-tools is an all-in-one Atom library. It parses and builds Atom (RFC 4287) entries and feeds, and manipulates Atom Publishing Protocol (RFC 5023) Collections.
|
51
|
+
|
52
|
+
It also comes with a set of commandline utilities for working with AtomPub Collections.
|
53
|
+
|
54
|
+
It is not the fastest Ruby Atom library, but it is comprehensive and makes handling extensions to the Atom format very easy.'
|
55
|
+
|
56
|
+
s.test_file = "test/runtests.rb" # TODO: should have the spec here instead?
|
57
|
+
s.has_rdoc = true
|
58
|
+
s.extra_rdoc_files = [ "README" ]
|
59
|
+
|
60
|
+
s.files = %w(COPYING README Rakefile setup.rb) +
|
61
|
+
Dir.glob("{bin,doc,test,spec,lib}/**/*") +
|
62
|
+
Dir.glob("ext/**/*.{h,c,rb}") +
|
63
|
+
Dir.glob("examples/**/*.rb") +
|
64
|
+
Dir.glob("tools/*.rb")
|
65
|
+
|
66
|
+
s.require_path = "lib"
|
67
|
+
s.extensions = FileList["ext/**/extconf.rb"].to_a
|
68
|
+
|
69
|
+
s.bindir = "bin"
|
80
70
|
end
|
81
71
|
|
82
|
-
|
83
|
-
|
72
|
+
Rake::GemPackageTask.new(spec) do |p|
|
73
|
+
p.gem_spec = spec
|
74
|
+
p.need_tar = true
|
75
|
+
end
|
84
76
|
|
85
|
-
|
86
|
-
|
87
|
-
|
77
|
+
task :install do
|
78
|
+
sh %{rake package}
|
79
|
+
sh %{gem install pkg/#{NAME}-#{VERS}}
|
80
|
+
end
|
data/bin/atom-post
CHANGED
data/lib/atom/element.rb
CHANGED
@@ -507,7 +507,7 @@ module Atom # :nodoc:
|
|
507
507
|
@attrs
|
508
508
|
end
|
509
509
|
|
510
|
-
self.class.
|
510
|
+
self.class.run_initters do |init|
|
511
511
|
self.instance_eval &init
|
512
512
|
end
|
513
513
|
|
@@ -521,9 +521,8 @@ module Atom # :nodoc:
|
|
521
521
|
@on_init << block
|
522
522
|
end
|
523
523
|
|
524
|
-
def self.
|
525
|
-
@on_init
|
526
|
-
@on_init.each &block
|
524
|
+
def self.run_initters &block
|
525
|
+
@on_init.each(&block) if @on_init
|
527
526
|
end
|
528
527
|
|
529
528
|
# appends an element named 'name' in namespace 'ns' to 'root'
|
@@ -644,4 +643,43 @@ module Atom # :nodoc:
|
|
644
643
|
class Contributor < Atom::Person
|
645
644
|
is_atom_element :contributor
|
646
645
|
end
|
646
|
+
|
647
|
+
module HasLinks
|
648
|
+
def HasLinks.included(klass)
|
649
|
+
klass.atom_elements :link, :links, Atom::Link
|
650
|
+
end
|
651
|
+
|
652
|
+
def find_link(criteria)
|
653
|
+
self.links.find do |l|
|
654
|
+
criteria.all? { |k,v| l.send(k) == v }
|
655
|
+
end
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
module HasCategories
|
660
|
+
def HasCategories.included(klass)
|
661
|
+
klass.atom_elements :category, :categories, Atom::Category
|
662
|
+
end
|
663
|
+
|
664
|
+
# categorize the entry with each of an array or a space-separated
|
665
|
+
# string
|
666
|
+
def tag_with(tags, delimiter = ' ')
|
667
|
+
return if not tags or tags.empty?
|
668
|
+
|
669
|
+
tag_list = unless tags.is_a?(String)
|
670
|
+
tags
|
671
|
+
else
|
672
|
+
tags = tags.split(delimiter)
|
673
|
+
tags.map! { |t| t.strip }
|
674
|
+
tags.reject! { |t| t.empty? }
|
675
|
+
tags.uniq
|
676
|
+
end
|
677
|
+
|
678
|
+
tag_list.each do |tag|
|
679
|
+
unless categories.any? { |c| c.term == tag }
|
680
|
+
categories.new :term => tag
|
681
|
+
end
|
682
|
+
end
|
683
|
+
end
|
684
|
+
end
|
647
685
|
end
|
data/lib/atom/entry.rb
CHANGED
@@ -3,7 +3,21 @@ require "rexml/document"
|
|
3
3
|
require "atom/element"
|
4
4
|
require "atom/text"
|
5
5
|
|
6
|
+
require 'atom/feed'
|
7
|
+
|
6
8
|
module Atom
|
9
|
+
# this is just a forward declaration since atom/entry includes atom/feed and vice-versa.
|
10
|
+
class Feed < Atom::Element # :nodoc:
|
11
|
+
end
|
12
|
+
|
13
|
+
class Source < Atom::Feed
|
14
|
+
is_atom_element :source
|
15
|
+
|
16
|
+
# TODO: this shouldn't be necessary, but on_init doesn't get inherited the
|
17
|
+
# way I would like it to.
|
18
|
+
@on_init = Atom::Feed.instance_variable_get '@on_init'
|
19
|
+
end
|
20
|
+
|
7
21
|
class Control < Atom::Element
|
8
22
|
attr_accessor :draft
|
9
23
|
|
@@ -21,45 +35,6 @@ module Atom
|
|
21
35
|
end
|
22
36
|
end
|
23
37
|
|
24
|
-
module HasCategories
|
25
|
-
def HasCategories.included(klass)
|
26
|
-
klass.atom_elements :category, :categories, Atom::Category
|
27
|
-
end
|
28
|
-
|
29
|
-
# categorize the entry with each of an array or a space-separated
|
30
|
-
# string
|
31
|
-
def tag_with(tags, delimiter = ' ')
|
32
|
-
return if not tags or tags.empty?
|
33
|
-
|
34
|
-
tag_list = unless tags.is_a?(String)
|
35
|
-
tags
|
36
|
-
else
|
37
|
-
tags = tags.split(delimiter)
|
38
|
-
tags.map! { |t| t.strip }
|
39
|
-
tags.reject! { |t| t.empty? }
|
40
|
-
tags.uniq
|
41
|
-
end
|
42
|
-
|
43
|
-
tag_list.each do |tag|
|
44
|
-
unless categories.any? { |c| c.term == tag }
|
45
|
-
categories.new :term => tag
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
module HasLinks
|
52
|
-
def HasLinks.included(klass)
|
53
|
-
klass.atom_elements :link, :links, Atom::Link
|
54
|
-
end
|
55
|
-
|
56
|
-
def find_link(criteria)
|
57
|
-
self.links.find do |l|
|
58
|
-
criteria.all? { |k,v| l.send(k) == v }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
38
|
# An individual entry in a feed. As an Atom::Element, it can be
|
64
39
|
# manipulated using accessors for each of its child elements. You
|
65
40
|
# should be able to set them using an instance of any class that
|
@@ -94,7 +69,7 @@ module Atom
|
|
94
69
|
|
95
70
|
atom_element :rights, Atom::Rights
|
96
71
|
|
97
|
-
|
72
|
+
atom_element :source, Atom::Source
|
98
73
|
|
99
74
|
atom_time :published
|
100
75
|
atom_time :updated
|
data/lib/atom/feed.rb
CHANGED
data/lib/atom/http.rb
CHANGED
data/spec/entry_spec.rb
ADDED
@@ -0,0 +1,353 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'atom/entry'
|
4
|
+
|
5
|
+
module TestsXML
|
6
|
+
def read_entry_xml xpath
|
7
|
+
REXML::XPath.first(@entry.to_xml, xpath, { 'atom' => Atom::NS, 'app' => Atom::PP_NS })
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Atom::Entry do
|
12
|
+
describe 'when parsing' do
|
13
|
+
before(:each) do
|
14
|
+
@entry = Atom::Entry.parse(fixtures(:entry))
|
15
|
+
@empty_entry = '<entry xmlns="http://www.w3.org/2005/Atom" />'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should read & parse input from an IO object' do
|
19
|
+
input = mock('IO')
|
20
|
+
input.should_receive(:read).and_return(@empty_entry)
|
21
|
+
Atom::Entry.parse(input).should be_an_instance_of(Atom::Entry)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should read & parse input from a string' do
|
25
|
+
input = mock('string')
|
26
|
+
input.should_receive(:to_s).and_return(@empty_entry)
|
27
|
+
Atom::Entry.parse(input).should be_an_instance_of(Atom::Entry)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should raise ParseError when invalid entry' do
|
31
|
+
lambda { Atom::Entry.parse('<entry/>') }.should raise_error(Atom::ParseError)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should parse title element correctly' do
|
35
|
+
@entry.title.should be_is_a(Atom::Text)
|
36
|
+
@entry.title['type'].should == 'text'
|
37
|
+
@entry.title.to_s.should == 'Atom draft-07 snapshot'
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should parse id element correctly' do
|
41
|
+
@entry.id.should == 'tag:example.org,2003:3.2397'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should parse updated element correctly' do
|
45
|
+
@entry.updated.should == Time.parse('2005-07-31T12:29:29Z')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should parse published element correctly' do
|
49
|
+
@entry.published.should == Time.parse('2003-12-13T08:29:29-04:00')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should parse app:edited element correctly' do
|
53
|
+
@entry.edited.should == Time.parse('2005-07-31T12:29:29Z')
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should parse app:control/draft element correctly' do
|
57
|
+
@entry.draft?.should be_true
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should parse rights element correctly' do
|
61
|
+
@entry.rights.should be_is_a(Atom::Text)
|
62
|
+
@entry.rights['type'].should == 'text'
|
63
|
+
@entry.rights.to_s.should == 'Copyright (c) 2003, Mark Pilgrim'
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should parse author element correctly' do
|
67
|
+
@entry.authors.length.should == 1
|
68
|
+
@entry.authors.first.name.should == 'Mark Pilgrim'
|
69
|
+
@entry.authors.first.email.should == 'f8dy@example.com'
|
70
|
+
@entry.authors.first.uri.should == 'http://example.org/'
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should parse contributor element correctly' do
|
74
|
+
@entry.contributors.length.should == 2
|
75
|
+
@entry.contributors.first.name.should == 'Sam Ruby'
|
76
|
+
@entry.contributors[1].name.should == 'Joe Gregorio'
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should parse content element correctly' do
|
80
|
+
@entry.content.should be_an_instance_of(Atom::Content)
|
81
|
+
@entry.content['type'].should == 'xhtml'
|
82
|
+
@entry.content.base.should == 'http://diveintomark.org/'
|
83
|
+
@entry.content.to_s.strip.should == '<p><i>[Update: The Atom draft is finished.]</i></p>'
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should parse summary element correctly' do
|
87
|
+
@entry.summary['type'].should == 'text'
|
88
|
+
@entry.summary.to_s.should == 'Some text.'
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should parse links element correctly' do
|
92
|
+
@entry.links.length.should == 2
|
93
|
+
alternates = @entry.links.select { |l| l['rel'] == 'alternate' }
|
94
|
+
alternates.length.should == 1
|
95
|
+
alternates.first['href'].should == 'http://example.org/2005/04/02/atom'
|
96
|
+
alternates.first['type'].should == 'text/html'
|
97
|
+
@entry.links.last['rel'].should == 'enclosure'
|
98
|
+
@entry.links.last['href'].should == 'http://example.org/audio/ph34r_my_podcast.mp3'
|
99
|
+
@entry.links.last['type'].should == 'audio/mpeg'
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should parse category element correctly' do
|
103
|
+
@entry.categories.first['term'].should == 'ann'
|
104
|
+
@entry.categories.first['scheme'].should == 'http://example.org/cats'
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should parse source element correctly' do
|
108
|
+
@entry.source.title.to_s.should == 'Atom Sample Feed'
|
109
|
+
@entry.source.id.should == 'tag:example.org,2003:/'
|
110
|
+
|
111
|
+
@entry.source.links.length.should == 1
|
112
|
+
@entry.source.links.first.rel == 'self'
|
113
|
+
|
114
|
+
@entry.source.authors.length.should == 0
|
115
|
+
|
116
|
+
@entry.source.contributors.length.should == 1
|
117
|
+
@entry.source.contributors.first.name == 'Mark Pilgrim'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'title element' do
|
122
|
+
before(:each) do
|
123
|
+
@entry = Atom::Entry.new
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'should be nil if not defined' do
|
127
|
+
@entry.title.should be_nil
|
128
|
+
|
129
|
+
@entry.title.to_s.should == ''
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should accept a simple string' do
|
133
|
+
@entry.title = '<clever thing here>'
|
134
|
+
|
135
|
+
@entry.title.type.should == 'text'
|
136
|
+
|
137
|
+
@entry.title.to_s.should == '<clever thing here>'
|
138
|
+
@entry.title.html.should =~ /^<clever thing/
|
139
|
+
@entry.title.to_xml.to_s.should =~ /<clever thing/
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should accept an HTML string' do
|
143
|
+
@entry.title = 'even <em>cleverer</em>'
|
144
|
+
@entry.title.type = 'html'
|
145
|
+
|
146
|
+
@entry.title.type.should == 'html'
|
147
|
+
|
148
|
+
@entry.title.to_s.should =~ /even <em>clever/
|
149
|
+
@entry.title.html.should =~ /even <em>clever/
|
150
|
+
@entry.title.to_xml.to_s.should =~ /even <em/
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should accept an XHTML string' do
|
154
|
+
@entry.title = 'the <strong>cleverest</strong>'
|
155
|
+
@entry.title.type = 'xhtml'
|
156
|
+
|
157
|
+
@entry.title.to_xml.to_s.should =~ /w3.org\/1999\/xhtml.>the <strong>/
|
158
|
+
@entry.title.html.should =~ /the <strong>cleverest/
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should reject an ill-formed XHTML string' do
|
162
|
+
@entry.title = 'the <strong>cleverest'
|
163
|
+
lambda { @entry.title.type = 'xhtml' }.should raise_error(Atom::ParseError)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should accept something like Atom::Text' do
|
167
|
+
title = Atom::Title.new '<3'
|
168
|
+
|
169
|
+
@entry.title = title
|
170
|
+
@entry.title.type.should == 'text'
|
171
|
+
|
172
|
+
@entry.title.to_xml.to_s.should =~ /<3/
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe 'updated element' do
|
177
|
+
before(:each) do
|
178
|
+
@entry = Atom::Entry.new
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should be nil if not defined' do
|
182
|
+
@entry.updated.should be_nil
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'should be definable' do
|
186
|
+
@entry.updated = '1990-04-07'
|
187
|
+
@entry.updated.should == Time.parse('1990-04-07')
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should be an xsd:DateTime' do
|
191
|
+
@entry.updated = '1990-04-07'
|
192
|
+
@entry.updated.to_s.should =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'should be declarable as updated using #updated!' do
|
196
|
+
@entry.updated!
|
197
|
+
@entry.updated.should > Time.parse('1990-04-07')
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe 'app:edited element' do
|
202
|
+
include TestsXML
|
203
|
+
|
204
|
+
before(:each) do
|
205
|
+
@entry = Atom::Entry.new
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'should be nil if not defined' do
|
209
|
+
@entry.edited.should be_nil
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'should be definable' do
|
213
|
+
@entry.edited = '1990-04-07'
|
214
|
+
@entry.edited.should == Time.parse('1990-04-07')
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should be an xsd:DateTime' do
|
218
|
+
@entry.edited = '1990-04-07'
|
219
|
+
@entry.edited.to_s.should =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'should have APP namespace' do
|
223
|
+
@entry.edited = '1990-04-07'
|
224
|
+
read_entry_xml('app:edited').namespace.should == Atom::PP_NS
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'should be declarable as edited using #edited!' do
|
228
|
+
@entry.edited!
|
229
|
+
@entry.edited.should > Time.parse('1990-04-07')
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
describe 'category element' do
|
234
|
+
before(:each) do
|
235
|
+
@entry = Atom::Entry.new
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'should have no category on intializing' do
|
239
|
+
@entry.categories.should be_empty
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'should increase total count when adding a new category' do
|
243
|
+
@count = @entry.categories.length
|
244
|
+
@entry.categories.new['term'] = 'foo'
|
245
|
+
@entry.categories.length.should == @count + 1
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'should find category' do
|
249
|
+
category = @entry.categories.new
|
250
|
+
category['scheme'] = 'http://example.org/categories'
|
251
|
+
category['term'] = 'bar'
|
252
|
+
@entry.categories.select { |c| c['scheme'] == 'http://example.org/categories' }.should == [category]
|
253
|
+
end
|
254
|
+
|
255
|
+
describe 'when using tags' do
|
256
|
+
before(:each) do
|
257
|
+
@tags = %w(chunky bacon ruby)
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'should set categories from an array of tags' do
|
261
|
+
@entry.tag_with(@tags)
|
262
|
+
@entry.categories.length.should == 3
|
263
|
+
@tags.each { |tag| @entry.categories.any? { |c| c['term'] == tag }.should be_true }
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'should set categories from a space-sperated string of tags' do
|
267
|
+
@entry.tag_with(@tags.join(' '))
|
268
|
+
@entry.categories.length.should == 3
|
269
|
+
@tags.each { |tag| @entry.categories.any? { |c| c['term'] == tag }.should be_true }
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'should be possible to specify the delimiter when passing tags as a string' do
|
273
|
+
@entry.tag_with(@tags.join(','), ',')
|
274
|
+
@entry.categories.length.should == 3
|
275
|
+
@tags.each { |tag| @entry.categories.any? { |c| c['term'] == tag }.should be_true }
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'should create a category only once' do
|
279
|
+
@entry.tag_with(@tags)
|
280
|
+
@entry.tag_with(@tags.first)
|
281
|
+
@entry.categories.length.should == 3
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe 'edit url' do
|
287
|
+
before(:each) do
|
288
|
+
@entry = Atom::Entry.new
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'should be nil on initializing' do
|
292
|
+
@entry.edit_url.should be_nil
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'should be easily definable' do
|
296
|
+
@entry.edit_url = 'http://example.org/entries/foo'
|
297
|
+
@entry.edit_url.should == 'http://example.org/entries/foo'
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'should not erase other links' do
|
301
|
+
link = @entry.links.new :rel => 'related', :href => 'http://example.org'
|
302
|
+
|
303
|
+
@entry.edit_url = 'http://example.com/entries/foo'
|
304
|
+
@entry.links.length.should == 2
|
305
|
+
@entry.links.should include(link)
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'should accept a URI object' do
|
309
|
+
@entry.edit_url = URI.parse('http://example.com/entries/foo')
|
310
|
+
@entry.to_s.should =~ /example.com\/entries/
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
describe 'draft element' do
|
315
|
+
include TestsXML
|
316
|
+
|
317
|
+
before(:each) do
|
318
|
+
@entry = Atom::Entry.new
|
319
|
+
end
|
320
|
+
|
321
|
+
it 'should not be a draft by default' do
|
322
|
+
@entry.should_not be_draft
|
323
|
+
end
|
324
|
+
|
325
|
+
it 'should be definable using draft=' do
|
326
|
+
@entry.draft = true
|
327
|
+
@entry.should be_draft
|
328
|
+
@entry.draft = false
|
329
|
+
@entry.should_not be_draft
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'should be declarable as a draft using #draft!' do
|
333
|
+
@entry.draft!
|
334
|
+
@entry.should be_draft
|
335
|
+
end
|
336
|
+
|
337
|
+
it 'should have APP namespace' do
|
338
|
+
@entry.draft!
|
339
|
+
read_entry_xml('app:control/app:draft').namespace.should == Atom::PP_NS
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
|
344
|
+
describe 'extensions' do
|
345
|
+
before(:each) do
|
346
|
+
@entry = Atom::Entry.parse(fixtures('entry-w-ext'))
|
347
|
+
end
|
348
|
+
|
349
|
+
it 'should preserve namespaces' do
|
350
|
+
@entry.to_s.should =~ /purl/
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
data/spec/ext_spec.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'atom/entry'
|
4
|
+
|
5
|
+
module Atom
|
6
|
+
THR_NS = "http://purl.org/syndication/thread/1.0"
|
7
|
+
SLUG_NS = 'http://example.org/ns/slug'
|
8
|
+
|
9
|
+
class InReplyTo < Atom::Element
|
10
|
+
is_element THR_NS, :"in-reply-to"
|
11
|
+
|
12
|
+
atom_attrb :ref
|
13
|
+
atom_attrb :href
|
14
|
+
atom_attrb :type
|
15
|
+
atom_attrb :source
|
16
|
+
end
|
17
|
+
|
18
|
+
class Entry
|
19
|
+
attrb ['sl', SLUG_NS], 'slug'
|
20
|
+
element ['thr', THR_NS], :"in-reply-to", InReplyTo
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Atom::Entry do
|
25
|
+
it 'should correctly write extension attributes' do
|
26
|
+
entry = Atom::Entry.new
|
27
|
+
entry.slug = 'hallo'
|
28
|
+
|
29
|
+
entry.to_s.should =~ /sl:slug/
|
30
|
+
entry.to_s.should =~ /xmlns:sl='#{Atom::SLUG_NS}'/
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'in-reply-to' do
|
34
|
+
it 'should be written with the correct namespace' do
|
35
|
+
entry = Atom::Entry.new
|
36
|
+
entry.in_reply_to = { :ref => 'http://example.org/some-entry' }
|
37
|
+
|
38
|
+
entry.to_s.should =~ /ref='http:\/\/example.org/
|
39
|
+
entry.to_s.should =~ Regexp.new(Atom::THR_NS)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/feed_spec.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'atom/feed'
|
4
|
+
|
5
|
+
describe Atom::Entry do
|
6
|
+
describe 'extensions' do
|
7
|
+
before(:each) do
|
8
|
+
@feed = Atom::Feed.parse(fixtures('feed-w-ext'))
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should preserve namespaces' do
|
12
|
+
@feed.to_s.should =~ /purl/
|
13
|
+
|
14
|
+
feed2 = Atom::Feed.new
|
15
|
+
feed2.merge! @feed
|
16
|
+
|
17
|
+
feed2.to_s.should =~ /purl/
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<entry xmlns="http://www.w3.org/2005/Atom"
|
2
|
+
xml:base='http://www.example.org/'
|
3
|
+
xmlns:thr='http://purl.org/syndication/thread/1.0'
|
4
|
+
xml:lang='en-us'>
|
5
|
+
<title>Extendy</title>
|
6
|
+
<link rel='replies' thr:count='2' type='application/xhtml+xml' href='Extendy#comments' />
|
7
|
+
<id>http://www.example.org/Extendy.atom</id>
|
8
|
+
<published>2008-03-15T02:00:00-07:00</published>
|
9
|
+
<updated>2008-03-15T18:10:25-07:00</updated>
|
10
|
+
<content type='xhtml'>
|
11
|
+
<div xmlns='http://www.w3.org/1999/xhtml'>
|
12
|
+
<p>Extensions ahoy!</p>
|
13
|
+
</div>
|
14
|
+
</content>
|
15
|
+
</entry>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<entry xmlns="http://www.w3.org/2005/Atom"
|
2
|
+
xmlns:app="http://www.w3.org/2007/app">
|
3
|
+
<title>Atom draft-07 snapshot</title>
|
4
|
+
<link rel="alternate" type="text/html"
|
5
|
+
href="http://example.org/2005/04/02/atom"/>
|
6
|
+
<link rel="enclosure" type="audio/mpeg" length="1337"
|
7
|
+
href="http://example.org/audio/ph34r_my_podcast.mp3"/>
|
8
|
+
<source>
|
9
|
+
<title>Atom Sample Feed</title>
|
10
|
+
<id>tag:example.org,2003:/</id>
|
11
|
+
<link rel="self" href="http://example.org/feed"/>
|
12
|
+
<contributor>
|
13
|
+
<name>Mark Pilgrim</name>
|
14
|
+
</contributor>
|
15
|
+
</source>
|
16
|
+
<rights>Copyright (c) 2003, Mark Pilgrim</rights>
|
17
|
+
<id>tag:example.org,2003:3.2397</id>
|
18
|
+
<updated>2005-07-31T12:29:29Z</updated>
|
19
|
+
<published>2003-12-13T08:29:29-04:00</published>
|
20
|
+
<app:edited>2005-07-31T12:29:29Z</app:edited>
|
21
|
+
<app:control><app:draft>yes</app:draft></app:control>
|
22
|
+
<author>
|
23
|
+
<name>Mark Pilgrim</name>
|
24
|
+
<uri>http://example.org/</uri>
|
25
|
+
<email>f8dy@example.com</email>
|
26
|
+
</author>
|
27
|
+
<contributor>
|
28
|
+
<name>Sam Ruby</name>
|
29
|
+
</contributor>
|
30
|
+
<contributor>
|
31
|
+
<name>Joe Gregorio</name>
|
32
|
+
</contributor>
|
33
|
+
<summary>Some text.</summary>
|
34
|
+
<category scheme="http://example.org/cats" term="ann" />
|
35
|
+
<content type="xhtml" xml:lang="en"
|
36
|
+
xml:base="http://diveintomark.org/">
|
37
|
+
<div xmlns="http://www.w3.org/1999/xhtml">
|
38
|
+
<p><i>[Update: The Atom draft is finished.]</i></p>
|
39
|
+
</div>
|
40
|
+
</content>
|
41
|
+
</entry>
|
42
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<feed xmlns='http://www.w3.org/2005/Atom'
|
2
|
+
xmlns:thr='http://purl.org/syndication/thread/1.0'
|
3
|
+
xml:base='http://www.tbray.org/ongoing/ongoing.atom'
|
4
|
+
xml:lang='en-us'>
|
5
|
+
<title>ongoing</title>
|
6
|
+
<id>http://www.tbray.org/ongoing/</id>
|
7
|
+
<link href='./' />
|
8
|
+
<link rel='self' href='' />
|
9
|
+
<link rel='replies' thr:count='101' href='/home/tbray.org/www/html/ongoing/comments.atom' />
|
10
|
+
<logo>rsslogo.jpg</logo>
|
11
|
+
<icon>/favicon.ico</icon>
|
12
|
+
<updated>2008-03-17T02:04:49-07:00</updated>
|
13
|
+
<author><name>Tim Bray</name></author>
|
14
|
+
<subtitle>ongoing fragmented essay by Tim Bray</subtitle>
|
15
|
+
<rights>All content written by Tim Bray and photos by Tim Bray Copyright Tim Bray, some rights reserved, see /ongoing/misc/Copyright</rights>
|
16
|
+
<generator uri='/misc/Colophon'>Generated from XML source code using Perl, Expat, Emacs, Mysql, Ruby, Java, and ImageMagick. Industrial-strength technology, baby.</generator>
|
17
|
+
<entry xml:base='When/200x/2008/03/13/'>
|
18
|
+
<title>Maui Bound</title>
|
19
|
+
<link href='Maui' />
|
20
|
+
<link rel='replies' thr:count='1' type='application/xhtml+xml' href='Maui#comments' />
|
21
|
+
<id>http://www.tbray.org/ongoing/When/200x/2008/03/13/Maui</id>
|
22
|
+
<published>2008-03-13T02:00:00-07:00</published>
|
23
|
+
<updated>2008-03-13T17:23:47-07:00</updated>
|
24
|
+
<category scheme='http://www.tbray.org/ongoing/What/' term='The World/Places/Hawaii' />
|
25
|
+
<category scheme='http://www.tbray.org/ongoing/What/' term='The World' />
|
26
|
+
<category scheme='http://www.tbray.org/ongoing/What/' term='Places' />
|
27
|
+
<category scheme='http://www.tbray.org/ongoing/What/' term='Hawaii' />
|
28
|
+
<content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
|
29
|
+
<p>I’m off with the family tomorrow for ten days in Maui, 15th through the
|
30
|
+
24th. We’ll be meeting an Aussie friend. Anyone else I know who’ll be there,
|
31
|
+
drop me a line and we’ll get together for a Mai Tai.</p>
|
32
|
+
</div></content></entry>
|
33
|
+
</feed>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
3
|
+
<workspace title="Yulup Demo">
|
4
|
+
<atom:title type="text">Yulup Demo</atom:title>
|
5
|
+
|
6
|
+
<collection title="Releases" href="../entries/?yanel.resource.viewid=atom">
|
7
|
+
<atom:title type="html">Early Yulup <i>Releases</i></atom:title>
|
8
|
+
</collection>
|
9
|
+
</workspace>
|
10
|
+
|
11
|
+
<workspace title="Yulup Website">
|
12
|
+
<atom:title type="text">Yulup Website</atom:title>
|
13
|
+
|
14
|
+
<collection title="Releases" href="http://www.yulup.org/download/release-atom-entries/?yanel.resource.viewid=atom">
|
15
|
+
<atom:title type="xhtml"><xhtml:div>Yulup <xhtml:b>Releases</xhtml:b>
|
16
|
+
</xhtml:div>
|
17
|
+
</atom:title>
|
18
|
+
|
19
|
+
</collection>
|
20
|
+
</workspace>
|
21
|
+
</service>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<?xml version="1.0" encoding='utf-8'?>
|
2
|
+
<service xmlns="http://www.w3.org/2007/app"
|
3
|
+
xmlns:atom="http://www.w3.org/2005/Atom">
|
4
|
+
<workspace>
|
5
|
+
<atom:title>Main Site</atom:title>
|
6
|
+
<collection
|
7
|
+
href="http://example.org/blog/main" >
|
8
|
+
<atom:title>My Blog Entries</atom:title>
|
9
|
+
<categories
|
10
|
+
href="http://example.com/cats/forMain.cats" />
|
11
|
+
</collection>
|
12
|
+
<collection
|
13
|
+
href="http://example.org/blog/pic" >
|
14
|
+
<atom:title>Pictures</atom:title>
|
15
|
+
<accept>image/png</accept>
|
16
|
+
<accept>image/jpeg</accept>
|
17
|
+
<accept>image/gif</accept>
|
18
|
+
</collection>
|
19
|
+
</workspace>
|
20
|
+
<workspace>
|
21
|
+
<atom:title>Sidebar Blog</atom:title>
|
22
|
+
<collection
|
23
|
+
href="http://example.org/sidebar/list" >
|
24
|
+
<atom:title>Remaindered Links</atom:title>
|
25
|
+
<accept>application/atom+xml;type=entry</accept>
|
26
|
+
<categories fixed="yes">
|
27
|
+
<atom:category
|
28
|
+
scheme="http://example.org/extra-cats/"
|
29
|
+
term="joke" />
|
30
|
+
<atom:category
|
31
|
+
scheme="http://example.org/extra-cats/"
|
32
|
+
term="serious" />
|
33
|
+
</categories>
|
34
|
+
</collection>
|
35
|
+
</workspace>
|
36
|
+
</service>
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'atom/service'
|
4
|
+
|
5
|
+
describe Atom::Service do
|
6
|
+
describe 'when parsing' do
|
7
|
+
before(:each) do
|
8
|
+
@service = Atom::Service.parse(fixtures(:service))
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should parse workspace elements correctly' do
|
12
|
+
@service.workspaces.length.should == 2
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should absolutize relative hrefs' do
|
16
|
+
svc = Atom::Service.parse(
|
17
|
+
fixtures('service-w-xhtml-ns'),
|
18
|
+
'http://example.org/introspection/')
|
19
|
+
|
20
|
+
coll = svc.workspaces.first.collections.first
|
21
|
+
coll.href.should == "http://example.org/entries/?yanel.resource.viewid=atom"
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should parse XHTML outside the default namespace correctly' do
|
25
|
+
xhtml_svc = Atom::Service.parse(fixtures('service-w-xhtml-ns'))
|
26
|
+
|
27
|
+
xhtml_svc.workspaces.length.should == 2
|
28
|
+
xhtml_coll = xhtml_svc.workspaces.last.collections.first
|
29
|
+
xhtml_coll.title.html.strip.should == 'Yulup <b>Releases</b>'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Atom::Workspace do
|
35
|
+
describe 'when parsing' do
|
36
|
+
before(:each) do
|
37
|
+
svc = Atom::Service.parse(fixtures(:service))
|
38
|
+
@main = svc.workspaces.first
|
39
|
+
@sidebar = svc.workspaces.last
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should parse title element correctly' do
|
43
|
+
@main.title.to_s.should == 'Main Site'
|
44
|
+
@sidebar.title.to_s.should == 'Sidebar Blog'
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should parse collection elements correctly' do
|
48
|
+
@main.collections.length.should == 2
|
49
|
+
@sidebar.collections.length.should == 1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe Atom::Collection do
|
55
|
+
describe 'when parsing' do
|
56
|
+
before(:each) do
|
57
|
+
svc = Atom::Service.parse(fixtures(:service))
|
58
|
+
@entries = svc.workspaces.first.collections.first
|
59
|
+
@pictures = svc.workspaces.first.collections.last
|
60
|
+
@links = svc.workspaces.last.collections.first
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should parse href correctly' do
|
64
|
+
@entries.href.should == 'http://example.org/blog/main'
|
65
|
+
@entries.feed.uri.to_s.should == 'http://example.org/blog/main'
|
66
|
+
|
67
|
+
@pictures.href.should == 'http://example.org/blog/pic'
|
68
|
+
@links.href.should == 'http://example.org/sidebar/list'
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should parse title element correctly' do
|
72
|
+
@entries.title.to_s.should == 'My Blog Entries'
|
73
|
+
@pictures.title.to_s.should == 'Pictures'
|
74
|
+
@links.title.to_s.should == 'Remaindered Links'
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should parse accept elements correctly' do
|
78
|
+
@entries.accepts.should == ['application/atom+xml;type=entry']
|
79
|
+
@pictures.accepts.should == ['image/png', 'image/jpeg', 'image/gif']
|
80
|
+
@links.accepts.should == ['application/atom+xml;type=entry']
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe Atom::Categories do
|
86
|
+
describe 'when parsing' do
|
87
|
+
before(:each) do
|
88
|
+
svc = Atom::Service.parse(fixtures(:service))
|
89
|
+
@ool = svc.workspaces.first.collections.first.categories.first
|
90
|
+
@il = svc.workspaces.last.collections.first.categories.first
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should parse out-of-line categories correctly' do
|
94
|
+
@ool.href.should == 'http://example.com/cats/forMain.cats'
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should parse inline categories correctly' do
|
98
|
+
@il.fixed.should be_true
|
99
|
+
|
100
|
+
@il.list.length.should == 2
|
101
|
+
|
102
|
+
@il.list.first.scheme.should == 'http://example.org/extra-cats/'
|
103
|
+
@il.list.first.term.should == 'joke'
|
104
|
+
|
105
|
+
@il.list.last.term.should == 'serious'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: atom-tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brendan Taylor
|
@@ -9,11 +9,16 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-08-15 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description:
|
16
|
+
description: |-
|
17
|
+
atom-tools is an all-in-one Atom library. It parses and builds Atom (RFC 4287) entries and feeds, and manipulates Atom Publishing Protocol (RFC 5023) Collections.
|
18
|
+
|
19
|
+
It also comes with a set of commandline utilities for working with AtomPub Collections.
|
20
|
+
|
21
|
+
It is not the fastest Ruby Atom library, but it is comprehensive and makes handling extensions to the Atom format very easy.
|
17
22
|
email: whateley@gmail.com
|
18
23
|
executables: []
|
19
24
|
|
@@ -34,7 +39,6 @@ files:
|
|
34
39
|
- test/runtests.rb
|
35
40
|
- test/test_feed.rb
|
36
41
|
- test/test_protocol.rb
|
37
|
-
- test/conformance
|
38
42
|
- test/conformance/updated.rb
|
39
43
|
- test/conformance/xmlnamespace.rb
|
40
44
|
- test/conformance/title.rb
|
@@ -43,7 +47,16 @@ files:
|
|
43
47
|
- test/test_xml.rb
|
44
48
|
- test/test_http.rb
|
45
49
|
- test/test_general.rb
|
46
|
-
-
|
50
|
+
- spec/entry_spec.rb
|
51
|
+
- spec/ext_spec.rb
|
52
|
+
- spec/spec_helper.rb
|
53
|
+
- spec/feed_spec.rb
|
54
|
+
- spec/fixtures/feed-w-ext.xml
|
55
|
+
- spec/fixtures/service-w-xhtml-ns.xml
|
56
|
+
- spec/fixtures/entry-w-ext.xml
|
57
|
+
- spec/fixtures/service.xml
|
58
|
+
- spec/fixtures/entry.xml
|
59
|
+
- spec/service_spec.rb
|
47
60
|
- lib/atom/cache.rb
|
48
61
|
- lib/atom/feed.rb
|
49
62
|
- lib/atom/text.rb
|
@@ -54,7 +67,9 @@ files:
|
|
54
67
|
- lib/atom/element.rb
|
55
68
|
- lib/atom/http.rb
|
56
69
|
has_rdoc: true
|
57
|
-
homepage: http://
|
70
|
+
homepage: http://github.com/bct/atom-tools/wikis
|
71
|
+
licenses: []
|
72
|
+
|
58
73
|
post_install_message:
|
59
74
|
rdoc_options: []
|
60
75
|
|
@@ -75,9 +90,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
90
|
requirements: []
|
76
91
|
|
77
92
|
rubyforge_project: ibes
|
78
|
-
rubygems_version: 1.3.
|
93
|
+
rubygems_version: 1.3.2
|
79
94
|
signing_key:
|
80
|
-
specification_version:
|
81
|
-
summary: Tools for working with Atom Entries, Feeds and Collections
|
95
|
+
specification_version: 3
|
96
|
+
summary: Tools for working with Atom Entries, Feeds and Collections.
|
82
97
|
test_files:
|
83
98
|
- test/runtests.rb
|