atom-tools 0.9.4 → 1.0.0

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/Rakefile CHANGED
@@ -6,7 +6,7 @@ require "rake/gempackagetask"
6
6
  require "rake/clean"
7
7
 
8
8
  NAME = "atom-tools"
9
- VERS = "0.9.4"
9
+ VERS = "1.0.0"
10
10
 
11
11
  # the following from markaby-0.5's tools/rakehelp
12
12
  def setup_tests
data/bin/atom-client.rb CHANGED
@@ -32,6 +32,7 @@ require "atom/service"
32
32
  require "atom/http"
33
33
 
34
34
  require "rubygems"
35
+ require "bluecloth"
35
36
 
36
37
  require "time"
37
38
 
@@ -62,26 +63,34 @@ class String
62
63
  end
63
64
 
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
+
65
80
  def edit
66
81
  yaml = YAML.load(self.to_yaml)
67
82
 
68
- # delete bits the person doesn't need to see
83
+ # human readability
69
84
  yaml.delete "id"
70
85
 
71
86
  if yaml["links"]
72
- yaml["links"].find_all { |l| ["alternate", "edit"].member? l["rel"] }.each { |l| yaml["links"].delete(l) }
87
+ yaml["links"].find_all { |l| l["rel"] == "alternate" or l["rel"] == "edit" }.each { |l| yaml["links"].delete(l) }
73
88
  yaml.delete("links") if yaml["links"].empty?
74
89
  end
75
-
76
- if self.content
77
- yaml["content"] = $text_filter_before.call(self.content.html)
78
- end
79
-
90
+
80
91
  new_yaml, entry = write_entry(yaml.to_yaml)
81
92
 
82
- # restore deleted bits
83
93
  entry.id = self.id
84
- self.links.each { |l| entry.links << l }
85
94
 
86
95
  [new_yaml["slug"], entry]
87
96
  end
@@ -136,12 +145,7 @@ def write_entry(editstring = "")
136
145
 
137
146
  entry = Atom::Entry.from_yaml yaml
138
147
 
139
- if yaml["content"] #and not yaml["type"]
140
- entry.content, type = $text_filter_after.call(yaml["content"])
141
- entry.content["type"] = (type || "text")
142
- end
143
-
144
- entry.updated!
148
+ entry.prepare_for_output
145
149
 
146
150
  # XXX disabled until the APP WG can decide what a valid entry is
147
151
  =begin
@@ -183,14 +187,6 @@ url = if options[:url]
183
187
  options[:url]
184
188
  else
185
189
  yaml = YAML.load(File.read("#{ENV["HOME"]}/.atom-client"))
186
-
187
- # leave it the way it came in
188
- i = Proc.new { |x| x }
189
- $text_filter_before = eval(yaml["text_filter_before"])
190
- $text_filter_before ||= i
191
- $text_filter_after = eval(yaml["text_filter_after"])
192
- $text_filter_after ||= i
193
-
194
190
  collections = yaml["collections"]
195
191
 
196
192
  puts "which collection?"
data/lib/atom/element.rb CHANGED
@@ -170,7 +170,7 @@ module Atom # :nodoc:
170
170
 
171
171
  self.class.attrs.each do |name,req|
172
172
  value = self[name.to_s]
173
- elem.attributes[name.to_s] = value if value
173
+ elem.attributes[name.to_s] = value.to_s if value
174
174
  end
175
175
 
176
176
  self.extensions.children.each do |element|
data/lib/atom/entry.rb CHANGED
@@ -66,7 +66,11 @@ module Atom
66
66
  elsif xml.respond_to? :read
67
67
  self.parse(xml.read)
68
68
  else
69
- REXML::Document.new(xml.to_s).to_atom_entry(base)
69
+ begin
70
+ REXML::Document.new(xml.to_s).to_atom_entry(base)
71
+ rescue REXML::ParseException
72
+ raise Atom::ParseError
73
+ end
70
74
  end
71
75
  end
72
76
 
data/lib/atom/feed.rb CHANGED
@@ -73,7 +73,11 @@ module Atom
73
73
  elsif xml.respond_to? :read
74
74
  self.parse(xml.read)
75
75
  else
