xoxo 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/HISTORY ADDED
@@ -0,0 +1,14 @@
1
+ = HISTORY
2
+
3
+ == 1.0.0 // 2009-07-06
4
+
5
+ This is essentially the XOXO library written Christian Neukirchen.
6
+ While the library has been distributed as part of Facets for some
7
+ time, there is no separate gem avaialbe for it. So this then is
8
+ that stand-alone release. It differs from the original only in
9
+ that it provides #to_xoxo.
10
+
11
+ * 1 Major Enhancement
12
+
13
+ * Happy Birthday!
14
+
data/LICENSE ADDED
@@ -0,0 +1,61 @@
1
+ = RUBY LICENSE
2
+
3
+ xoxo.rb is copyrighted free software by Christian Neukirchen <chneukirchen@gmail.com>.
4
+ You can redistribute it and/or modify it under either the terms of the GPL
5
+ (see COPYING file), or the conditions below:
6
+
7
+ 1. You may make and give away verbatim copies of the source form of the
8
+ software without restriction, provided that you duplicate all of the
9
+ original copyright notices and associated disclaimers.
10
+
11
+ 2. You may modify your copy of the software in any way, provided that
12
+ you do at least ONE of the following:
13
+
14
+ a) place your modifications in the Public Domain or otherwise
15
+ make them Freely Available, such as by posting said
16
+ modifications to Usenet or an equivalent medium, or by allowing
17
+ the author to include your modifications in the software.
18
+
19
+ b) use the modified software only within your corporation or
20
+ organization.
21
+
22
+ c) rename any non-standard executables so the names do not conflict
23
+ with standard executables, which must also be provided.
24
+
25
+ d) make other distribution arrangements with the author.
26
+
27
+ 3. You may distribute the software in object code or executable
28
+ form, provided that you do at least ONE of the following:
29
+
30
+ a) distribute the executables and library files of the software,
31
+ together with instructions (in the manual page or equivalent)
32
+ on where to get the original distribution.
33
+
34
+ b) accompany the distribution with the machine-readable source of
35
+ the software.
36
+
37
+ c) give non-standard executables non-standard names, with
38
+ instructions on where to get the original software distribution.
39
+
40
+ d) make other distribution arrangements with the author.
41
+
42
+ 4. You may modify and include the part of the software into any other
43
+ software (possibly commercial). But some files in the distribution
44
+ are not written by the author, so that they are not under this terms.
45
+
46
+ They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
47
+ files under the ./missing directory. See each file for the copying
48
+ condition.
49
+
50
+ 5. The scripts and library files supplied as input to or produced as
51
+ output from the software do not automatically fall under the
52
+ copyright of the software, but belong to whomever generated them,
53
+ and may be sold commercially, and may be aggregated with this
54
+ software.
55
+
56
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
57
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
58
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
59
+ PURPOSE.
60
+
61
+
@@ -0,0 +1,20 @@
1
+ test
2
+ test/test_xoxo.rb
3
+ RELEASE
4
+ LICENSE
5
+ README
6
+ HISTORY
7
+ meta
8
+ meta/created
9
+ meta/repository
10
+ meta/homepage
11
+ meta/summary
12
+ meta/abstract
13
+ meta/package
14
+ meta/released
15
+ meta/version
16
+ meta/license
17
+ meta/authors
18
+ meta/project
19
+ lib
20
+ lib/xoxo.rb
data/README ADDED
@@ -0,0 +1,58 @@
1
+ = XOXO
2
+
3
+ * http://death.rubyforge.org
4
+ * http://death.rubyforge.org/xoxo
5
+ * http://chneukirchen.org/repos/xoxo-rb/
6
+
7
+
8
+ == DESCRIPTION
9
+
10
+ XOXO is a Ruby XOXO parser and generator. It provides
11
+ a Ruby API similar to Marshal and YAML (though more
12
+ specific) to load and dump XOXO[http://microformats.org/wiki/xoxo],
13
+ an simple, open outline format written in standard XHTML and
14
+ suitable for embedding in (X)HTML, Atom, RSS, and arbitrary XML.
15
+
16
+
17
+ == FEATURES/ISSUES
18
+
19
+ * Uses REXML's pull parser.
20
+ * Serialize any object via to_xoxo.
21
+
22
+
23
+ == RELEASE NOTES
24
+
25
+ Please see RELEASE file.
26
+
27
+
28
+ == SYNOPSIS
29
+
30
+ Simple way to generate XOXO.
31
+
32
+ obj.to_xoxo
33
+
34
+
35
+ == HOW TO INSTALL
36
+
37
+ To install with RubyGems simply open a console and type:
38
+
39
+ gem install xoxo
40
+
41
+ Local installation requires Setup.rb (gem install setup),
42
+ then download the tarball package and type:
43
+
44
+ tar -xvzf xoxo-1.0.0.tgz
45
+ cd xoxo-1.0.0
46
+ sudo setup.rb all
47
+
48
+ Windows users use 'ruby setup.rb all'.
49
+
50
+
51
+ == COPYING
52
+
53
+ Copyright (C) 2006 Christian Neukirchen
54
+
55
+ This program is ditributed unser the terms of the Ruby license.
56
+
57
+ See LICENSE file for details.
58
+
data/RELEASE ADDED
@@ -0,0 +1,14 @@
1
+ = RELEASE NOTES
2
+
3
+ This is essentially the XOXO library written Christian Neukirchen.
4
+ While the library has been distributed as part of Facets for some
5
+ time, there is no separate gem avaialbe for it. So this then is
6
+ that stand-alone release. It differs from the original only in
7
+ that it provides #to_xoxo.
8
+
9
+ ### 1.0.0 // 2009-07-06
10
+
11
+ * 1 Major Enhancement
12
+
13
+ * Happy Birthday!
14
+
@@ -0,0 +1,241 @@
1
+ # xoxo.rb
2
+ #
3
+ # Copyright (C) 2006 Christian Neukirchen
4
+ #
5
+ # Ruby License
6
+ #
7
+ # This module is free software. You may use, modify, and/or redistribute this
8
+ # software under the same terms as Ruby.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
+ # FOR A PARTICULAR PURPOSE.
13
+ #
14
+ # See original version at http://chneukirchen.org/repos/xoxo-rb/.
15
+
16
+ require 'rexml/parsers/pullparser'
17
+
18
+ # XOXO is a Ruby XOXO parser and generator. It provides
19
+ # a Ruby API similar to Marshal and YAML (though more
20
+ # specific) to load and dump XOXO[http://microformats.org/wiki/xoxo],
21
+ # an simple, open outline format written in standard XHTML and
22
+ # suitable for embedding in (X)HTML, Atom, RSS, and arbitrary XML.
23
+ #
24
+ module XOXO
25
+ # xoxo.rb version number
26
+ #VERSION = "1.0.0"
27
+
28
+ # Load and return a XOXO structure from the String, IO or StringIO or _xoxo_.
29
+ #
30
+ def self.load(xoxo)
31
+ structs = Parser.new(xoxo).parse.structs
32
+ while structs.kind_of?(Array) && structs.size == 1
33
+ structs = structs.first
34
+ end
35
+ structs
36
+ end
37
+
38
+ # Return a XOXO string corresponding to the Ruby object +struct+,
39
+ # translated to the following rules:
40
+ #
41
+ # * Arrays become ordered lists <tt><ol></tt>.
42
+ # * Hashes become definition lists <tt><dl></tt>, keys are
43
+ # stringified with +to_s+.
44
+ # * Everything else becomes stringified with +to_s+ and wrapped in
45
+ # appropriate list elements (<tt><li></tt> or <tt><dt></tt>/<tt><dd></tt>).
46
+ #
47
+ # Additionally, you can pass these options on the _options_ hash:
48
+ # <tt>:html_wrap</tt> => +true+:: Wrap the XOXO with a basic XHTML 1.0
49
+ # Transitional header.
50
+ # <tt>:css</tt> => _css_:: Reference _css_ as stylesheet for the
51
+ # wrapped XOXO document.
52
+ #
53
+ def self.dump(struct, options={})
54
+ struct = [struct] unless struct.kind_of? Array
55
+
56
+ if options[:html_wrap]
57
+ result = <<EOF.strip
58
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN
59
+ http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
60
+ <html xmlns="http://www.w3.org/1999/xhtml"><head profile=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
61
+ EOF
62
+ if options[:css]
63
+ result << %Q[<style type="text/css" >@import "#{options[:css]}";</style>]
64
+ end
65
+
66
+ result << "</head><body>" << make_xoxo(struct, 'xoxo') << "</body></html>"
67
+ else
68
+ result = make_xoxo(struct, 'xoxo')
69
+ end
70
+
71
+ result
72
+ end
73
+
74
+ private
75
+
76
+ def self.make_xoxo(struct, class_name=nil)
77
+ s = ''
78
+ case struct
79
+ when Array
80
+ if class_name
81
+ s << %Q[<ol class="#{class_name}">]
82
+ else
83
+ s << "<ol>"
84
+ end
85
+ struct.each { |item|
86
+ s << "<li>" << make_xoxo(item) << "</li>"
87
+ }
88
+ s << "</ol>"
89
+
90
+ when Hash
91
+ d = struct.dup
92
+ if d.has_key? 'url'
93
+ s << '<a href="' << d['url'].to_s << '" '
94
+ text = d.fetch('text') { d.fetch('title', d['url']) }
95
+ %w[title rel type].each { |tag|
96
+ if d.has_key? tag
97
+ s << tag.to_s << '="' << make_xoxo(d.delete(tag)) << '" '
98
+ end
99
+ }
100
+ s << '>' << make_xoxo(text) << '</a>'
101
+ d.delete 'text'
102
+ d.delete 'url'
103
+ end
104
+
105
+ unless d.empty?
106
+ s << "<dl>"
107
+ d.each { |key, value|
108
+ s << "<dt>" << key.to_s << "</dt><dd>" << make_xoxo(value) << "</dd>"
109
+ }
110
+ s << "</dl>"
111
+ end
112
+
113
+ when String
114
+ s << struct
115
+
116
+ else
117
+ s << struct.to_s # too gentle?
118
+ end
119
+
120
+ s
121
+ end
122
+ end
123
+
124
+ class XOXO::Parser # :nodoc:
125
+ CONTAINER_TAGS = %w{dl ol ul}
126
+
127
+ attr_reader :structs
128
+
129
+ def initialize(xoxo)
130
+ @parser = REXML::Parsers::PullParser.new(xoxo)
131
+
132
+ @textstack = ['']
133
+ @xostack = []
134
+ @structs = []
135
+ @tags = []
136
+ end
137
+
138
+ def parse
139
+ while @parser.has_next?
140
+ res = @parser.pull
141
+
142
+ if res.start_element?
143
+ @tags << res[0]
144
+
145
+ case res[0]
146
+ when "a"
147
+ attrs = normalize_attrs res[1]
148
+ attrs['url'] = attrs['href']
149
+ attrs.delete 'href'
150
+ push attrs
151
+ @textstack << ''
152
+
153
+ when "dl"
154
+ push({})
155
+
156
+ when "ol", "ul"
157
+ push []
158
+
159
+ when "li", "dt", "dd"
160
+ @textstack << ''
161
+
162
+ end
163
+ elsif res.end_element?
164
+ @tags.pop
165
+
166
+ case res[0]
167
+ when "a"
168
+ val = @textstack.pop
169
+ unless val.empty?
170
+ val = '' if @xostack.last['title'] == val
171
+ val = '' if @xostack.last['url'] == val
172
+ @xostack.last['text'] = val unless val.empty?
173
+ end
174
+ @xostack.pop
175
+
176
+ when "dl", "ol", "ul"
177
+ @xostack.pop
178
+
179
+ when "li"
180
+ val = @textstack.pop
181
+ while @structs.last != @xostack.last
182
+ val = @structs.pop
183
+ @xostack.last << val
184
+ end
185
+ @xostack.last << val if val.kind_of? String
186
+
187
+ when "dt"
188
+ # skip
189
+
190
+ when "dd"
191
+ val = @textstack.pop
192
+ key = @textstack.pop
193
+
194
+ val = @structs.pop if @structs.last != @xostack.last
195
+ @xostack.last[key] = val
196
+
197
+ end
198
+ elsif res.text?
199
+ unless @tags.empty? || CONTAINER_TAGS.include?(@tags.last)
200
+ @textstack.last << res[0]
201
+ end
202
+ end
203
+ end
204
+
205
+ self
206
+ end
207
+
208
+ private
209
+
210
+ def normalize_attrs(attrs)
211
+ attrs.keys.find_all { |k, v| k != k.downcase }.each { |k, v|
212
+ v = v.downcase if k == "rel" || k == "type"
213
+ attrs.delete k
214
+ attrs[k.downcase] = v
215
+ }
216
+ attrs
217
+ end
218
+
219
+ def push(struct)
220
+ if struct == {} && @structs.last.kind_of?(Hash) &&
221
+ @structs.last.has_key?('url') &&
222
+ @structs.last != @xostack.last
223
+ # put back the <a>-made one for extra def's
224
+ @xostack << @structs.last
225
+ else
226
+ @structs << struct
227
+ @xostack << @structs.last
228
+ end
229
+ end
230
+ end
231
+
232
+
233
+ class Object
234
+
235
+ # Dump object as XOXO.
236
+
237
+ def to_xoxo(*args)
238
+ XOXO.dump(self,*args)
239
+ end
240
+
241
+ end
@@ -0,0 +1,5 @@
1
+ XOXO is a Ruby XOXO parser and generator. It provides
2
+ a Ruby API similar to Marshal and YAML (though more
3
+ specific) to load and dump XOXO[http://microformats.org/wiki/xoxo],
4
+ an simple, open outline format written in standard XHTML and
5
+ suitable for embedding in (X)HTML, Atom, RSS, and arbitrary XML.
@@ -0,0 +1 @@
1
+ Christian Neukirchen <chneukirchen@gmail.com>
@@ -0,0 +1 @@
1
+ 2006-01-01
@@ -0,0 +1 @@
1
+ http://death.rubyforge.org/
@@ -0,0 +1 @@
1
+ Ruby
@@ -0,0 +1 @@
1
+ xoxo
@@ -0,0 +1 @@
1
+ death
@@ -0,0 +1 @@
1
+ 2009-07-06
@@ -0,0 +1 @@
1
+ svn://rubyforge.org/var/svn/death/xoxo
@@ -0,0 +1 @@
1
+ XOXO Parser and Generator
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,272 @@
1
+ require 'xoxo'
2
+ require 'test/unit'
3
+
4
+ class TC_XOXO < Test::Unit::TestCase
5
+
6
+ def test_simple_list
7
+ l = ['1', '2', '3']
8
+ html = XOXO.dump(l)
9
+ assert_equal '<ol class="xoxo"><li>1</li><li>2</li><li>3</li></ol>', html
10
+ end
11
+
12
+ def test_nested_list
13
+ l = ['1', ['2', '3']]
14
+ assert_equal '<ol class="xoxo"><li>1</li><li><ol><li>2</li><li>3</li></ol></li></ol>', XOXO.dump(l)
15
+ end
16
+
17
+ def test_hash
18
+ h = {'test' => '1', 'name' => 'Kevin'}
19
+ # Changed since Ruby sorts the hash differently.
20
+ assert_equal '<ol class="xoxo"><li><dl><dt>name</dt><dd>Kevin</dd><dt>test</dt><dd>1</dd></dl></li></ol>', XOXO.dump(h)
21
+ end
22
+
23
+ def test_single_item
24
+ l = 'test'
25
+ assert_equal '<ol class="xoxo"><li>test</li></ol>', XOXO.dump(l)
26
+ end
27
+
28
+ def test_wrap_differs
29
+ l = 'test'
30
+ html = XOXO.dump(l)
31
+ html_wrap = XOXO.dump(l, :html_wrap => true)
32
+ assert_not_equal html, html_wrap
33
+ end
34
+
35
+ def test_wrap_single_item
36
+ l = 'test'
37
+ html = XOXO.dump(l, :html_wrap => true)
38
+ assert_equal <<EOF.strip, html
39
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN
40
+ http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
41
+ <html xmlns="http://www.w3.org/1999/xhtml"><head profile=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body><ol class="xoxo"><li>test</li></ol></body></html>
42
+ EOF
43
+ end
44
+
45
+ def test_wrap_item_with_css
46
+ l = 'test'
47
+ html = XOXO.dump(l, :html_wrap => true, :css => 'reaptest.css')
48
+ assert_equal <<EOF.strip, html
49
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN
50
+ http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
51
+ <html xmlns="http://www.w3.org/1999/xhtml"><head profile=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><style type="text/css" >@import "reaptest.css";</style></head><body><ol class="xoxo"><li>test</li></ol></body></html>
52
+ EOF
53
+ end
54
+
55
+ def test_hash_roundtrip
56
+ h = {'test' => '1', 'name' => 'Kevin'}
57
+ assert_equal h, XOXO.load(XOXO.dump(h))
58
+ end
59
+
60
+ def test_hash_with_url_roundtrip
61
+ h = {'url' => 'http://example.com', 'name' => 'Kevin'}
62
+ assert_equal h, XOXO.load(XOXO.dump(h))
63
+ end
64
+
65
+ def test_nested_hash_roundtrip
66
+ h = {'test' => '1', 'inner' => {'name' => 'Kevin'}}
67
+ assert_equal h, XOXO.load(XOXO.dump(h))
68
+ end
69
+
70
+ def test_nested_hash_with_url_roundtrip
71
+ h = {'url' => 'http://example.com', 'inner' => {
72
+ 'url' => 'http://slashdot.org', 'name' => 'Kevin'}}
73
+ assert_equal h, XOXO.load(XOXO.dump(h))
74
+ end
75
+
76
+ def test_list_round_trip
77
+ l = ['3', '2', '1']
78
+ assert_equal l, XOXO.load(XOXO.dump(l))
79
+ end
80
+
81
+ def test_list_of_hashes_round_trip
82
+ l = ['3', {'a' => '2'}, {'b' => '1', 'c' => '4'}]
83
+ assert_equal l, XOXO.load(XOXO.dump(l))
84
+ end
85
+
86
+ def test_list_of_lists_round_trip
87
+ l = ['3', ['a', '2'], ['b', ['1', ['c', '4']]]]
88
+ assert_equal l, XOXO.load(XOXO.dump(l))
89
+ end
90
+
91
+ def test_hashes_of_lists_roundtrip
92
+ h = {
93
+ 'test' => ['1', '2'],
94
+ 'name' => 'Kevin',
95
+ 'nestlist' => ['a', ['b', 'c']],
96
+ 'nestdict' => {'e' => '6', 'f' => '7'}
97
+ }
98
+ assert_equal h, XOXO.load(XOXO.dump(h))
99
+ end
100
+
101
+ def test_xoxo_junk_in_containers
102
+ h = XOXO.load '<ol>bad<li><dl>worse<dt>good</dt><dd>buy</dd> now</dl></li></ol>'
103
+ assert_equal({'good' => 'buy'}, h)
104
+ end
105
+
106
+ def test_xoxo_junk_in_elements
107
+ l = XOXO.load '<ol><li>bad<dl><dt>good</dt><dd>buy</dd></dl>worse</li><li>bag<ol><li>OK</li></ol>fish</li></ol>'
108
+ assert_equal([{'good' => 'buy'}, ['OK']], l)
109
+ end
110
+
111
+ def test_xoxo_with_spaces_and_newlines
112
+ xoxo_sample = <<EOF.strip
113
+ <ol class='xoxo'>
114
+ <li>
115
+ <dl>
116
+ <dt>text</dt>
117
+ <dd>item 1</dd>
118
+ <dt>description</dt>
119
+ <dd> This item represents the main point we're trying to make.</dd>
120
+ <dt>url</dt>
121
+ <dd>http://example.com/more.xoxo</dd>
122
+ <dt>title</dt>
123
+ <dd>title of item 1</dd>
124
+ <dt>type</dt>
125
+ <dd>text/xml</dd>
126
+ <dt>rel</dt>
127
+ <dd>help</dd>
128
+ </dl>
129
+ </li>
130
+ </ol>
131
+ EOF
132
+ h = XOXO.load xoxo_sample
133
+ h2 = {
134
+ 'text' => 'item 1',
135
+ 'description' => " This item represents the main point we're trying to make.",
136
+ 'url' => 'http://example.com/more.xoxo',
137
+ 'title' => 'title of item 1',
138
+ 'type' => 'text/xml',
139
+ 'rel' => 'help'
140
+ }
141
+ assert_equal h2, XOXO.load(xoxo_sample)
142
+ end
143
+
144
+ def test_special_attribute_decoding
145
+ xoxo_sample = <<EOF.strip
146
+ <ol class='xoxo'>
147
+ <li>
148
+ <dl>
149
+ <dt>text</dt>
150
+ <dd>item 1</dd>
151
+ <dt>url</dt>
152
+ <dd>http://example.com/more.xoxo</dd>
153
+ <dt>title</dt>
154
+ <dd>title of item 1</dd>
155
+ <dt>type</dt>
156
+ <dd>text/xml</dd>
157
+ <dt>rel</dt>
158
+ <dd>help</dd>
159
+ </dl>
160
+ </li>
161
+ </ol>
162
+ EOF
163
+ smart_xoxo_sample = <<EOF.strip
164
+ <ol class='xoxo'>
165
+ <li><a href="http://example.com/more.xoxo"
166
+ title="title of item 1"
167
+ type="text/xml"
168
+ rel="help">item 1</a>
169
+ <!-- note how the "text" property is simply the contents of the <a> element -->
170
+ </li>
171
+ </ol>
172
+ EOF
173
+ assert_equal XOXO.load(xoxo_sample), XOXO.load(smart_xoxo_sample)
174
+ end
175
+
176
+ def test_special_attribute_and_dl_decoding
177
+ xoxo_sample = <<EOF.strip
178
+ <ol class="xoxo">
179
+ <li>
180
+ <dl>
181
+ <dt>text</dt>
182
+ <dd>item 1</dd>
183
+ <dt>description</dt>
184
+ <dd> This item represents the main point we're trying to make.</dd>
185
+ <dt>url</dt>
186
+ <dd>http://example.com/more.xoxo</dd>
187
+ <dt>title</dt>
188
+ <dd>title of item 1</dd>
189
+ <dt>type</dt>
190
+ <dd>text/xml</dd>
191
+ <dt>rel</dt>
192
+ <dd>help</dd>
193
+ </dl>
194
+ </li>
195
+ </ol>
196
+ EOF
197
+ smart_xoxo_sample = <<EOF.strip
198
+ <ol class="xoxo">
199
+ <li><a href="http://example.com/more.xoxo"
200
+ title="title of item 1"
201
+ type="text/xml"
202
+ rel="help">item 1</a>
203
+ <!-- note how the "text" property is simply the contents of the <a> element -->
204
+ <dl>
205
+ <dt>description</dt>
206
+ <dd> This item represents the main point we're trying to make.</dd>
207
+ </dl>
208
+ </li>
209
+ </ol>
210
+ EOF
211
+ assert_equal XOXO.load(xoxo_sample), XOXO.load(smart_xoxo_sample)
212
+ end
213
+
214
+ def test_special_attribute_encode
215
+ h = {
216
+ 'url' => 'http://example.com/more.xoxo',
217
+ 'title' => 'sample url',
218
+ 'type' => "text/xml",
219
+ 'rel' => 'help',
220
+ 'text' => 'an example'
221
+ }
222
+ assert_equal '<ol class="xoxo"><li><a href="http://example.com/more.xoxo" title="sample url" rel="help" type="text/xml" >an example</a></li></ol>', XOXO.dump(h)
223
+ end
224
+
225
+ def test_special_attribute_roundtrip_full
226
+ h = {
227
+ 'url' => 'http://example.com/more.xoxo',
228
+ 'title' => 'sample url',
229
+ 'type' => "text/xml",
230
+ 'rel' => 'help',
231
+ 'text' => 'an example'
232
+ }
233
+ assert_equal h, XOXO.load(XOXO.dump(h))
234
+ end
235
+
236
+ def test_special_attribute_roundtrip_no_text
237
+ h = {
238
+ 'url' => 'http://example.com/more.xoxo',
239
+ 'title' => 'sample url',
240
+ 'type' => "text/xml",
241
+ 'rel' => 'help'
242
+ }
243
+ assert_equal h, XOXO.load(XOXO.dump(h))
244
+ end
245
+
246
+ def test_special_attribute_roundtrip_no_text_or_title
247
+ h = {'url' => 'http://example.com/more.xoxo'}
248
+ assert_equal h, XOXO.load(XOXO.dump(h))
249
+ end
250
+
251
+ def test_attention_roundtrip
252
+ kmattn = <<EOF.strip
253
+ <ol class="xoxo"><li><a href="http://www.boingboing.net/" title="Boing Boing Blog" >Boing Boing Blog</a><dl><dt>alturls</dt><dd><ol><li><a href="http://boingboing.net/rss.xml" >xmlurl</a></li></ol></dd><dt>description</dt><dd>Boing Boing Blog</dd></dl></li><li><a href="http://www.financialcryptography.com/" title="Financial Cryptography" >Financial Cryptography</a><dl><dt>alturls</dt><dd><ol><li><a href="http://www.financialcryptography.com/mt/index.rdf" >xmlurl</a></li></ol></dd><dt>description</dt><dd>Financial Cryptography</dd></dl></li><li><a href="http://hublog.hubmed.org/" title="HubLog" >HubLog</a><dl><dt>alturls</dt><dd><ol><li><a href="http://hublog.hubmed.org/index.xml" >xmlurl</a></li><li><a href="http://hublog.hubmed.org/foaf.rdf" >foafurl</a></li></ol></dd><dt>description</dt><dd>HubLog</dd></dl></li></ol>
254
+ EOF
255
+ assert_equal kmattn, XOXO.dump(XOXO.load(kmattn))
256
+ assert_equal XOXO.load(kmattn), XOXO.load(XOXO.dump(XOXO.load(kmattn)))
257
+ assert_equal XOXO.dump(XOXO.load(kmattn)),
258
+ XOXO.dump(XOXO.load(XOXO.dump(XOXO.load(kmattn))))
259
+ end
260
+
261
+ def test_unicode_roundtrip
262
+ unicode = "Tantek \xc3\x87elik and a snowman \xe2\x98\x83"
263
+ assert_equal unicode, XOXO.load(XOXO.dump(unicode))
264
+ end
265
+
266
+ # TBD: Implement proper encodings.
267
+ #
268
+ # def test_utf8_roundtrip
269
+ # end
270
+ # def test_windows1252_roundtrip
271
+ # end
272
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xoxo
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Christian Neukirchen <chneukirchen@gmail.com>
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-06 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: |-
17
+ XOXO is a Ruby XOXO parser and generator. It provides
18
+ a Ruby API similar to Marshal and YAML (though more
19
+ specific) to load and dump XOXO[http://microformats.org/wiki/xoxo],
20
+ an simple, open outline format written in standard XHTML and
21
+ suitable for embedding in (X)HTML, Atom, RSS, and arbitrary XML.
22
+ email: chneukirchen@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README
29
+ - MANIFEST
30
+ - RELEASE
31
+ - LICENSE
32
+ - HISTORY
33
+ files:
34
+ - test/test_xoxo.rb
35
+ - RELEASE
36
+ - LICENSE
37
+ - README
38
+ - HISTORY
39
+ - meta/created
40
+ - meta/repository
41
+ - meta/homepage
42
+ - meta/summary
43
+ - meta/abstract
44
+ - meta/package
45
+ - meta/released
46
+ - meta/version
47
+ - meta/license
48
+ - meta/authors
49
+ - meta/project
50
+ - lib/xoxo.rb
51
+ - MANIFEST
52
+ has_rdoc: true
53
+ homepage: http://death.rubyforge.org/
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --inline-source
59
+ - --title
60
+ - xoxo api
61
+ - --main
62
+ - README
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ requirements: []
78
+
79
+ rubyforge_project: death
80
+ rubygems_version: 1.3.4
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: XOXO is a Ruby XOXO parser and generator.
84
+ test_files:
85
+ - test/test_xoxo.rb