builder 3.2.3
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.
- checksums.yaml +7 -0
- data/CHANGES +107 -0
- data/MIT-LICENSE +20 -0
- data/README.md +258 -0
- data/Rakefile +195 -0
- data/doc/jamis.rb +591 -0
- data/doc/releases/builder-1.2.4.rdoc +31 -0
- data/doc/releases/builder-2.0.0.rdoc +46 -0
- data/doc/releases/builder-2.1.1.rdoc +58 -0
- data/lib/blankslate.rb +137 -0
- data/lib/builder.rb +13 -0
- data/lib/builder/blankslate.rb +23 -0
- data/lib/builder/version.rb +8 -0
- data/lib/builder/xchar.rb +197 -0
- data/lib/builder/xmlbase.rb +199 -0
- data/lib/builder/xmlevents.rb +63 -0
- data/lib/builder/xmlmarkup.rb +339 -0
- data/rakelib/publish.rake +20 -0
- data/rakelib/tags.rake +62 -0
- data/rakelib/testing.rake +7 -0
- data/test/helper.rb +12 -0
- data/test/performance.rb +41 -0
- data/test/preload.rb +39 -0
- data/test/test_blankslate.rb +213 -0
- data/test/test_eventbuilder.rb +150 -0
- data/test/test_markupbuilder.rb +611 -0
- data/test/test_method_caching.rb +62 -0
- data/test/test_namecollision.rb +39 -0
- data/test/test_xchar.rb +78 -0
- metadata +87 -0
@@ -0,0 +1,611 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org).
|
5
|
+
# Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net).
|
6
|
+
# All rights reserved.
|
7
|
+
|
8
|
+
# Permission is granted for use, copying, modification, distribution,
|
9
|
+
# and distribution of modified versions of this work as long as the
|
10
|
+
# above copyright notice is included.
|
11
|
+
#++
|
12
|
+
|
13
|
+
require 'helper'
|
14
|
+
require 'preload'
|
15
|
+
require 'builder'
|
16
|
+
require 'builder/xmlmarkup'
|
17
|
+
|
18
|
+
class TestMarkup < Builder::Test
|
19
|
+
def setup
|
20
|
+
@xml = Builder::XmlMarkup.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_create
|
24
|
+
assert_not_nil @xml
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_simple
|
28
|
+
@xml.simple
|
29
|
+
assert_equal "<simple/>", @xml.target!
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_value
|
33
|
+
@xml.value("hi")
|
34
|
+
assert_equal "<value>hi</value>", @xml.target!
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_empty_value
|
38
|
+
@xml.value("")
|
39
|
+
assert_equal "<value></value>", @xml.target!
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_nil_value
|
43
|
+
@xml.value(nil)
|
44
|
+
assert_equal "<value/>", @xml.target!
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_no_value
|
48
|
+
@xml.value()
|
49
|
+
assert_equal "<value/>", @xml.target!
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_nested
|
53
|
+
@xml.outer { |x| x.inner("x") }
|
54
|
+
assert_equal "<outer><inner>x</inner></outer>", @xml.target!
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_attributes
|
58
|
+
@xml.ref(:id => 12)
|
59
|
+
assert_equal %{<ref id="12"/>}, @xml.target!
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_single_quotes_for_attrs
|
63
|
+
@xml = Builder::XmlMarkup.new(:quote => :single)
|
64
|
+
@xml.ref(:id => 12)
|
65
|
+
assert_equal %{<ref id='12'/>}, @xml.target!
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_mixed_quotes_for_attrs
|
69
|
+
@xml = Builder::XmlMarkup.new(:quote => :single)
|
70
|
+
x = Builder::XmlMarkup.new(:target=>@xml, :quote => :double)
|
71
|
+
@xml.ref(:id => 12) do
|
72
|
+
x.link(:id => 13)
|
73
|
+
end
|
74
|
+
assert_equal %{<ref id='12'><link id="13"/></ref>}, @xml.target!
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_string_attributes_are_escaped_by_default
|
78
|
+
@xml.ref(:id => "H&R")
|
79
|
+
assert_equal %{<ref id="H&R"/>}, @xml.target!
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_symbol_attributes_are_unescaped_by_default
|
83
|
+
@xml.ref(:id => :"H&R")
|
84
|
+
assert_equal %{<ref id="H&R"/>}, @xml.target!
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_attributes_escaping_can_be_turned_on
|
88
|
+
@xml = Builder::XmlMarkup.new
|
89
|
+
@xml.ref(:id => "<H&R \"block\">")
|
90
|
+
assert_equal %{<ref id="<H&R "block">"/>}, @xml.target!
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_mixed_attribute_escaping_with_nested_builders
|
94
|
+
x = Builder::XmlMarkup.new(:target=>@xml)
|
95
|
+
@xml.ref(:id=>:"H&R") {
|
96
|
+
x.element(:tag=>"Long&Short")
|
97
|
+
}
|
98
|
+
assert_equal "<ref id=\"H&R\"><element tag=\"Long&Short\"/></ref>",
|
99
|
+
@xml.target!
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_multiple_attributes
|
103
|
+
@xml.ref(:id => 12, :name => "bill")
|
104
|
+
assert_match %r{^<ref( id="12"| name="bill"){2}/>$}, @xml.target!
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_attributes_with_text
|
108
|
+
@xml.a("link", :href=>"http://onestepback.org")
|
109
|
+
assert_equal %{<a href="http://onestepback.org">link</a>}, @xml.target!
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_attributes_with_newlines
|
113
|
+
@xml.abbr("W3C", :title=>"World\nWide\rWeb\r\nConsortium")
|
114
|
+
assert_equal %{<abbr title="World Wide Web Consortium">W3C</abbr>},
|
115
|
+
@xml.target!
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_complex
|
119
|
+
@xml.body(:bg=>"#ffffff") { |x|
|
120
|
+
x.title("T", :style=>"red")
|
121
|
+
}
|
122
|
+
assert_equal %{<body bg="#ffffff"><title style="red">T</title></body>}, @xml.target!
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_funky_symbol
|
126
|
+
@xml.tag!("non-ruby-token", :id=>1) { |x| x.ok }
|
127
|
+
assert_equal %{<non-ruby-token id="1"><ok/></non-ruby-token>}, @xml.target!
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_tag_can_handle_private_method
|
131
|
+
@xml.tag!("loop", :id=>1) { |x| x.ok }
|
132
|
+
assert_equal %{<loop id="1"><ok/></loop>}, @xml.target!
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_no_explicit_marker
|
136
|
+
@xml.p { |x| x.b("HI") }
|
137
|
+
assert_equal "<p><b>HI</b></p>", @xml.target!
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_reference_local_vars
|
141
|
+
n = 3
|
142
|
+
@xml.ol { |x| n.times { x.li(n) } }
|
143
|
+
assert_equal "<ol><li>3</li><li>3</li><li>3</li></ol>", @xml.target!
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_reference_methods
|
147
|
+
@xml.title { |x| x.a { x.b(_name) } }
|
148
|
+
assert_equal "<title><a><b>bob</b></a></title>", @xml.target!
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_append_text
|
152
|
+
@xml.p { |x| x.br; x.text! "HI" }
|
153
|
+
assert_equal "<p><br/>HI</p>", @xml.target!
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_ambiguous_markup
|
157
|
+
ex = assert_raise(ArgumentError) {
|
158
|
+
@xml.h1("data1") { b }
|
159
|
+
}
|
160
|
+
assert_match(/\btext\b/, ex.message)
|
161
|
+
assert_match(/\bblock\b/, ex.message)
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_capitalized_method
|
165
|
+
@xml.P { |x| x.B("hi"); x.BR(); x.EM { x.text! "world" } }
|
166
|
+
assert_equal "<P><B>hi</B><BR/><EM>world</EM></P>", @xml.target!
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_escaping
|
170
|
+
@xml.div { |x| x.text! "<hi>"; x.em("H&R Block") }
|
171
|
+
assert_equal %{<div><hi><em>H&R Block</em></div>}, @xml.target!
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_nil
|
175
|
+
b = Builder::XmlMarkup.new
|
176
|
+
b.tag! "foo", nil
|
177
|
+
assert_equal %{<foo/>}, b.target!
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_nil_without_explicit_nil_handling
|
181
|
+
b = Builder::XmlMarkup.new(:explicit_nil_handling => false)
|
182
|
+
b.tag! "foo", nil
|
183
|
+
assert_equal %{<foo/>}, b.target!
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_nil_with_explicit_nil_handling
|
187
|
+
b = Builder::XmlMarkup.new(:explicit_nil_handling => true)
|
188
|
+
b.tag! "foo", nil
|
189
|
+
assert_equal %{<foo nil="true"/>}, b.target!
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_non_escaping
|
193
|
+
@xml.div("ns:xml"=>:"&xml;") { |x| x << "<h&i>"; x.em("H&R Block") }
|
194
|
+
assert_equal %{<div ns:xml="&xml;"><h&i><em>H&R Block</em></div>}, @xml.target!
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_return_value
|
198
|
+
str = @xml.x("men")
|
199
|
+
assert_equal @xml.target!, str
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_stacked_builders
|
203
|
+
b = Builder::XmlMarkup.new( :target => @xml )
|
204
|
+
b.div { @xml.span { @xml.a("text", :href=>"ref") } }
|
205
|
+
assert_equal "<div><span><a href=\"ref\">text</a></span></div>", @xml.target!
|
206
|
+
end
|
207
|
+
|
208
|
+
def _name
|
209
|
+
"bob"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class TestAttributeEscaping < Builder::Test
|
214
|
+
|
215
|
+
def setup
|
216
|
+
@xml = Builder::XmlMarkup.new
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_element_gt
|
220
|
+
@xml.title('1<2')
|
221
|
+
assert_equal '<title>1<2</title>', @xml.target!
|
222
|
+
end
|
223
|
+
|
224
|
+
def test_element_amp
|
225
|
+
@xml.title('AT&T')
|
226
|
+
assert_equal '<title>AT&T</title>', @xml.target!
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_element_amp2
|
230
|
+
@xml.title('&')
|
231
|
+
assert_equal '<title>&amp;</title>', @xml.target!
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_attr_less
|
235
|
+
@xml.a(:title => '2>1')
|
236
|
+
assert_equal '<a title="2>1"/>', @xml.target!
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_attr_amp
|
240
|
+
@xml.a(:title => 'AT&T')
|
241
|
+
assert_equal '<a title="AT&T"/>', @xml.target!
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_attr_quot
|
245
|
+
@xml.a(:title => '"x"')
|
246
|
+
assert_equal '<a title=""x""/>', @xml.target!
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
class TestNameSpaces < Builder::Test
|
252
|
+
def setup
|
253
|
+
@xml = Builder::XmlMarkup.new(:indent=>2)
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_simple_name_spaces
|
257
|
+
@xml.rdf :RDF
|
258
|
+
assert_equal "<rdf:RDF/>\n", @xml.target!
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_long
|
262
|
+
xml = Builder::XmlMarkup.new(:indent=>2)
|
263
|
+
xml.instruct!
|
264
|
+
xml.rdf :RDF,
|
265
|
+
"xmlns:rdf" => :"&rdf;",
|
266
|
+
"xmlns:rdfs" => :"&rdfs;",
|
267
|
+
"xmlns:xsd" => :"&xsd;",
|
268
|
+
"xmlns:owl" => :"&owl;" do
|
269
|
+
xml.owl :Class, :'rdf:ID'=>'Bird' do
|
270
|
+
xml.rdfs :label, 'bird'
|
271
|
+
xml.rdfs :subClassOf do
|
272
|
+
xml.owl :Restriction do
|
273
|
+
xml.owl :onProperty, 'rdf:resource'=>'#wingspan'
|
274
|
+
xml.owl :maxCardinality,1,'rdf:datatype'=>'&xsd;nonNegativeInteger'
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
assert_match(/^<\?xml/, xml.target!)
|
280
|
+
assert_match(/\n<rdf:RDF/m, xml.target!)
|
281
|
+
assert_match(/xmlns:rdf="&rdf;"/m, xml.target!)
|
282
|
+
assert_match(/<owl:Restriction>/m, xml.target!)
|
283
|
+
end
|
284
|
+
|
285
|
+
def test_ensure
|
286
|
+
xml = Builder::XmlMarkup.new
|
287
|
+
xml.html do
|
288
|
+
xml.body do
|
289
|
+
begin
|
290
|
+
xml.p do
|
291
|
+
raise Exception.new('boom')
|
292
|
+
end
|
293
|
+
rescue Exception => e
|
294
|
+
xml.pre e
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
assert_match %r{<p>}, xml.target!
|
299
|
+
assert_match %r{</p>}, xml.target!
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
class TestDeclarations < Builder::Test
|
304
|
+
def setup
|
305
|
+
@xml = Builder::XmlMarkup.new(:indent=>2)
|
306
|
+
end
|
307
|
+
|
308
|
+
def test_declare
|
309
|
+
@xml.declare! :element
|
310
|
+
assert_equal "<!element>\n", @xml.target!
|
311
|
+
end
|
312
|
+
|
313
|
+
def test_bare_arg
|
314
|
+
@xml.declare! :element, :arg
|
315
|
+
assert_equal"<!element arg>\n", @xml.target!
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_string_arg
|
319
|
+
@xml.declare! :element, "string"
|
320
|
+
assert_equal"<!element \"string\">\n", @xml.target!
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_mixed_args
|
324
|
+
@xml.declare! :element, :x, "y", :z, "-//OASIS//DTD DocBook XML//EN"
|
325
|
+
assert_equal "<!element x \"y\" z \"-//OASIS//DTD DocBook XML//EN\">\n", @xml.target!
|
326
|
+
end
|
327
|
+
|
328
|
+
def test_nested_declarations
|
329
|
+
@xml = Builder::XmlMarkup.new
|
330
|
+
@xml.declare! :DOCTYPE, :chapter do |x|
|
331
|
+
x.declare! :ELEMENT, :chapter, "(title,para+)".intern
|
332
|
+
end
|
333
|
+
assert_equal "<!DOCTYPE chapter [<!ELEMENT chapter (title,para+)>]>", @xml.target!
|
334
|
+
end
|
335
|
+
|
336
|
+
def test_nested_indented_declarations
|
337
|
+
@xml.declare! :DOCTYPE, :chapter do |x|
|
338
|
+
x.declare! :ELEMENT, :chapter, "(title,para+)".intern
|
339
|
+
end
|
340
|
+
assert_equal "<!DOCTYPE chapter [\n <!ELEMENT chapter (title,para+)>\n]>\n", @xml.target!
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_complex_declaration
|
344
|
+
@xml.declare! :DOCTYPE, :chapter do |x|
|
345
|
+
x.declare! :ELEMENT, :chapter, "(title,para+)".intern
|
346
|
+
x.declare! :ELEMENT, :title, "(#PCDATA)".intern
|
347
|
+
x.declare! :ELEMENT, :para, "(#PCDATA)".intern
|
348
|
+
end
|
349
|
+
expected = %{<!DOCTYPE chapter [
|
350
|
+
<!ELEMENT chapter (title,para+)>
|
351
|
+
<!ELEMENT title (#PCDATA)>
|
352
|
+
<!ELEMENT para (#PCDATA)>
|
353
|
+
]>
|
354
|
+
}
|
355
|
+
assert_equal expected, @xml.target!
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
|
360
|
+
class TestSpecialMarkup < Builder::Test
|
361
|
+
def setup
|
362
|
+
@xml = Builder::XmlMarkup.new(:indent=>2)
|
363
|
+
end
|
364
|
+
|
365
|
+
def test_comment
|
366
|
+
@xml.comment!("COMMENT")
|
367
|
+
assert_equal "<!-- COMMENT -->\n", @xml.target!
|
368
|
+
end
|
369
|
+
|
370
|
+
def test_indented_comment
|
371
|
+
@xml.p { @xml.comment! "OK" }
|
372
|
+
assert_equal "<p>\n <!-- OK -->\n</p>\n", @xml.target!
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_instruct
|
376
|
+
@xml.instruct! :abc, :version=>"0.9"
|
377
|
+
assert_equal "<?abc version=\"0.9\"?>\n", @xml.target!
|
378
|
+
end
|
379
|
+
|
380
|
+
def test_indented_instruct
|
381
|
+
@xml.p { @xml.instruct! :xml }
|
382
|
+
assert_match %r{<p>\n <\?xml version="1.0" encoding="UTF-8"\?>\n</p>\n},
|
383
|
+
@xml.target!
|
384
|
+
end
|
385
|
+
|
386
|
+
def test_instruct_without_attributes
|
387
|
+
@xml.instruct! :zz
|
388
|
+
assert_equal "<?zz?>\n", @xml.target!
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_xml_instruct
|
392
|
+
@xml.instruct!
|
393
|
+
assert_match(/^<\?xml version="1.0" encoding="UTF-8"\?>$/, @xml.target!)
|
394
|
+
end
|
395
|
+
|
396
|
+
def test_xml_instruct_with_overrides
|
397
|
+
@xml.instruct! :xml, :encoding=>"UCS-2"
|
398
|
+
assert_match(/^<\?xml version="1.0" encoding="UCS-2"\?>$/, @xml.target!)
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_xml_instruct_with_standalong
|
402
|
+
@xml.instruct! :xml, :encoding=>"UCS-2", :standalone=>"yes"
|
403
|
+
assert_match(/^<\?xml version="1.0" encoding="UCS-2" standalone="yes"\?>$/, @xml.target!)
|
404
|
+
end
|
405
|
+
|
406
|
+
def test_no_blocks
|
407
|
+
assert_raise(Builder::IllegalBlockError) do
|
408
|
+
@xml.instruct! { |x| x.hi }
|
409
|
+
end
|
410
|
+
assert_raise(Builder::IllegalBlockError) do
|
411
|
+
@xml.comment!(:element) { |x| x.hi }
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
def test_cdata
|
416
|
+
@xml.cdata!("TEST")
|
417
|
+
assert_equal "<![CDATA[TEST]]>\n", @xml.target!
|
418
|
+
end
|
419
|
+
|
420
|
+
def test_cdata_with_ampersand
|
421
|
+
@xml.cdata!("TEST&CHECK")
|
422
|
+
assert_equal "<![CDATA[TEST&CHECK]]>\n", @xml.target!
|
423
|
+
end
|
424
|
+
|
425
|
+
def test_cdata_with_included_close
|
426
|
+
@xml.cdata!("TEST]]>CHECK")
|
427
|
+
assert_equal "<![CDATA[TEST]]]]><![CDATA[>CHECK]]>\n", @xml.target!
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
class TestIndentedXmlMarkup < Builder::Test
|
432
|
+
def setup
|
433
|
+
@xml = Builder::XmlMarkup.new(:indent=>2)
|
434
|
+
end
|
435
|
+
|
436
|
+
def test_one_level
|
437
|
+
@xml.ol { |x| x.li "text" }
|
438
|
+
assert_equal "<ol>\n <li>text</li>\n</ol>\n", @xml.target!
|
439
|
+
end
|
440
|
+
|
441
|
+
def test_two_levels
|
442
|
+
@xml.p { |x|
|
443
|
+
x.ol { x.li "text" }
|
444
|
+
x.br
|
445
|
+
}
|
446
|
+
assert_equal "<p>\n <ol>\n <li>text</li>\n </ol>\n <br/>\n</p>\n", @xml.target!
|
447
|
+
end
|
448
|
+
|
449
|
+
def test_initial_level
|
450
|
+
@xml = Builder::XmlMarkup.new(:indent=>2, :margin=>4)
|
451
|
+
@xml.name { |x| x.first("Jim") }
|
452
|
+
assert_equal " <name>\n <first>Jim</first>\n </name>\n", @xml.target!
|
453
|
+
end
|
454
|
+
|
455
|
+
class TestUtfMarkup < Builder::Test
|
456
|
+
if ! String.method_defined?(:encode)
|
457
|
+
def setup
|
458
|
+
@old_kcode = $KCODE
|
459
|
+
end
|
460
|
+
|
461
|
+
def teardown
|
462
|
+
$KCODE = @old_kcode
|
463
|
+
end
|
464
|
+
|
465
|
+
def test_use_entities_if_no_encoding_is_given_and_kcode_is_none
|
466
|
+
$KCODE = 'NONE'
|
467
|
+
xml = Builder::XmlMarkup.new
|
468
|
+
xml.p("\xE2\x80\x99")
|
469
|
+
assert_match(%r(<p>’</p>), xml.target!) #
|
470
|
+
end
|
471
|
+
|
472
|
+
def test_use_entities_if_encoding_is_utf_but_kcode_is_not
|
473
|
+
$KCODE = 'NONE'
|
474
|
+
xml = Builder::XmlMarkup.new
|
475
|
+
xml.instruct!(:xml, :encoding => 'UTF-8')
|
476
|
+
xml.p("\xE2\x80\x99")
|
477
|
+
assert_match(%r(<p>’</p>), xml.target!) #
|
478
|
+
end
|
479
|
+
else
|
480
|
+
# change in behavior. As there is no $KCODE anymore, the default
|
481
|
+
# moves from "does not understand utf-8" to "supports utf-8".
|
482
|
+
|
483
|
+
def test_use_entities_if_no_encoding_is_given_and_kcode_is_none
|
484
|
+
xml = Builder::XmlMarkup.new
|
485
|
+
xml.p("\xE2\x80\x99")
|
486
|
+
assert_match("<p>\u2019</p>", xml.target!) #
|
487
|
+
end
|
488
|
+
|
489
|
+
def test_use_entities_if_encoding_is_utf_but_kcode_is_not
|
490
|
+
xml = Builder::XmlMarkup.new
|
491
|
+
xml.instruct!(:xml, :encoding => 'UTF-8')
|
492
|
+
xml.p("\xE2\x80\x99")
|
493
|
+
assert_match("<p>\u2019</p>", xml.target!) #
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
def encode string, encoding
|
498
|
+
if !String.method_defined?(:encode)
|
499
|
+
$KCODE = encoding
|
500
|
+
string
|
501
|
+
elsif encoding == 'UTF8'
|
502
|
+
string.force_encoding('UTF-8')
|
503
|
+
else
|
504
|
+
string
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
def test_use_entities_if_kcode_is_utf_but_encoding_is_dummy_encoding
|
509
|
+
xml = Builder::XmlMarkup.new
|
510
|
+
xml.instruct!(:xml, :encoding => 'UTF-16')
|
511
|
+
xml.p(encode("\xE2\x80\x99", 'UTF8'))
|
512
|
+
assert_match(%r(<p>’</p>), xml.target!) #
|
513
|
+
end
|
514
|
+
|
515
|
+
def test_use_entities_if_kcode_is_utf_but_encoding_is_unsupported_encoding
|
516
|
+
xml = Builder::XmlMarkup.new
|
517
|
+
xml.instruct!(:xml, :encoding => 'UCS-2')
|
518
|
+
xml.p(encode("\xE2\x80\x99", 'UTF8'))
|
519
|
+
assert_match(%r(<p>’</p>), xml.target!) #
|
520
|
+
end
|
521
|
+
|
522
|
+
def test_use_utf8_if_encoding_defaults_and_kcode_is_utf8
|
523
|
+
xml = Builder::XmlMarkup.new
|
524
|
+
xml.p(encode("\xE2\x80\x99",'UTF8'))
|
525
|
+
assert_equal encode("<p>\xE2\x80\x99</p>",'UTF8'), xml.target!
|
526
|
+
end
|
527
|
+
|
528
|
+
def test_use_utf8_if_both_encoding_and_kcode_are_utf8
|
529
|
+
xml = Builder::XmlMarkup.new
|
530
|
+
xml.instruct!(:xml, :encoding => 'UTF-8')
|
531
|
+
xml.p(encode("\xE2\x80\x99",'UTF8'))
|
532
|
+
assert_match encode("<p>\xE2\x80\x99</p>",'UTF8'), xml.target!
|
533
|
+
end
|
534
|
+
|
535
|
+
def test_use_utf8_if_both_encoding_and_kcode_are_utf8_with_lowercase
|
536
|
+
xml = Builder::XmlMarkup.new
|
537
|
+
xml.instruct!(:xml, :encoding => 'utf-8')
|
538
|
+
xml.p(encode("\xE2\x80\x99",'UTF8'))
|
539
|
+
assert_match encode("<p>\xE2\x80\x99</p>",'UTF8'), xml.target!
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
class TestXmlEvents < Builder::Test
|
544
|
+
def setup
|
545
|
+
@handler = EventHandler.new
|
546
|
+
@xe = Builder::XmlEvents.new(:target=>@handler)
|
547
|
+
end
|
548
|
+
|
549
|
+
def test_simple
|
550
|
+
@xe.p
|
551
|
+
assert_equal [:start, :p, nil], @handler.events.shift
|
552
|
+
assert_equal [:end, :p], @handler.events.shift
|
553
|
+
end
|
554
|
+
|
555
|
+
def test_text
|
556
|
+
@xe.p("HI")
|
557
|
+
assert_equal [:start, :p, nil], @handler.events.shift
|
558
|
+
assert_equal [:text, "HI"], @handler.events.shift
|
559
|
+
assert_equal [:end, :p], @handler.events.shift
|
560
|
+
end
|
561
|
+
|
562
|
+
def test_attributes
|
563
|
+
@xe.p("id"=>"2")
|
564
|
+
ev = @handler.events.shift
|
565
|
+
assert_equal [:start, :p], ev[0,2]
|
566
|
+
assert_equal "2", ev[2]['id']
|
567
|
+
assert_equal [:end, :p], @handler.events.shift
|
568
|
+
end
|
569
|
+
|
570
|
+
def test_indented
|
571
|
+
@xml = Builder::XmlEvents.new(:indent=>2, :target=>@handler)
|
572
|
+
@xml.p { |x| x.b("HI") }
|
573
|
+
assert_equal [:start, :p, nil], @handler.events.shift
|
574
|
+
assert_equal "\n ", pop_text
|
575
|
+
assert_equal [:start, :b, nil], @handler.events.shift
|
576
|
+
assert_equal "HI", pop_text
|
577
|
+
assert_equal [:end, :b], @handler.events.shift
|
578
|
+
assert_equal "\n", pop_text
|
579
|
+
assert_equal [:end, :p], @handler.events.shift
|
580
|
+
end
|
581
|
+
|
582
|
+
def pop_text
|
583
|
+
result = ''
|
584
|
+
while ! @handler.events.empty? && @handler.events[0][0] == :text
|
585
|
+
result << @handler.events[0][1]
|
586
|
+
@handler.events.shift
|
587
|
+
end
|
588
|
+
result
|
589
|
+
end
|
590
|
+
|
591
|
+
class EventHandler
|
592
|
+
attr_reader :events
|
593
|
+
def initialize
|
594
|
+
@events = []
|
595
|
+
end
|
596
|
+
|
597
|
+
def start_tag(sym, attrs)
|
598
|
+
@events << [:start, sym, attrs]
|
599
|
+
end
|
600
|
+
|
601
|
+
def end_tag(sym)
|
602
|
+
@events << [:end, sym]
|
603
|
+
end
|
604
|
+
|
605
|
+
def text(txt)
|
606
|
+
@events << [:text, txt]
|
607
|
+
end
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
end
|