atomutil 0.0.1

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/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2007-12-05
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/License.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Lyo Kato
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,35 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ config/hoe.rb
7
+ config/requirements.rb
8
+ lib/atomutil.rb
9
+ log/debug.log
10
+ script/destroy
11
+ script/generate
12
+ script/txt2html
13
+ setup.rb
14
+ spec/categories_spec.rb
15
+ spec/category_spec.rb
16
+ spec/content_spec.rb
17
+ spec/customfeed_spec.rb
18
+ spec/feed_spec.rb
19
+ spec/link_spec.rb
20
+ spec/namespace_spec.rb
21
+ spec/opensearch_spec.rb
22
+ spec/person_spec.rb
23
+ spec/samples/feed.atom
24
+ spec/spec.opts
25
+ spec/spec_helper.rb
26
+ spec/threading_spec.rb
27
+ tasks/deployment.rake
28
+ tasks/environment.rake
29
+ tasks/rspec.rake
30
+ tasks/website.rake
31
+ website/index.html
32
+ website/index.txt
33
+ website/javascripts/rounded_corners_lite.inc.js
34
+ website/stylesheets/screen.css
35
+ website/template.rhtml
data/README.txt ADDED
@@ -0,0 +1,632 @@
1
+ = Utilities for AtomPub / Atom Syndication Format
2
+
3
+ = SYNOPSIS
4
+
5
+ == Building or parsing XML with Atom Syndication Format
6
+
7
+ === How To Construct Each Atom Element
8
+
9
+ Create new object and setup with each accessor.
10
+
11
+ entry = Atom::Entry.new
12
+
13
+ entry.title = 'Title!'
14
+ entry.summary = 'Summary!'
15
+ entry.published = Time.now
16
+
17
+ Or you can do that at once with passing hash parameter to constructor
18
+
19
+ entry = Atom::Entry.new(
20
+ :title => 'Title!',
21
+ :summary => 'Summary',
22
+ :published => Time.now
23
+ )
24
+
25
+ And you also can setup new element within a block if you pass one.
26
+
27
+ entry = Atom::Entry.new(:title => 'New Entry') do |e|
28
+ e.summary = 'New Summary'
29
+ author = Atom::Author.new :name => 'John'
30
+ e.author = author
31
+ e.published = Time.now
32
+ end
33
+
34
+ And finally you can get xml-document from them.
35
+
36
+ xml_string = entry.to_s
37
+
38
+ If you pass false to to_s, it returns non-indented string
39
+
40
+ xml_string = entry.to_s(false)
41
+
42
+ === How To Parse Each Atom XML Document
43
+
44
+ xml_string = <<-EOS
45
+ <?xml version="1.0" encoding="UTF-8"?>
46
+ <entry xmlns="http://www.w3.org/2005/Atom">
47
+ <id>tag:example.org,2007-12-01:mybook</id>
48
+ <title>Title</title>
49
+ <summary>Summary</summary>
50
+ <author><name>John</name></author>
51
+ </entry>
52
+ EOS
53
+
54
+ Pass the xml-string to proper Atom Element Class with :stream key
55
+
56
+ entry = Atom::Entry.new :stream => xml_string
57
+ puts entry.title # Book
58
+ puts entry.summary # Summary
59
+ puts entry.author.name # John
60
+
61
+ Atom::Feed and Atom::Entry can be build from files
62
+
63
+ entry = Atom::Feed.new :file => 'my_feed.atom'
64
+
65
+ or from uri
66
+
67
+ entry = Atom::Feed.new :uri => 'http://example.com/feed.atom'
68
+
69
+ == How To Handle other Namespace
70
+
71
+ There are times when you want to extend your atom element
72
+ with other namespaces.
73
+ For example, in case you want to deal pagination with OpenSearch
74
+
75
+ xmlstring = <<-EOS
76
+ <feed xmlns="http://www.w3.org/2005/Atom"
77
+ xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">
78
+ <openSearch:totalResult>153</openSearch:totalResult>
79
+ <openSearch:startIndex>40</openSearch:startIndex>
80
+ <openSearch:itemsPerPage>20</openSearch:itemsPerPage>
81
+ ...
82
+ </feed>
83
+ EOS
84
+
85
+ How to get these values?
86
+ The answer is using 'get' method.
87
+ And then, just a reminder, you have to prepare Atom::Namespace object.
88
+ Pass the object and element name to the method.
89
+ And it returns REXML::Element object.
90
+
91
+ feed = Atom::Feed.new :stream => xmlstring
92
+ open_search_ns = Atom::Namespace.new(
93
+ :prefix => 'openSearch',
94
+ :uri => 'http://a9.com/-/spec/opensearchrss/1.1/')
95
+
96
+ total = feed.get(open_search_ns, 'totalResult').text.to_i
97
+ start = feed.get(open_search_ns, 'startIndex').text.to_i
98
+ per_page = feed.get(open_search_ns, 'itemsPerPage').text.to_i
99
+
100
+ And of cource, you also can 'set'
101
+
102
+ feed = Atom::Feed.new
103
+ feed.title = 'my new feed'
104
+ feed.set(open_search_ns, 'totalResult', 153)
105
+ feed.set(open_search_ns, 'startIndex', 40)
106
+ feed.set(open_search_ns, 'itemsPerPage', 20)
107
+
108
+ In this example, I take the 'openSearch' for pagination, but it's already implemented with
109
+ useful methods.
110
+
111
+ feed = Atom::Feed.new
112
+ feed.total_results = 35
113
+ feed.start_index = 1
114
+ feed.items_per_page = 20
115
+
116
+ puts feed.total_results
117
+ puts feed.start_index
118
+ puts feed.items_per_page
119
+
120
+ === Build a Service Document
121
+
122
+ Create root service element
123
+
124
+ service = Atom::Service.new
125
+
126
+ Create workspace element which the service appends.
127
+
128
+ blog_workspace = Atom::Workspace.new
129
+ blog_workspace.title = 'My Blog'
130
+
131
+ collection = Atom::Collection.new
132
+ collection.href = 'http://blog.example.org/feed'
133
+ collection.title = 'Sample Blog'
134
+
135
+ Create categories that your collection handles
136
+
137
+ cats = Atom::Categories.new
138
+ cats.fixed = 'no'
139
+
140
+ You can set each concrete categories here
141
+
142
+ category1 = Atom::Category.new
143
+ category1.term = 'technology'
144
+ category2 = Atom::Category.new
145
+ category2.term = 'music'
146
+ category3 = Atom::Category.new
147
+ category3.term = 'sport'
148
+ cats.add_category category1
149
+ cats.add_category category2
150
+ cats.add_category category3
151
+
152
+ Or set only href parameter that represents uri for Categories Document,
153
+ Instead of setting each categories here.
154
+ Then you should provides Categories Document at indicated uri.
155
+
156
+ cats.href = 'http://blog.example.org/categories'
157
+
158
+ collection.add_categories cats
159
+ blog_workspace.add_collection collection
160
+ service.add_workspace blog_workspace
161
+ service_document_xml_string = service.to_s
162
+
163
+ === Build a Categories Document
164
+
165
+ cats = Atom::Categories.new
166
+ category1 = Atom::Category.new
167
+ category1.term = 'technology'
168
+ category2 = Atom::Category.new
169
+ category2.term = 'music'
170
+ category3 = Atom::Category.new
171
+ category3.term = 'sport'
172
+ cats.add_category category1
173
+ cats.add_category category2
174
+ cats.add_category category3
175
+
176
+ categories_xml_string = cats.to_s
177
+
178
+ === Build an Entry
179
+
180
+ entry = Atom::Entry.new
181
+
182
+ * id
183
+ * title
184
+ * summary
185
+ * rights
186
+ * source
187
+
188
+ Simple text accessors
189
+
190
+ entry.id = 'tag:example.org,2007:example'
191
+ entry.title = 'My First Blog Post'
192
+ entry.summary = 'This is summary'
193
+ entry.rights = 'Copyright(c) 2007 Lyo Kato all rights reserved.'
194
+
195
+ * published
196
+ * updated
197
+
198
+ You can set them with Time class
199
+
200
+ entry.published = Time.now
201
+ entry.updated = Time.now
202
+
203
+ Or you can set with W3CDTF formatted string
204
+
205
+ entry.published = "2007-12-01T01:30:00Z"
206
+
207
+ And pick it up as Time object
208
+
209
+ published = entry.published
210
+ puts published.year
211
+ puts published.month
212
+
213
+ * author
214
+ * contributor
215
+
216
+ Set person construct with Atom::Person
217
+
218
+ person = Atom::Person.new
219
+ person.name = 'Lyo Kato'
220
+ person.email = 'lyo.kato atmark gmail.com'
221
+ person.uri = 'http://www.lyokato.net/'
222
+
223
+ entry.author = person.to_author
224
+ entry.contributor = person.to_contributor
225
+
226
+ Or Atom::Author, Atom::Contributor directly
227
+
228
+ cont = Atom::Contributor.new
229
+ cont.name = 'Lyo'
230
+ cont.email = 'lyo.kato atmark gmail.com'
231
+ entry.contributor = cont
232
+
233
+ To set multiple data
234
+
235
+ entry.add_author author1
236
+ entry.add_author author2
237
+ entry.add_contributor contributor1
238
+ entry.add_contributor contributor2
239
+
240
+ Get all authors and contributors
241
+
242
+ authors = entry.authors
243
+ contributors = entry.contributors
244
+
245
+ Get only first author and contributor
246
+
247
+ author = entry.author
248
+ contributor = entry.contributor
249
+
250
+ * link
251
+
252
+ Link Element Accessor
253
+
254
+ link = Atom::Link.new
255
+ link.href = 'http://example.org/entry/1'
256
+ link.rel = 'alternate'
257
+ link.type = 'text/html'
258
+ link.hreflang = 'fr'
259
+ link.length = '512'
260
+ link.title = 'My Blog Post'
261
+ entry.link = link
262
+
263
+ You can set multiple links
264
+
265
+ entry.add_link link1
266
+ entry.add_link link2
267
+
268
+ To get all links as an Array
269
+
270
+ links = entry.links
271
+
272
+ To get first one
273
+
274
+ link = entry.link
275
+ puts link.href
276
+ puts link.rel
277
+
278
+ Further more, useful methods are implemented for major 'rel' types.
279
+
280
+ entry.alternate_link = 'http://example.org/entry/1'
281
+
282
+ This is same as
283
+
284
+ link = Atom::Link.new
285
+ link.rel = 'alternate'
286
+ link.href = 'http://example.org/entry/1'
287
+ entry.add_link link
288
+
289
+ And
290
+
291
+ puts entry.alternate_link # http://example.org/entry1
292
+
293
+ This is same as
294
+
295
+ links = entry.links
296
+ alternate_link = links.select{ |l| l.rel == 'alternate' }.first
297
+ puts alternate_link.href
298
+
299
+ If it contains multiple 'alternate' links, to get all of them,
300
+
301
+ alternate_links = links.alternate_links
302
+
303
+ Like this, you can use following methods for each links
304
+
305
+ entry.self_link:: <link rel='self' href='...'/>
306
+ entry.edit_link:: <link rel='edit' href='...'/>
307
+ entry.edit_media_link:: <link rel='edit-media' href='...'/>
308
+ entry.enclosure_link:: <link rel='enclosure' href='...'/>
309
+ entry.related_link:: <link rel='related' href='...' />
310
+ entry.via_link:: <link rel='via' href='...' />
311
+ entry.first_link:: <link rel='first' href='...'/>
312
+ entry.previous_link:: <link rel='previous' href='...'/>
313
+ entry.next_link:: <link rel='next' href='...' />
314
+ entry.last_link:: <link rel='last' href='...' />
315
+
316
+ * category
317
+
318
+ Category Element Accessor
319
+
320
+ category = Atom::Category.new
321
+ category.term = 'music'
322
+ category.scheme = 'http://example.org/category/music'
323
+ category.label = 'My Music'
324
+ entry.category = category
325
+
326
+ You can set multiple categories
327
+
328
+ entry.add_category cat1
329
+ entry.add_category cat2
330
+
331
+ To get all categories as an Array
332
+
333
+ categories = entry.categories
334
+
335
+ To get first one
336
+
337
+ first_category = entry.category
338
+ puts first_category.term
339
+ puts first_category.scheme
340
+
341
+ * content
342
+
343
+ You can push it as a text
344
+
345
+ entry.content = 'This is a content'
346
+
347
+ Or an Atom::Content object
348
+
349
+ content = Atom::Content.new :body => 'This is a content'
350
+ entry.content = content
351
+
352
+ To pick it up
353
+
354
+ content = entry.content
355
+
356
+ puts content.type
357
+ puts content.body
358
+
359
+ * control
360
+
361
+ Control Element Accessor
362
+
363
+ control = Atom::Control.new
364
+ control.draft = 'yes'
365
+ entry.control = control
366
+
367
+ Then entry includes
368
+
369
+ <app:control xmlns:app='http://www.w3.org/2007/app'>
370
+ <app:draft>yes</app:draft>
371
+ </app:control>
372
+
373
+ * edited
374
+
375
+ Represents what time this entry was edited.
376
+
377
+ entry.edited = Time.now
378
+
379
+ Then entry includes
380
+
381
+ <app:edited>2007-09-01T00:00:00Z</app:edited>
382
+
383
+ To pick it up
384
+
385
+ edited = entry.edited
386
+ puts edited.year
387
+ puts edited.month
388
+
389
+ You also can handle Atom-Threading
390
+ (http://tools.ietf.org/html/rfc4685)
391
+
392
+ target = Atom::ReplyTarget.new
393
+ target.id = 'tag:example.org,2007:12:example'
394
+ target.href = 'http://example.org/blog/2007/12/archive01'
395
+ target.type = 'text/xhtml'
396
+
397
+ entry.in_reply_to target
398
+
399
+ Or you can set the target direclty with hash
400
+
401
+ entry.in_reply_to(
402
+ :id => 'tag:example.org,2007:12:example',
403
+ :href => 'http://example.org/blog/2007/12/archive01',
404
+ :type => 'text/xhtml'
405
+ )
406
+
407
+ And then entry includes xml
408
+
409
+ <thr:in-reply-to xmlns:thr='http://purl.org/syndication/thread/1.0'
410
+ ref='tag:example.org,2007:12:example'
411
+ href='http://example.org/blog/2007/12/archive01'
412
+ type='text/xhtml'/>
413
+
414
+ Pick it up from entry
415
+
416
+ target = entry.in_reply_to
417
+ puts target.id
418
+ puts target.href
419
+ puts target.type
420
+
421
+ Add a replies link
422
+
423
+ link = Atom::RepliesLink.new
424
+ link.href = 'http://example.org/entry/1/replies'
425
+ link.count = 10
426
+ link.updated = Time.now
427
+
428
+ entry.add_link link
429
+
430
+ Then entry includes
431
+
432
+ <link rel='replies' href='http://example.org/entry/1/replies'
433
+ thr:count='10' thr:updated='2007-01-01T00:00:00Z'>
434
+
435
+ Add total replies count
436
+
437
+ entry.total = 10
438
+
439
+ Then entry includes
440
+
441
+ <thr:total>10</thr:total>
442
+
443
+ === Build a Feed
444
+
445
+ feed = Atom::Feed.new
446
+
447
+ * id
448
+ * title
449
+ * subtitle
450
+ * rights
451
+ * icon
452
+ * logo
453
+ * language
454
+ * version
455
+
456
+ Simple text accessors
457
+
458
+ feed.id = 'tag:example.org,2007:example'
459
+ feed.title = 'Example Feed'
460
+ feed.subtitle = 'Subtitle of Example Feed'
461
+ feed.rights = 'Copyright(c) 2007 example.org all rights reserved'
462
+ feed.icon = 'http://example.org/icon.png'
463
+ feed.logo = 'http://example.org/logo.png'
464
+ feed.language = 'fr'
465
+ feed.version = '1.0'
466
+
467
+ * updated
468
+
469
+ Time accessor
470
+
471
+ feed.updated = Time.now
472
+ updated = feed.updated
473
+ puts updated.year
474
+ puts updated.month
475
+
476
+ * generator
477
+
478
+ You can set generator information
479
+
480
+ feed.generator = 'MyGenerator'
481
+
482
+ Or more in detail
483
+
484
+ generator = Atom::Generator.new(
485
+ :name => 'MyGenerator',
486
+ :uri => 'http://example.org/mygenerator',
487
+ :version => '1.0'
488
+ )
489
+ feed.generator = generator
490
+
491
+ generator = feed.generator
492
+ puts generator.name
493
+ puts generator.uri
494
+ puts generator.version
495
+
496
+ * link
497
+
498
+ You can set links like you do with entry
499
+
500
+ link1 = Atom::Link.new :href => 'http://example.org/entry/1', :rel => 'alternate'
501
+ feed.add_link link1
502
+
503
+ feed.edit_link = 'http://example.org/entry/1/edit'
504
+
505
+ * category
506
+
507
+ You can set categoryes like you do with entry
508
+
509
+ * author
510
+ * contributor
511
+
512
+ Person construct data.
513
+ You can set authors/contributors on same way for entry.
514
+
515
+ * entry
516
+
517
+ Entry Accessors
518
+
519
+ entry1 = Atom::Entry.new
520
+ entry1.title = 'Entry1'
521
+
522
+ entry2 = Atom::Entry.new
523
+ entry2.title = 'Entry2'
524
+
525
+ feed.add_entry entry1
526
+ feed.add_entry entry2
527
+
528
+ entries = feed.entries
529
+
530
+ OpenSeach Pagination Control
531
+
532
+ feed.total_results = 35
533
+ feed.items_per_page = 10
534
+ feed.start_index = 11
535
+
536
+ Then feed includes
537
+
538
+ <openSearch:totalResults>35</openSearch:totalResults>
539
+ <openSearch:itemsPerPage>10</openSearch:itemsPerPage>
540
+ <openSearch:startIndex>11</openSearch:startIndex>
541
+
542
+ == Using service that provides AtomPub API
543
+
544
+ At first, construct appropriate authorizer
545
+ At this time, let's assume that we're requried WSSE Authentication.
546
+ Of cource, you can choose other authorizer,
547
+ for example, Atom::Auth::Basic(Basic authentication),
548
+ and in future, Atom::Auth::OAuth, Atom::Auth::OpenID, and etc.
549
+
550
+ auth = Atompub::Auth::Wsse.new :username => 'myname', :password => 'mypass'
551
+
552
+ client = Atompub::Client.new :auth => auth
553
+
554
+ service = client.get_service( 'http://example/service/api/endpoint' )
555
+ collection = service.workspaces.first.collection.first
556
+ categories = client.get_categories( collection.categories.href )
557
+
558
+ categories.categories.each do |category|
559
+ puts category.label
560
+ puts category.scheme
561
+ puts category.term
562
+ end
563
+
564
+ feed = client.get_feed( collection.href )
565
+
566
+ puts feed.title # 'Example Feed'
567
+ puts feed.icon # http://example/icon.jpg
568
+ puts feed.logo # http://example/logo.jpg
569
+
570
+ entries = feed.entries
571
+ entries.each do |entry|
572
+ puts entry.id
573
+ puts entry.title
574
+ end
575
+
576
+ entry = entries.first
577
+ entry.title = 'Changed!'
578
+
579
+ client.update_entry( entry.edit_link, entry )
580
+
581
+ client.delete_entry( entries[2].edit_link )
582
+
583
+ new_entry = Atom::Entry.new
584
+ new_entry.title = 'New!'
585
+ new_entry.summary = 'New Entry for Example'
586
+ new_entry.published = Time.now
587
+
588
+ edit_uri = client.create_entry( collection.href, new_entry )
589
+
590
+ # you also can use 'slug'
591
+ slug = 'new-entry'
592
+ edit_uri = client.create_entry( collection.href, new_entry, slug )
593
+
594
+ media_collection = service.workspaces.first.collections[1]
595
+ media_collection_uri = media_collection.href
596
+
597
+ media_uri = client.create_media( media_collection_uri, '', 'image/jpeg')
598
+ # with slug
599
+ # client.create_media( media_collection_uri, 'foo.jpg', 'image/jpeg', 'new-image')
600
+
601
+ media_entry = client.get_entry( media_uri )
602
+ edit_media_link = media_entry.edit_media_link
603
+ client.update_media( edit_media_link, 'bar.jpg', 'image/jpeg' )
604
+ client.delete_media( edit_media_link )
605
+
606
+ feed_contains_media_entreis = client.get_feed( media_collection_uri )
607
+
608
+ = DESCRIPTION
609
+
610
+ This library allows you to handle AtomPub and Atom Syndication Format easily.
611
+ Most of the idea is from great Perl modules on CPAN.
612
+
613
+ = TO DO
614
+
615
+ * More document
616
+ * More tests (RSpec)
617
+ * Encoding control
618
+ * New Auth classes Atompub::Auth::OpenID and Atompub::Auth::OAuth
619
+
620
+ = SEE ALSO
621
+
622
+ AtomPub Spec(RFC):: http://atompub.org/rfc4287.html
623
+ Atom::XML(Perl):: http://search.cpan.org/perldoc?XML%3A%3AAtom
624
+ Atom::XML::Service(Perl):: http://search.cpan.org/perldoc?XML%3A%3AAtom%3A%3AService
625
+ Atompub(Perl):: http://search.cpan.org/perldoc?Atompub
626
+
627
+ = Author and License
628
+
629
+ Author:: Lyo Kato (lyo.kato atmark gmail.com)
630
+ Copyright:: Copyright (c) 2007, Lyo Kato All rights reserved.
631
+ License:: Ruby License
632
+
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }