atom-tools 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,39 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.4
3
- specification_version: 1
4
2
  name: atom-tools
5
3
  version: !ruby/object:Gem::Version
6
- version: 1.0.0
7
- date: 2007-11-10 00:00:00 -07:00
8
- summary: Tools for working with Atom Entries, Feeds and Collections
9
- require_paths:
10
- - lib
11
- email:
12
- homepage:
13
- rubyforge_project:
14
- description:
15
- autorequire:
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: true
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
24
- version:
4
+ version: 2.0.0
25
5
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
6
  authors:
30
7
  - Brendan Taylor
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-03-28 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email:
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
31
24
  files:
32
25
  - COPYING
33
26
  - README
34
27
  - Rakefile
35
28
  - setup.rb
36
- - bin/atom-client.rb
29
+ - bin/atom-grep
30
+ - bin/atom-post
31
+ - bin/atom-purge
32
+ - bin/atom-cp
37
33
  - test/test_constructs.rb
38
34
  - test/runtests.rb
39
35
  - test/test_feed.rb
@@ -48,26 +44,40 @@ files:
48
44
  - test/test_http.rb
49
45
  - test/test_general.rb
50
46
  - lib/atom
51
- - lib/atom/yaml.rb
47
+ - lib/atom/cache.rb
52
48
  - lib/atom/feed.rb
53
49
  - lib/atom/text.rb
54
50
  - lib/atom/collection.rb
55
51
  - lib/atom/service.rb
56
52
  - lib/atom/entry.rb
57
- - lib/atom/xml.rb
53
+ - lib/atom/tools.rb
58
54
  - lib/atom/element.rb
59
55
  - lib/atom/http.rb
60
- test_files:
61
- - test/runtests.rb
56
+ has_rdoc: true
57
+ homepage:
58
+ post_install_message:
62
59
  rdoc_options: []
63
60
 
64
- extra_rdoc_files:
65
- - README
66
- executables: []
67
-
68
- extensions: []
69
-
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
70
75
  requirements: []
71
76
 