76
- REXML::Document.new(xml.to_s).to_atom_feed(base)
76
+ begin
77
+ REXML::Document.new(xml.to_s).to_atom_feed(base)
78
+ rescue REXML::ParseException
79
+ raise Atom::ParseError
80
+ end
77
81
  end
78
82
  end
79
83
 
@@ -96,6 +100,10 @@ module Atom
96
100
  @entries.each &block
97
101
  end
98
102
 
103
+ def empty?
104
+ @entries.empty?
105
+ end
106
+
99
107
  # gets everything in the logical feed (could be a lot of stuff)
100
108
  # (see <http://www.ietf.org/internet-drafts/draft-nottingham-atompub-feed-history-05.txt>)
101
109
  def get_everything!
@@ -130,7 +138,7 @@ module Atom
130
138
 
131
139
  # like #merge, but in place
132
140
  def merge! other_feed
133
- [:id, :title, :subtitle, :updated, :rights].each { |p|
141
+ [:id, :title, :subtitle, :updated, :rights, :logo, :icon].each { |p|
134
142
  self.send("#{p}=", other_feed.send("#{p}"))
135
143
  }
136
144
 
data/lib/atom/http.rb CHANGED
@@ -14,7 +14,7 @@ class String # :nodoc:
14
14
  end
15
15
 
16
16
  module Atom
17
- UA = "atom-tools 0.9.3"
17
+ UA = "atom-tools 1.0.0"
18
18
 
19
19
  module DigestAuth
20
20
  CNONCE = Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
data/lib/atom/service.rb CHANGED
@@ -5,11 +5,6 @@ require "atom/element"
5
5
  require "atom/collection"
6
6
 
7
7
  module Atom
8
- class WrongNamespace < RuntimeError #:nodoc:
9
- end
10
- class WrongResponse < RuntimeError # :nodoc:
11
- end
12
-
13
8
  # an Atom::Workspace has a #title (Atom::Text) and #collections, an Array of Atom::Collection s
14
9
  class Workspace < Atom::Element
15
10
  element :collections, Atom::Multiple(Atom::Collection)
@@ -23,7 +18,11 @@ module Atom
23
18
  elsif xml.is_a? REXML::Element
24
19
  xml
25
20
  else
26
- REXML::Document.new(xml)
21
+ begin
22
+ REXML::Document.new(xml)
23
+ rescue REXML::ParseException
24
+ raise Atom::ParseError
25
+ end
27
26
  end
28
27
 
29
28
  xml.fill_text_construct(ws, "title")
@@ -42,7 +41,12 @@ module Atom
42
41
  "./app:accept",
43
42
  {"app" => Atom::PP_NS} )
44
43
 
45
- coll.accepts = (accepts ? accepts.text : "entry")
44
+ accepts = []
45
+ REXML::XPath.each(col_el, "./app:accept", {"app" => Atom::PP_NS}) do |a|
46
+ accepts << a.texts.join
47
+ end
48
+
49
+ coll.accepts = (accepts.empty? ? ["application/atom+xml;type=entry"] : accepts)
46
50
 
47
51
  ws.collections << coll
48
52
  end
@@ -62,16 +66,18 @@ module Atom
62
66
  self.collections.each do |coll|
63
67
  el = REXML::Element.new "collection"
64
68
 
65
- el.attributes["href"] = coll.uri
69
+ el.attributes["href"] = coll.uri.to_s
66
70
 
67
71
  title = coll.title.to_element
68
72
  title.name = "atom:title"
69
73
  el << title
70
74
 
71
75
  unless coll.accepts.nil?
72
- accepts = REXML::Element.new "accepts"
73
- accepts.text = coll.accepts
74
- el << accepts
76
+ coll.accepts.each do |acc|
77
+ accept = REXML::Element.new "accept"
78
+ accept.text = acc
79
+ el << accept
80
+ end
75
81
  end
76
82
 
77
83
  root << el
@@ -102,8 +108,8 @@ module Atom
102
108
  res = @http.get(base, "Accept" => "application/atomsvc+xml")
103
109
  res.validate_content_type(["application/atomsvc+xml"])
104
110
 
105
- unless res.code == "200" # XXX needs to handle redirects, &c.
106
- raise WrongResponse, "service document URL responded with unexpected code #{res.code}"
111
+ unless res.code == "200"
112
+ raise Atom::HTTPException, "Unexpected HTTP response code: #{res.code}"
107
113
  end
108
114
 
109
115
  parse(res.body, base)
@@ -128,7 +134,7 @@ module Atom
128
134
  end
129
135
 
130
136
  unless rxml.root.namespace == PP_NS
131
- raise WrongNamespace, "this isn't an atom service document!"
137
+ raise Atom::ParseError, "this isn't an atom service document! (wrong namespace: #{rxml.root.namespace})"
132
138
  end
133
139
 
134
140
  REXML::XPath.match( rxml, "/app:service/app:workspace", {"app" => Atom::PP_NS} ).each do |ws_el|
data/lib/atom/text.rb CHANGED
@@ -105,16 +105,14 @@ module Atom
105
105
  end
106
106
 
107
107
  # this should be done via inheritance
108
- unless self.class == Atom::Content and self["src"]
109
- c = convert_contents e
108
+ c = convert_contents e
110
109
 
111
- if c.is_a? String
112
- e.text = c
113
- elsif c.is_a? REXML::Element
114
- e << c.dup
115
- else
116
- raise RuntimeError, "atom:#{local_name} can't contain type #{@content.class}"
117
- end
110
+ if c.is_a? String
111
+ e.text = c
112
+ elsif c.is_a? REXML::Element
113
+ e << c.dup
114
+ else
115
+ raise RuntimeError, "atom:#{local_name} can't contain type #{@content.class}"
118
116
  end
119
117
 
120
118
  e
@@ -176,6 +174,15 @@ module Atom
176
174
  end
177
175
  end
178
176
 
177
+ def to_element
178
+ if self["src"]
179
+ element_super = Element.instance_method(:to_element)
180
+ return element_super.bind(self).call
181
+ end
182
+
183
+ super
184
+ end
185
+
179
186
  private
180
187
  def valid_type? type
