atom-tools 0.9.0 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +3 -3
- data/README +9 -49
- data/Rakefile +65 -62
- data/bin/atom-cp +159 -0
- data/bin/atom-grep +78 -0
- data/bin/atom-post +73 -0
- data/bin/atom-purge +82 -0
- data/doc/classes/Atom/AttrEl.html +163 -0
- data/doc/classes/Atom/Author.html +2 -19
- data/doc/classes/Atom/AutodiscoveryFailure.html +111 -0
- data/doc/classes/Atom/Categories.html +168 -0
- data/doc/classes/Atom/Category.html +10 -1
- data/doc/classes/Atom/Collection.html +194 -91
- data/doc/classes/Atom/Content.html +42 -1
- data/doc/classes/Atom/Contributor.html +2 -8
- data/doc/classes/Atom/Control.html +126 -0
- data/doc/classes/Atom/Converters.html +571 -0
- data/doc/classes/Atom/DigestAuth.html +285 -0
- data/doc/classes/Atom/Element.html +673 -106
- data/doc/classes/Atom/FileCache.html +287 -0
- data/doc/classes/Atom/HTTP.html +211 -95
- data/doc/classes/Atom/HTTPResponse.html +190 -0
- data/doc/classes/Atom/HasCategories.html +187 -0
- data/doc/classes/Atom/HasLinks.html +168 -0
- data/doc/classes/Atom/Link.html +80 -3
- data/doc/classes/Atom/NilCache.html +202 -0
- data/doc/classes/Atom/ParseError.html +111 -0
- data/doc/classes/Atom/Parsers.html +311 -0
- data/doc/classes/Atom/Person.html +130 -0
- data/doc/classes/Atom/Rights.html +113 -0
- data/doc/classes/Atom/Service.html +298 -0
- data/doc/{files/lib/atom/yaml_rb.html → classes/Atom/Source.html} +26 -24
- data/doc/classes/Atom/Subtitle.html +113 -0
- data/doc/classes/Atom/Summary.html +113 -0
- data/doc/classes/Atom/Text.html +196 -53
- data/doc/classes/Atom/Title.html +113 -0
- data/doc/classes/Atom/Tools.html +525 -0
- data/doc/classes/Atom/Workspace.html +121 -0
- data/doc/classes/Object.html +204 -0
- data/doc/created.rid +1 -1
- data/doc/files/README.html +9 -49
- data/doc/files/lib/atom/cache_rb.html +302 -0
- data/doc/files/lib/atom/collection_rb.html +1 -2
- data/doc/files/lib/atom/element_rb.html +2 -1
- data/doc/files/lib/atom/entry_rb.html +2 -2
- data/doc/files/lib/atom/feed_rb.html +1 -2
- data/doc/files/lib/atom/http_rb.html +6 -1
- data/doc/files/lib/atom/{xml_rb.html → service_rb.html} +8 -6
- data/doc/files/lib/atom/text_rb.html +2 -1
- data/doc/files/lib/atom/{app_rb.html → tools_rb.html} +4 -6
- data/doc/fr_class_index.html +23 -3
- data/doc/fr_file_index.html +3 -3
- data/doc/fr_method_index.html +111 -36
- data/lib/atom/cache.rb +178 -0
- data/lib/atom/collection.rb +90 -40
- data/lib/atom/element.rb +569 -161
- data/lib/atom/entry.rb +63 -89
- data/lib/atom/feed.rb +65 -67
- data/lib/atom/http.rb +421 -49
- data/lib/atom/service.rb +106 -0
- data/lib/atom/text.rb +138 -61
- data/lib/atom/tools.rb +163 -0
- data/spec/entry_spec.rb +364 -0
- data/spec/ext_spec.rb +42 -0
- data/spec/feed_spec.rb +39 -0
- data/spec/fixtures/contacts-feed.xml +34 -0
- data/spec/fixtures/entry-w-ext.xml +15 -0
- data/spec/fixtures/entry-w-xml.xml +24 -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
- data/test/conformance/order.rb +11 -10
- data/test/conformance/title.rb +9 -9
- data/test/conformance/updated.rb +2 -1
- data/test/runtests.rb +0 -0
- data/test/test_constructs.rb +78 -8
- data/test/test_feed.rb +35 -29
- data/test/test_general.rb +3 -30
- data/test/test_http.rb +248 -34
- data/test/test_protocol.rb +143 -24
- data/test/test_xml.rb +145 -53
- metadata +116 -62
- data/bin/atom-client.rb +0 -246
- data/bin/atom-server.rb~ +0 -71
- data/doc/classes/Atom/App.html +0 -217
- data/doc/classes/Atom/Entry.html +0 -365
- data/doc/classes/Atom/Feed.html +0 -585
- data/lib/atom/app.rb +0 -87
- data/lib/atom/xml.rb +0 -200
- data/lib/atom/yaml.rb +0 -101
data/spec/entry_spec.rb
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
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
|
+
describe 'extensions' do
|
|
344
|
+
before(:each) do
|
|
345
|
+
@entry = Atom::Entry.parse(fixtures('entry-w-ext'))
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
it 'should preserve namespaces' do
|
|
349
|
+
@entry.to_s.should =~ /purl/
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
describe "with XML in the content element" do
|
|
354
|
+
it "should expose the content XML" do
|
|
355
|
+
@entry = Atom::Entry.parse(fixtures('entry-w-xml'))
|
|
356
|
+
@entry.content.xml.should be_instance_of(REXML::Element)
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
it "should expose the content XML" do
|
|
360
|
+
@entry = Atom::Entry.parse(fixtures('entry-w-xml'))
|
|
361
|
+
@entry.content.xml.root.name.should_not == 'content'
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
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,39 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
require 'atom/feed'
|
|
4
|
+
|
|
5
|
+
describe Atom::Feed 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
|
+
|
|
21
|
+
before :each do
|
|
22
|
+
@feed = Atom::Feed.parse(fixtures('contacts-feed'))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe "to_s" do
|
|
26
|
+
it "should only have one content element" do
|
|
27
|
+
result = @feed.to_s
|
|
28
|
+
result.scan("<content type=").size.should == 1
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "to_xml" do
|
|
33
|
+
it "should only have one content element" do
|
|
34
|
+
result = @feed.to_xml
|
|
35
|
+
REXML::XPath.match(result, "//content").size.should == 1
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
3
|
+
<id>http://api.constantcontact.com/ws/customers/foo/contacts</id>
|
|
4
|
+
<title type="text">Contacts for Customer: Foo</title>
|
|
5
|
+
<link href="contacts"></link>
|
|
6
|
+
<link href="contacts" rel="self"></link>
|
|
7
|
+
<author>
|
|
8
|
+
<name>Foo</name>
|
|
9
|
+
</author>
|
|
10
|
+
<updated>2010-05-18T13:45:29.352Z</updated>
|
|
11
|
+
<link href="/ws/customers/Foo/contacts" rel="first"></link>
|
|
12
|
+
<link href="/ws/customers/Foo/contacts?email=tropix50%40hotmail.com" rel="current"></link>
|
|
13
|
+
<entry>
|
|
14
|
+
<link href="/ws/customers/Foo/contacts/42" rel="edit"></link>
|
|
15
|
+
<id>http://api.constantcontact.com/ws/customers/foo/contacts/42</id>
|
|
16
|
+
<title type="text">Contact: foo@example.com</title>
|
|
17
|
+
<updated>2010-05-18T13:45:29.372Z</updated>
|
|
18
|
+
<author>
|
|
19
|
+
<name>Constant Contact</name>
|
|
20
|
+
</author>
|
|
21
|
+
<content type="application/vnd.ctct+xml">
|
|
22
|
+
<Contact xmlns="http://ws.constantcontact.com/ns/1.0/" id="http://api.constantcontact.com/ws/customers/foo/contacts/42">
|
|
23
|
+
<Status>Active</Status>
|
|
24
|
+
<EmailAddress>foo@example.com</EmailAddress>
|
|
25
|
+
<EmailType>HTML</EmailType>
|
|
26
|
+
<Name>Bar, Foo</Name>
|
|
27
|
+
<OptInTime>2008-09-22T15:03:18.894Z</OptInTime>
|
|
28
|
+
<OptInSource>ACTION_BY_CUSTOMER</OptInSource>
|
|
29
|
+
<Confirmed>false</Confirmed>
|
|
30
|
+
<InsertTime>2008-09-22T15:03:18.894Z</InsertTime>
|
|
31
|
+
</Contact>
|
|
32
|
+
</content>
|
|
33
|
+
</entry>
|
|
34
|
+
</feed>
|
|
@@ -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,24 @@
|
|
|
1
|
+
<entry xmlns="http://www.w3.org/2005/Atom">
|
|
2
|
+
<link href="/ws/customers/joesflowers/lists/1" rel="edit" />
|
|
3
|
+
<id>http://api.constantcontact.com/ws/customers/joesflowers/lists/1</id>
|
|
4
|
+
<title type="text">General Interest</title>
|
|
5
|
+
<updated>2008-04-16T18:39:35.710Z</updated>
|
|
6
|
+
<content type="application/vnd.ctct+xml">
|
|
7
|
+
<ContactList xmlns="http://ws.constantcontact.com/ns/1.0/" id="http://api.constantcontact.com/ws/customers/joesflowers/lists/1">
|
|
8
|
+
<OptInDefault>false</OptInDefault>
|
|
9
|
+
<Name>General Interest</Name>
|
|
10
|
+
<ShortName>General Interest</ShortName>
|
|
11
|
+
<SortOrder>1</SortOrder>
|
|
12
|
+
</ContactList>
|
|
13
|
+
</content>
|
|
14
|
+
<source>
|
|
15
|
+
<id>http://api.constantcontact.com/ws/customers/joesflowers/lists</id>
|
|
16
|
+
<title type="text">Contact Lists</title>
|
|
17
|
+
<link href="" />
|
|
18
|
+
<link href="" rel="self" />
|
|
19
|
+
<author>
|
|
20
|
+
<name>Constant Contact Web Services</name>
|
|
21
|
+
</author>
|
|
22
|
+
<updated>2008-04-16T18:39:35.717Z</updated>
|
|
23
|
+
</source>
|
|
24
|
+
</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>
|