72
- dependencies: []
73
-
77
+ rubyforge_project:
78
+ rubygems_version: 1.0.1
79
+ signing_key:
80
+ specification_version: 2
81
+ summary: Tools for working with Atom Entries, Feeds and Collections
82
+ test_files:
83
+ - test/runtests.rb
data/bin/atom-client.rb DELETED
@@ -1,275 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- require "optparse"
4
-
5
- options = {}
6
-
7
- OptionParser.new do |opts|
8
- opts.banner = "Usage: #{$0} [options]"
9
-
10
- opts.on("-c", "--coll-url [URL]", "URL of the collection you would like to manipulate") do |url|
11
- options[:url] = url
12
- end
13
-
14
- opts.on("-u", "--user [USERNAME]", "Username to authenticate with") do |user|
15
- options[:user] = user
16
- end
17
-
18
- opts.on("-p", "--password [PASSWORD]", "Password to authenticate with") do |pass|
19
- options[:pass] = pass
20
- end
21
-
22
- opts.on_tail("-h", "--help", "Show this message") do
23
- puts opts
24
- exit
25
- end
26
- end.parse!
27
-
28
- require "tempfile"
29
-
30
- require "atom/yaml"
31
- require "atom/service"
32
- require "atom/http"
33
-
34
- require "rubygems"
35
- require "bluecloth"
36
-
37
- require "time"
38
-
39
- require 'yaml'
40
-
41
- class Tempfile
42
- def edit_externally
43
- self.close
44
-
45
- system("#{EDITOR} #{self.path}")
46
-
47
- self.open
48
- end
49
- end
50
-
51
- class String
52
- def edit_externally
53
- tempfile = Tempfile.new("entry")
54
- tempfile.puts self
55
-
56
- tempfile.edit_externally
57
-
58
- ret = tempfile.read
59
- tempfile.delete
60
-
61
- ret
62
- end
63
- end
64
-
65
- class Atom::Entry
66
- def prepare_for_output
67
- filter_hook
68
-
69
- updated!
70
- end
71
-
72
- def filter_hook
73
- # so much for actual text content...
74
- if @content and @content["type"] == "text"
75
- self.content = BlueCloth.new( @content.to_s ).to_html
76
- @content["type"] = "xhtml"
77
- end
78
- end
79
-
80
- def edit
81
- yaml = YAML.load(self.to_yaml)
82
-
83
- # human readability
84
- yaml.delete "id"
85
-
86
- if yaml["links"]
87
- yaml["links"].find_all { |l| l["rel"] == "alternate" or l["rel"] == "edit" }.each { |l| yaml["links"].delete(l) }
88
- yaml.delete("links") if yaml["links"].empty?
89
- end
90
-
91
- new_yaml, entry = write_entry(yaml.to_yaml)
92
-
93
- entry.id = self.id
94
-
95
- [new_yaml["slug"], entry]
96
- end
97
- end
98
-
99
- # maybe this should handle displaying the list too.
100
- def choose_from list
101
- item = nil
102
- itemno = nil
103
-
104
- # oh wow this is pathetic
105
- until item
106
- if itemno
107
- puts "try picking a number on the list."
108
- end
109
-
110
- print "? "
111
- itemno = $stdin.gets.chomp
112
-
113
- item = list[itemno.to_i]
114
- end
115
-
116
- item
117
- end
118
-
119
- def choose_entry_url coll
120
- puts "which entry?"
121
-
122
- coll.entries.each_with_index do |entry, index|
123
- puts "#{index}: #{entry.title}"
124
- end
125
-
126
- entry = choose_from coll.entries
127
-
128
- edit_link = entry.links.find do |link|
129
- link["rel"] = "edit"
130
- end
131
-
132
- edit_link["href"]
133
- end
134
-
135
- def write_entry(editstring = "")
136
- begin
137
- edited = editstring.edit_externally
138
-
139
- if edited == editstring
140
- puts "You didn't edit anything, aborting."
141
- exit
142
- end
143
-
144
- yaml = YAML.load(edited)
145
-
146
- entry = Atom::Entry.from_yaml yaml
147
-
148
- entry.prepare_for_output
149
-
150
- # XXX disabled until the APP WG can decide what a valid entry is
151
- =begin
152
- valid, message = entry.valid?
153
- unless valid
154
- print "entry is invalid (#{message}). post anyway? (y/n)? "
155
- (gets.chomp == "y") || (raise Atom::InvalidEntry.new)
156
- end
157
- =end
158
-
159
- # this has to be here ATM to we can detect malformed atom:content
160
- puts entry.to_s
161
- rescue ArgumentError,REXML::ParseException => e
162
- puts e
163
-
164
- puts "press enter to edit again..."
165
- $stdin.gets
166
-
167
- editstring = edited
168
-
169
- retry
170
- rescue Atom::InvalidEntry
171
- editstring = edited
172
- retry
173
- end
174
-
175
- [yaml, entry]
176
- end
177
-
178
- module Atom
179
- class InvalidEntry < RuntimeError; end
180
- end
181
-
182
- EDITOR = ENV["EDITOR"] || "env vim"
183
-
184
- http = Atom::HTTP.new
185
-
186
- url = if options[:url]
187
- options[:url]
188
- else
189
- yaml = YAML.load(File.read("#{ENV["HOME"]}/.atom-client"))
190
- collections = yaml["collections"]
191
-
192
- puts "which collection?"
193
-
194
- collections.keys.each_with_index do |name,index|
195
- puts "#{index}: #{name}"
196
- end
197
-
198
- tmp = choose_from collections.values
199
-
200
- http.user = tmp["user"] if tmp["user"]
201
- http.pass = tmp["pass"] if tmp["pass"]
202
-
203
- tmp["url"]
204
- end
205
-
206
- http.user = options[:user] if options[:user]
207
- http.pass = options[:pass] if options[:pass]
208
-
209
- # this is where all the Atom stuff starts
210
-
211
- coll = Atom::Collection.new(url, http)
212
-
213
- # XXX generate a real id
214
- CLIENT_ID = "http://necronomicorp.com/nil"
215
-
216
- new = lambda do
217
- entry = Atom::Entry.new
218
-
219
- entry.title = ""
220
- entry.content = ""
221
-
222
- slug, entry = entry.edit
223
-
224
- entry.id = CLIENT_ID
225
- entry.published = Time.now.iso8601
226
-
227
- res = coll.post! entry, slug
228
-
229
- # XXX error recovery here, lost updates suck
230
- puts res.body
231
- end
232
-
233
- edit = lambda do
234
- coll.update!
235
-
236
- coll.entries.each_with_index do |entry,idx|
237
- puts "#{idx}: #{entry.title}"
238
- end
239
-
240
- entry = choose_from(coll.entries) { |entry| entry.title }
241
-
242
- url = entry.edit_url
243
-
244
- raise "this entry has no edit link" unless url
245
-
246
- entry = http.get_atom_entry url
247
-
248
- slug, new_entry = entry.edit
249
-
250
- res = coll.put! new_entry, url
251
-
252
- # XXX error recovery here, lost updates suck
253
- puts res.body
254
- end
255
-
256
- delete = lambda do
257
- coll.update!
258
-
259
- coll.entries.each_with_index do |entry,idx|
260
- puts "#{idx} #{entry.title}"
261
- end
262
-
263
- entry = choose_from(coll.entries)
264
- res = coll.delete! entry
265
-
266
- puts res.body
267
- end
268
-
269
- actions = [ new, edit, delete ]
270
-
271
- puts "0: new entry"
272
- puts "1: edit entry"
273
- puts "2: delete entry"
274
-
275
- choose_from(actions).call
data/lib/atom/xml.rb DELETED
@@ -1,213 +0,0 @@
1
- require "atom/entry"
2
- require "atom/feed"
3
- require "uri"
4
-
5
- class Atom::ParseError < StandardError; end
6
-
7
- # Two big, interrelated problems:
8
- #
9
- # * I probably shouldn't be playing around in REXML's namespace
10
- # * REXML isn't a great parser, and other options would be nice
11
- #
12
- # This shouldn't be hard to do, it's just tedious and non-critical
13
- module REXML # :nodoc: all
14
- class Document
15
- def to_atom_entry base = ""
16
- raise Atom::ParseError unless self.root
17
- self.root.to_atom_entry base
18
- end
19
- def to_atom_feed base = ""
20
- raise Atom::ParseError unless self.root
21
- self.root.to_atom_feed base
22
- end
23
- end
24
- class Element
25
- def get_atom_element name
26
- XPath.first(self, "./atom:#{name}", { "atom" => Atom::NS })
27
- end
28
-
29
- def each_atom_element name
30
- XPath.each(self, "./atom:#{name}", { "atom" => Atom::NS }) do |elem|
31
- yield elem
32
- end
33
- end
34
-
35
- def copy_extensions(coll)
36
- # XXX also look for attributes
37
- children.find_all do |child|
38
- child.respond_to? :namespace and child.namespace != Atom::NS
39
- end.each do |elem|
40
- e = elem.dup
41
-
42
- # because namespaces might be defined on parents
43
- unless e.prefix.empty?
44
- e.add_namespace e.prefix, e.namespace
45
- end
46
-
47
- coll << e
48
- end
49
- end
50
-
51
- # get the text content of a descendant element in the Atom namespace
52
- def get_atom_text name
53
- elem = get_atom_element name
54
- if elem
55
- elem.text
56
- else
57
- nil
58
- end
59
- end
60
-
61
- # a workaround for the odd way in which REXML handles namespaces
62
- # returns the value of the attribute +name+ that's in the same namespace as this element
63
- def ns_attr name
64
- if not self.prefix.empty?
65
- attr = self.prefix + ":" + name
66
- else
67
- attr = name
68
- end
69
-
70
- self.attributes[attr]
71
- end
72
-
73
- def fill_text_construct(entry, name)
74
- text = get_atom_element(name)
75
- if text
76
- type = text.ns_attr("type")
77
- src = text.ns_attr("src")
78
-
79
- if src and name == :content
80
- # the only content is out of line
81
- entry.send( "#{name}=".to_sym, "")
82
- entry.send(name.to_sym)["src"] = src
83
- elsif type == "xhtml"
84
- div = XPath.first(text, "./xhtml:div", { "xhtml" => XHTML::NS })
85
- unless div
86
- raise Atom::ParseError, "Refusing to parse type='xhtml' with no <div/> wrapper"
87
- end
88
-
89
- # content is the serialized content of the <div> wrapper
90
- entry.send( "#{name}=".to_sym, div )
91
- else
92
- raw = text.text || ""
93
- entry.send( "#{name}=", raw )
94
- end
95
-
96
- if text.attributes["xml:base"]
97
- entry.send(name.to_sym).base = text.attributes["xml:base"]
98
- end
99
-
100
- if type and type != "text"
101
- entry.send(name.to_sym)["type"] = type
102
- end
103
- end
104
- end
105
-
106
- def fill_elem_element(top, kind)
107
- each_atom_element(kind) do |elem|
108
- person = top.send("#{kind}s".to_sym).new
109
-
110
- ["name", "uri", "email"].each do |name|
111
- person.send("#{name}=".to_sym, elem.get_atom_text(name))
112
- end
113
- end
114
- end
115
-
116
- def fill_attr_element(top, array, kind)
117
- each_atom_element(kind) do |elem|
118
- thing = array.new
119
-
120
- thing.class.attrs.each do |name,req|
121
- value = elem.ns_attr name.to_s
122
- if value and name == :href
123
- begin
124
- thing[name.to_s] = (top.base.to_uri + value).to_s
125
- rescue URI::BadURIError
126
- raise "Document contains relative URIs and no xml:base. You must pass a base URI to #parse()"
127
- end
128
- elsif value
129
- thing[name.to_s] = value
130
- end
131
- end
132
- end
133
- end
134
-
135
- # 'base' is the URI that you fetched this document from.
136
- def to_atom_entry base = ""
137
- unless self.name == "entry" and self.namespace == Atom::NS
138
- raise Atom::ParseError, "this isn't an atom:entry! (name: #{self.name}, ns: #{self.namespace})"
139
- end
140
-
141
- entry = Atom::Entry.new
142
-
143
- entry.base = if attributes["xml:base"]
144
- (URI.parse(base) + attributes["xml:base"]).to_s
145
- else
146
- # go with the URL we were passed in
147
- base
148
- end
149
-
150
- # Text constructs
151
- entry.class.elements.find_all { |n,k,r| k.ancestors.member? Atom::Text }.each do |n,k,r|
152
- fill_text_construct(entry, n)
153
- end
154
-
155
- ["id", "published", "updated"].each do |name|
156
- entry.send("#{name}=".to_sym, get_atom_text(name))
157
- end
158
-
159
- ["author", "contributor"].each do |type|
160
- fill_elem_element(entry, type)
161
- end
162
-
163
- {"link" => entry.links, "category" => entry.categories}.each do |k,v|
164
- fill_attr_element(entry, v, k)
165
- end
166
-
167
- copy_extensions(entry.extensions)
168
-
169
- entry
170
- end
171
-
172
- # 'base' is the URI that you fetched this document from.
173
- def to_atom_feed base = ""
174
- unless self.name == "feed" and self.namespace == Atom::NS
175
- raise Atom::ParseError, "this isn't an atom:feed! (name: #{self.name}, ns: #{self.namespace})"
176
- end
177
-
178
- feed = Atom::Feed.new
179
-
180
- feed.base = if attributes["xml:base"]
181
- (URI.parse(base) + attributes["xml:base"]).to_s
182
- else
183
- # go with the URL we were passed in
184
- base
185
- end
186
-
187
- # Text constructs
188
- feed.class.elements.find_all { |n,k,r| k.ancestors.member? Atom::Text }.each do |n,k,r|
189
- fill_text_construct(feed, n)
190
- end
191
-
192
- ["id", "updated", "generator", "icon", "logo"].each do |name|
193
- feed.send("#{name}=".to_sym, get_atom_text(name))
194
- end
195
-
196
- ["author", "contributor"].each do |type|
197
- fill_elem_element(feed, type)
198
- end
199
-
200
- {"link" => feed.links, "category" => feed.categories}.each do |k,v|
201
- fill_attr_element(feed, v, k)
202
- end
203
-
204
- each_atom_element("entry") do |elem|
205
- feed << elem.to_atom_entry(feed.base)
206
- end
207
-
208
- copy_extensions(feed.extensions)
209
-
210
- feed
211
- end
212
- end
213
- end