181
188
  super or type.match(/\//)
data/lib/atom/xml.rb CHANGED
@@ -2,6 +2,8 @@ require "atom/entry"
2
2
  require "atom/feed"
3
3
  require "uri"
4
4
 
5
+ class Atom::ParseError < StandardError; end
6
+
5
7
  # Two big, interrelated problems:
6
8
  #
7
9
  # * I probably shouldn't be playing around in REXML's namespace
@@ -11,9 +13,11 @@ require "uri"
11
13
  module REXML # :nodoc: all
12
14
  class Document
13
15
  def to_atom_entry base = ""
16
+ raise Atom::ParseError unless self.root
14
17
  self.root.to_atom_entry base
15
18
  end
16
19
  def to_atom_feed base = ""
20
+ raise Atom::ParseError unless self.root
17
21
  self.root.to_atom_feed base
18
22
  end
19
23
  end
@@ -79,7 +83,7 @@ module REXML # :nodoc: all
79
83
  elsif type == "xhtml"
80
84
  div = XPath.first(text, "./xhtml:div", { "xhtml" => XHTML::NS })
81
85
  unless div
82
- raise "Refusing to parse type='xhtml' with no <div/> wrapper"
86
+ raise Atom::ParseError, "Refusing to parse type='xhtml' with no <div/> wrapper"
83
87
  end
84
88
 
85
89
  # content is the serialized content of the <div> wrapper
@@ -131,7 +135,7 @@ module REXML # :nodoc: all
131
135
  # 'base' is the URI that you fetched this document from.
132
136
  def to_atom_entry base = ""
133
137
  unless self.name == "entry" and self.namespace == Atom::NS
134
- raise TypeError, "this isn't an atom:entry! (name: #{self.name}, ns: #{self.namespace})"
138
+ raise Atom::ParseError, "this isn't an atom:entry! (name: #{self.name}, ns: #{self.namespace})"
135
139
  end
136
140
 
137
141
  entry = Atom::Entry.new
@@ -168,7 +172,7 @@ module REXML # :nodoc: all
168
172
  # 'base' is the URI that you fetched this document from.
169
173
  def to_atom_feed base = ""
170
174
  unless self.name == "feed" and self.namespace == Atom::NS
171
- raise TypeError, "this isn't an atom:feed! (name: #{self.name}, ns: #{self.namespace})"
175
+ raise Atom::ParseError, "this isn't an atom:feed! (name: #{self.name}, ns: #{self.namespace})"
172
176
  end
173
177
 
174
178
  feed = Atom::Feed.new
@@ -43,14 +43,14 @@ END
43
43
  assert_equal "My Blog", ws.title.to_s
44
44
 
45
45
  coll = ws.collections.first
46
- assert_equal URI.parse("http://example.org/myblog/entries"), coll.uri
47
- assert_equal "Entries", coll.title.to_s
48
- assert_equal "entry", coll.accepts
46
+ assert_equal URI.parse("http://example.org/myblog/entries"), coll.uri
47
+ assert_equal "Entries", coll.title.to_s
48
+ assert_equal ["application/atom+xml;type=entry"], coll.accepts
49
49
 
50
50
  coll = ws.collections.last
51
- assert_equal URI.parse("http://example.org/myblog/fotes"), coll.uri
52
- assert_equal "Photos", coll.title.to_s
53
- assert_equal "image/*", coll.accepts
51
+ assert_equal URI.parse("http://example.org/myblog/fotes"), coll.uri
52
+ assert_equal "Photos", coll.title.to_s
53
+ assert_equal ["image/*"], coll.accepts
54
54
 
55
55
  http = service.instance_variable_get(:@http)
56
56
  assert_instance_of Atom::HTTP, http
@@ -74,7 +74,7 @@ END
74
74
 
75
75
  coll = Atom::Collection.new "http://example.org/audio"
76
76
  coll.title = "Audio"
77
- coll.accepts = "audio/*"
77
+ coll.accepts = ["audio/*"]
78
78
  ws.collections << coll
79
79
 
80
80
  nses = { "app" => Atom::PP_NS, "atom" => Atom::NS }
@@ -102,7 +102,7 @@ END
102
102
  title = REXML::XPath.first(entries, "./atom:title", nses)
103
103
  assert_equal "Entries", title.text
104
104
 
105
- accepts = REXML::XPath.first(entries, "./app:accepts", nses)
105
+ accepts = REXML::XPath.first(entries, "./app:accept", nses)
106
106
  assert_nil accepts
107
107
 
108
108
  audio = colls.last
@@ -112,7 +112,7 @@ END
112
112
  title = REXML::XPath.first(audio, "./atom:title", nses)
113
113
  assert_equal "Audio", title.text
114
114
 
115
- accepts = REXML::XPath.first(audio, "./app:accepts", nses)
115
+ accepts = REXML::XPath.first(audio, "./app:accept", nses)
116
116
  assert_equal "audio/*", accepts.text
117
117
  end
118
118
 
data/test/test_xml.rb CHANGED
@@ -146,7 +146,7 @@ class AtomTest < Test::Unit::TestCase
146
146
  assert entry.draft
147
147
  end
148
148
 
149
- def test_extensive_enty_parsing
149
+ def test_extensive_entry_parsing
150
150
  str = '<entry xmlns="http://www.w3.org/2005/Atom">
151
151
  <title>Atom draft-07 snapshot</title>
152
152
  <link rel="alternate" type="text/html"
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: atom-tools
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.9.4
7
- date: 2007-08-11 00:00:00 -06:00
6
+ version: 1.0.0
7
+ date: 2007-11-10 00:00:00 -07:00
8
8
  summary: Tools for working with Atom Entries, Feeds and Collections
9
9
  require_paths:
10
10
  - lib
@@ -39,14 +39,14 @@ files:
39
39
  - test/test_feed.rb
40
40
  - test/test_protocol.rb
41
41
  - test/conformance
42
- - test/test_xml.rb
43
- - test/test_http.rb
44
- - test/test_general.rb
45
42
  - test/conformance/updated.rb
46
43
  - test/conformance/xmlnamespace.rb
47
44
  - test/conformance/title.rb
48
45
  - test/conformance/order.rb
49
46
  - test/conformance/xhtmlcontentdiv.rb
47
+ - test/test_xml.rb
48
+ - test/test_http.rb
49
+ - test/test_general.rb
50
50
  - lib/atom
51
51
  - lib/atom/yaml.rb
52
52
  - lib/atom/feed.rb