htree 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data.tar.gz.sig +4 -0
  2. data/Makefile +20 -0
  3. data/Manifest +58 -0
  4. data/README +61 -0
  5. data/Rakefile +37 -0
  6. data/htree.gemspec +32 -0
  7. data/init.rb +1 -0
  8. data/install.rb +112 -0
  9. data/lib/htree.rb +97 -0
  10. data/lib/htree/container.rb +8 -0
  11. data/lib/htree/context.rb +69 -0
  12. data/lib/htree/display.rb +46 -0
  13. data/lib/htree/doc.rb +149 -0
  14. data/lib/htree/elem.rb +262 -0
  15. data/lib/htree/encoder.rb +217 -0
  16. data/lib/htree/equality.rb +219 -0
  17. data/lib/htree/extract_text.rb +37 -0
  18. data/lib/htree/fstr.rb +32 -0
  19. data/lib/htree/gencode.rb +193 -0
  20. data/lib/htree/htmlinfo.rb +672 -0
  21. data/lib/htree/inspect.rb +108 -0
  22. data/lib/htree/leaf.rb +92 -0
  23. data/lib/htree/loc.rb +369 -0
  24. data/lib/htree/modules.rb +49 -0
  25. data/lib/htree/name.rb +122 -0
  26. data/lib/htree/output.rb +212 -0
  27. data/lib/htree/parse.rb +410 -0
  28. data/lib/htree/raw_string.rb +127 -0
  29. data/lib/htree/regexp-util.rb +19 -0
  30. data/lib/htree/rexml.rb +131 -0
  31. data/lib/htree/scan.rb +176 -0
  32. data/lib/htree/tag.rb +113 -0
  33. data/lib/htree/template.rb +961 -0
  34. data/lib/htree/text.rb +115 -0
  35. data/lib/htree/traverse.rb +497 -0
  36. data/test-all.rb +5 -0
  37. data/test/assign.html +1 -0
  38. data/test/template.html +4 -0
  39. data/test/test-attr.rb +67 -0
  40. data/test/test-charset.rb +79 -0
  41. data/test/test-context.rb +29 -0
  42. data/test/test-display_xml.rb +45 -0
  43. data/test/test-elem-new.rb +101 -0
  44. data/test/test-encoder.rb +53 -0
  45. data/test/test-equality.rb +55 -0
  46. data/test/test-extract_text.rb +18 -0
  47. data/test/test-gencode.rb +27 -0
  48. data/test/test-leaf.rb +25 -0
  49. data/test/test-loc.rb +60 -0
  50. data/test/test-namespace.rb +147 -0
  51. data/test/test-output.rb +133 -0
  52. data/test/test-parse.rb +115 -0
  53. data/test/test-raw_string.rb +17 -0
  54. data/test/test-rexml.rb +70 -0
  55. data/test/test-scan.rb +153 -0
  56. data/test/test-security.rb +37 -0
  57. data/test/test-subnode.rb +142 -0
  58. data/test/test-template.rb +313 -0
  59. data/test/test-text.rb +43 -0
  60. data/test/test-traverse.rb +69 -0
  61. metadata +166 -0
  62. metadata.gz.sig +1 -0
@@ -0,0 +1,17 @@
1
+ require 'test/unit'
2
+ require 'htree'
3
+
4
+ class TestRawString < Test::Unit::TestCase
5
+ def test_elem
6
+ t = HTree.parse("<a>x</a>")
7
+ assert_equal("<a>x</a>", t.root.raw_string)
8
+ assert_equal("<a>x</a>", t.root.raw_string) # raw_string shouldn't have side effect.
9
+ end
10
+
11
+ def test_no_raw_string
12
+ t = HTree::Elem.new('a')
13
+ assert_equal(nil, t.raw_string)
14
+ t = HTree::Elem.new('a', HTree.parse("<a>x</a>").root)
15
+ assert_equal(nil, t.raw_string)
16
+ end
17
+ end
@@ -0,0 +1,70 @@
1
+ require 'test/unit'
2
+ require 'htree/parse'
3
+ require 'htree/rexml'
4
+ begin
5
+ require 'rexml/document'
6
+ rescue LoadError
7
+ end
8
+
9
+ class TestREXML < Test::Unit::TestCase
10
+ def test_doc
11
+ r = HTree.parse('<root/>').to_rexml
12
+ assert_instance_of(REXML::Document, r)
13
+ end
14
+
15
+ def test_elem
16
+ r = HTree.parse('<root a="b"/>').to_rexml
17
+ assert_instance_of(REXML::Element, e = r.root)
18
+ assert_equal('root', e.name)
19
+ assert_equal('b', e.attribute('a').to_s)
20
+ end
21
+
22
+ def test_text
23
+ r = HTree.parse('<root>aaa</root>').to_rexml
24
+ assert_instance_of(REXML::Text, t = r.root.children[0])
25
+ assert_equal('aaa', t.to_s)
26
+ end
27
+
28
+ def test_xmldecl
29
+ s = '<?xml version="1.0"?>'
30
+ r = HTree.parse(s + '<root>aaa</root>').to_rexml
31
+ assert_instance_of(REXML::XMLDecl, x = r.children[0])
32
+ assert_equal('1.0', x.version)
33
+ assert_equal(nil, x.standalone)
34
+
35
+ assert_instance_of(REXML::XMLDecl, HTree.parse(s).children[0].to_rexml)
36
+ end
37
+
38
+ def test_doctype
39
+ s = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
40
+ r = HTree.parse(s + '<html><title>xxx</title></html>').to_rexml
41
+ assert_instance_of(REXML::DocType, d = r.children[0])
42
+ assert_equal('html', d.name)
43
+ assert_equal('PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"', d.external_id)
44
+
45
+ assert_instance_of(REXML::DocType, HTree.parse(s).children[0].to_rexml)
46
+ end
47
+
48
+ def test_procins
49
+ r = HTree.parse('<root><?xxx yyy?></root>').to_rexml
50
+ assert_instance_of(REXML::Instruction, i = r.root.children[0])
51
+ assert_equal('xxx', i.target)
52
+ assert_equal('yyy', i.content)
53
+
54
+ assert_instance_of(REXML::Instruction, HTree.parse('<?xxx yyy?>').children[0].to_rexml)
55
+ end
56
+
57
+ def test_comment
58
+ r = HTree.parse('<root><!-- zzz --></root>').to_rexml
59
+ assert_instance_of(REXML::Comment, c = r.root.children[0])
60
+ assert_equal(' zzz ', c.to_s)
61
+ end
62
+
63
+ def test_bogusetag
64
+ assert_equal(nil, HTree.parse('</e>').children[0].to_rexml)
65
+ end
66
+
67
+ def test_style
68
+ assert_equal('<style>a&lt;b</style>', HTree.parse('<html><style>a<b</style></html>').to_rexml.to_s[/<style.*style>/])
69
+ end
70
+ end if defined? REXML
@@ -0,0 +1,153 @@
1
+ require 'test/unit'
2
+ require 'htree/scan'
3
+
4
+ class TestScan < Test::Unit::TestCase
5
+ def scan(str)
6
+ result = []
7
+ HTree.scan(str) {|e| result << e }
8
+ result
9
+ end
10
+
11
+ def test_empty
12
+ assert_equal([], scan(''))
13
+ end
14
+
15
+ def t_single(s)
16
+ n = yield
17
+ assert_equal([n], scan(s))
18
+ end
19
+
20
+ def test_single
21
+ s = '<?xml version="1.0"?>'
22
+ assert_equal([[:xmldecl, s]], scan(s))
23
+
24
+ s = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
25
+ assert_equal([[:doctype, s]], scan(s))
26
+
27
+ s = '<?xxx yyy?>'
28
+ assert_equal([[:procins, s]], scan(s))
29
+
30
+ s = '<a>'
31
+ assert_equal([[:stag, s]], scan(s))
32
+ s = '</a>'
33
+ assert_equal([[:etag, s]], scan(s))
34
+ s = '<a/>'
35
+ assert_equal([[:emptytag, s]], scan(s))
36
+ s = '<!-- abc -->'
37
+ assert_equal([[:comment, s]], scan(s))
38
+ s = '<![CDATA[abc]]>'
39
+ assert_equal([[:text_cdata_section, s]], scan(s))
40
+ s = 'abc'
41
+ assert_equal([[:text_pcdata, s]], scan(s))
42
+ end
43
+
44
+ def test_xmldecl_seen
45
+ s0 = '<?xml version="1.0"?>'
46
+ s1 = '<A>'
47
+ assert_equal([[:stag, s1]], scan(s1))
48
+ assert_equal([[:xmldecl, s0], [:stag, s1]], scan(s0 + s1))
49
+ end
50
+
51
+ def test_cdata_content
52
+ s = '<html><script><a></script><a>'
53
+ assert_equal([
54
+ [:stag, '<html>'],
55
+ [:stag, '<script>'],
56
+ [:text_cdata_content, '<a>'],
57
+ [:etag, '</script>'],
58
+ [:stag, '<a>'],
59
+ ], scan(s))
60
+
61
+ s = '<html><script><a>'
62
+ assert_equal([
63
+ [:stag, '<html>'],
64
+ [:stag, '<script>'],
65
+ [:text_cdata_content, '<a>'],
66
+ ], scan(s))
67
+ end
68
+
69
+ def test_text
70
+ s = 'a<e>b<e>c<e>d'
71
+ assert_equal([
72
+ [:text_pcdata, 'a'],
73
+ [:stag, '<e>'],
74
+ [:text_pcdata, 'b'],
75
+ [:stag, '<e>'],
76
+ [:text_pcdata, 'c'],
77
+ [:stag, '<e>'],
78
+ [:text_pcdata, 'd'],
79
+ ], scan(s))
80
+ end
81
+
82
+ def test_eol_html
83
+ # In SGML, a line break just after start tag and
84
+ # a line break just before end tag is ignored.
85
+ # http://www.w3.org/TR/REC-html40/appendix/notes.html#notes-line-breaks
86
+ #
87
+ # But usual browser including mozilla doesn't.
88
+ # So HTree doesn't ignore them and treat as usual text.
89
+ s = "<html>a\n<e>\nb\n<f>\nc\n</f>\nd\n</e>\ne"
90
+ assert_equal([
91
+ [:stag, "<html>"],
92
+ [:text_pcdata, "a\n"],
93
+ [:stag, "<e>"],
94
+ [:text_pcdata, "\nb\n"],
95
+ [:stag, "<f>"],
96
+ [:text_pcdata, "\nc\n"],
97
+ [:etag, "</f>"],
98
+ [:text_pcdata, "\nd\n"],
99
+ [:etag, "</e>"],
100
+ [:text_pcdata, "\ne"],
101
+ ], scan(s))
102
+
103
+ s = "<html>a\n<e>\nb\n<script>\nc\n</script>\nd\n</e>\ne"
104
+ assert_equal([
105
+ [:stag, "<html>"],
106
+ [:text_pcdata, "a\n"],
107
+ [:stag, "<e>"],
108
+ [:text_pcdata, "\nb\n"],
109
+ [:stag, "<script>"],
110
+ [:text_cdata_content, "\nc\n"],
111
+ [:etag, "</script>"],
112
+ [:text_pcdata, "\nd\n"],
113
+ [:etag, "</e>"],
114
+ [:text_pcdata, "\ne"],
115
+ ], scan(s))
116
+
117
+ end
118
+
119
+ def test_eol_xml
120
+ # In XML, line breaks are treated as part of content.
121
+ # It's because KEEPRSRE is yes in XML.
122
+ # http://www.satoshii.org/markup/websgml/valid-xml#keeprsre
123
+ s = "<?xml version='1.0'?>a\n<e>\nb\n<f>\nc\n</f>\nd\n</e>\ne"
124
+ assert_equal([
125
+ [:xmldecl, "<?xml version='1.0'?>"],
126
+ [:text_pcdata, "a\n"],
127
+ [:stag, "<e>"],
128
+ [:text_pcdata, "\nb\n"],
129
+ [:stag, "<f>"],
130
+ [:text_pcdata, "\nc\n"],
131
+ [:etag, "</f>"],
132
+ [:text_pcdata, "\nd\n"],
133
+ [:etag, "</e>"],
134
+ [:text_pcdata, "\ne"],
135
+ ], scan(s))
136
+ end
137
+
138
+ def test_xml_html_detection
139
+ assert_equal([false, true], HTree.scan("<html></html>") {})
140
+ assert_equal([true, false], HTree.scan("<rss></rss>") {})
141
+ assert_equal([true, true], HTree.scan('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">') {})
142
+ end
143
+
144
+ def test_quoted_attr
145
+ assert_equal([[:emptytag, '<e a=">"/>']], scan('<e a=">"/>'))
146
+ end
147
+
148
+ def test_bare_slash
149
+ assert_equal([[:stag, '<n dir=/foo/bar/>']], scan('<n dir=/foo/bar/>'))
150
+ assert_equal([[:stag, '<n a=v/>']], scan('<n a=v/>'))
151
+ end
152
+
153
+ end
@@ -0,0 +1,37 @@
1
+ require 'test/unit'
2
+ require 'htree/parse'
3
+ require 'htree/template'
4
+ require 'pathname'
5
+
6
+ class TestSecurity < Test::Unit::TestCase
7
+ def safe(n)
8
+ assert_equal(0, $SAFE)
9
+ Thread.new {
10
+ $SAFE = n
11
+ assert_equal(n, $SAFE)
12
+ yield
13
+ }.join
14
+ assert_equal(0, $SAFE)
15
+ end
16
+
17
+ def test_parse
18
+ safe(1) {
19
+ assert_equal(1, $SAFE)
20
+ assert_nothing_raised { HTree.parse("") }
21
+ assert_raise(SecurityError) { HTree.parse("".taint) }
22
+ }
23
+ assert_nothing_raised { HTree.parse("") }
24
+ assert_nothing_raised { HTree.parse("".taint) }
25
+ end
26
+
27
+ def test_template
28
+ safe(1) {
29
+ assert_nothing_raised { HTree.expand_template("/dev/null", nil, '') }
30
+ assert_raise(SecurityError) { HTree.expand_template("/dev/null".taint, nil, '') }
31
+ }
32
+ assert_nothing_raised { HTree.expand_template("/dev/null", nil, '') }
33
+ assert_nothing_raised { HTree.expand_template("/dev/null".taint, nil, '') }
34
+ end
35
+
36
+ end
37
+
@@ -0,0 +1,142 @@
1
+ require 'test/unit'
2
+ require 'htree'
3
+
4
+ class TestSubnode < Test::Unit::TestCase
5
+ def test_elem_get
6
+ e1 = HTree.parse("<a href=x>abc</a>").root
7
+ assert_equal(HTree::Text.new("x"), e1.get_subnode("href"))
8
+ assert_equal(HTree::Text.new("abc"), e1.get_subnode(0))
9
+ end
10
+
11
+ def test_elem_subst
12
+ e1 = HTree.parse_xml("<a href=x>abc</a>").root
13
+ e2 = e1.subst_subnode("href"=>"xxx", 0=>"def")
14
+ assert_equal("a", e2.name)
15
+ assert_equal("xxx", e2.fetch_attr("href"))
16
+ assert_equal([HTree::Text.new("def")], e2.children)
17
+ assert_equal([], e1.subst_subnode(0=>nil).children)
18
+ end
19
+
20
+ def test_elem_subst_empty
21
+ e1 = HTree.parse("<img />").root
22
+ assert_equal(true, e1.empty_element?)
23
+ assert_equal(true, e1.subst_subnode("src"=>"xxx").empty_element?)
24
+ assert_equal(false, e1.subst_subnode(0=>"xxx").empty_element?)
25
+ end
26
+
27
+ def test_elem_multiple_attr_value
28
+ h = {"b"=>"c", HTree::Name.new(nil, "", "b")=>"d"}
29
+ assert_match(/\A(cd|dc)\z/,
30
+ HTree::Elem.new("a").subst_subnode(h).get_subnode('b').to_s)
31
+
32
+ a = [["b","c"], [HTree::Name.new(nil, "", "b"),"d"]]
33
+ assert_equal('cd',
34
+ HTree::Elem.new("a").subst_subnode(a).get_subnode('b').to_s)
35
+ assert_equal('dc',
36
+ HTree::Elem.new("a").subst_subnode(a.reverse).get_subnode('b').to_s)
37
+ end
38
+
39
+ def test_elem_subst_outrange
40
+ e1 = HTree("<r>abc</r>").root
41
+ e2 = e1.subst_subnode(-1=>HTree('<x/>'), 1=>HTree('<y/>'))
42
+ assert_equal(HTree('<r><x/>abc<y/></r>').root, e2)
43
+ end
44
+
45
+ def test_doc_subst_outrange
46
+ d1 = HTree("<r>abc</r>")
47
+ d2 = d1.subst_subnode(-1=>HTree('<x/>'), 1=>HTree('<y/>'))
48
+ assert_equal(HTree('<x/><r>abc</r><y/>'), d2)
49
+ end
50
+
51
+ def test_doc_get
52
+ doc = HTree.parse("<?xml?><a href=x>abc</a> ")
53
+ assert_equal(doc.root, doc.get_subnode(1))
54
+ end
55
+
56
+ def test_doc_subst
57
+ doc1 = HTree.parse("<?xml?><a href=x>abc</a> ")
58
+ doc2 = doc1.subst_subnode(1=>"yy")
59
+ assert_equal(HTree::Text.new("yy"), doc2.children[1])
60
+ assert_equal([], doc1.subst_subnode(0=>nil, 1=>nil, 2=>nil).children)
61
+ end
62
+
63
+ def test_doc_loc
64
+ d1 = HTree.parse("<r>a</r>")
65
+ d2 = HTree.parse("<q/>")
66
+ assert_equal(d2, d1.subst_subnode(0=>d2.make_loc))
67
+ end
68
+
69
+ def test_doc
70
+ e = HTree.parse("<r>a</r>").root
71
+ d = HTree.parse("<?xml version='1.0'?><!DOCTYPE q><q/>")
72
+ r = HTree('<r><q/></r>').root
73
+ assert_equal(r, e.subst_subnode(0=>d))
74
+ assert_equal(r, e.subst_subnode(0=>d.make_loc))
75
+ assert_equal(r, e.subst_subnode(0=>[d]))
76
+ assert_equal(r, e.subst_subnode(0=>[d.make_loc]))
77
+ end
78
+
79
+ def test_doc2
80
+ e = HTree.parse("<r>a</r>")
81
+ d = HTree.parse("<?xml version='1.0'?><!DOCTYPE q><q/>")
82
+ r = HTree('<q/>')
83
+ assert_equal(r, e.subst_subnode(0=>d))
84
+ assert_equal(r, e.subst_subnode(0=>d.make_loc))
85
+ assert_equal(r, e.subst_subnode(0=>[d]))
86
+ assert_equal(r, e.subst_subnode(0=>[d.make_loc]))
87
+ end
88
+
89
+ def test_change_by_subst_itself
90
+ l = HTree("<r>a</r>").make_loc
91
+ l2 = l.get_subnode(0, 0).subst_itself('x')
92
+ assert_equal(HTree::Text.new('x'), l2.to_node)
93
+ assert_equal(HTree('<r>x</r>'), l2.top.to_node)
94
+ l2 = l.get_subnode(0).subst_itself('xxx')
95
+ assert_equal(HTree::Text.new('xxx'), l2.to_node)
96
+ assert_equal(HTree('xxx'), l2.top.to_node)
97
+ end
98
+
99
+ def test_add_by_subst_itself
100
+ l = HTree("<r>a</r>").make_loc
101
+ l2 = l.get_subnode(0, 'x').subst_itself('y')
102
+ assert_equal(HTree::Text.new('y'), l2.to_node)
103
+ assert_equal(HTree('<r x="y">a</r>'), l2.top.to_node)
104
+ l2 = l.get_subnode(0, 0).subst_itself('b')
105
+ assert_equal(HTree::Text.new('b'), l2.to_node)
106
+ assert_equal(HTree('<r>b</r>'), l2.top.to_node)
107
+ xmldecl = HTree('<?xml version="1.0"?>').get_subnode(0)
108
+ l2 = l.get_subnode(-1).subst_itself(xmldecl)
109
+ assert_equal(0, l2.index)
110
+ assert_equal(xmldecl, l2.to_node)
111
+ assert_equal(HTree('<?xml version="1.0"?><r>a</r>'), l2.top.to_node)
112
+ procins = HTree('<?xxx yyy?>').get_subnode(0)
113
+ l2 = l.get_subnode(10).subst_itself(procins)
114
+ assert_equal(1, l2.index)
115
+ assert_equal(procins, l2.to_node)
116
+ assert_equal(HTree('<r>a</r><?xxx yyy?>'), l2.top.to_node)
117
+ end
118
+
119
+ def test_del_by_subst_itself
120
+ l = HTree("<r x='y'><x/>y<z/></r>").make_loc
121
+ l2 = l.get_subnode(0, 'x').subst_itself(nil)
122
+ assert_equal(nil, l2.to_node)
123
+ assert_equal(HTree('<r><x/>y<z/></r>'), l2.top.to_node)
124
+ l2 = l.get_subnode(0, 1).subst_itself(nil)
125
+ assert_equal(HTree('<r x="y"><x/><z/></r>'), l2.top.to_node)
126
+ l = HTree('<?xml version="1.0"?><r/>').make_loc
127
+ l2 = l.get_subnode(0).subst_itself(nil)
128
+ assert_equal(HTree('<r/>'), l2.top.to_node)
129
+ end
130
+
131
+ def test_subst
132
+ l = HTree('<?xml version="1.0"?><r><x/><y/><z/></r>').make_loc
133
+ assert_equal(HTree("<r>x<y>a</y><z k=v /></r>"),
134
+ l.to_node.subst({
135
+ l.get_subnode(0) => nil,
136
+ l.get_subnode(1, 0) => 'x',
137
+ l.get_subnode(1, 1, 0) => 'a',
138
+ l.get_subnode(1, 2, 'k') => 'v'
139
+ }))
140
+ end
141
+
142
+ end
@@ -0,0 +1,313 @@
1
+ require 'test/unit'
2
+ require 'htree/template'
3
+ require 'stringio'
4
+
5
+ class TestTemplate < Test::Unit::TestCase
6
+ Decl = '<?xml version="1.0" encoding="US-ASCII"?>'
7
+
8
+ def assert_xhtml(expected, template, message=nil)
9
+ prefix = '<?xml version="1.0" encoding="US-ASCII"?>' +
10
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\"\n>"
11
+ suffix = "</html\n>"
12
+ result = HTree.expand_template(''){"<?xml version=\"1.0\"?><html>#{template}</html>"}
13
+ assert_match(/\A#{Regexp.quote prefix}/, result)
14
+ assert_match(/#{Regexp.quote suffix}\z/, result)
15
+ result = result[prefix.length..(-suffix.length-1)]
16
+ assert_equal(expected, result, message)
17
+ end
18
+
19
+ def test_text
20
+ assert_xhtml("<e\n>1</e\n>", '<e _text=1>d</e>')
21
+ assert_xhtml('1', '<span _text=1>d</span>')
22
+ assert_xhtml("<span x=\"2\"\n>1</span\n>", '<span x=2 _text=1>d</span>')
23
+ assert_xhtml("abc", %q{a<span _text="'b'"/>c})
24
+ end
25
+
26
+ def test_tree
27
+ assert_xhtml("<e\n><z\n>x</z\n></e\n>", '<e _tree="HTree(&quot;<z>x</z>&quot;)">d</e>')
28
+ assert_xhtml("<n:e xmlns:n=\"a\"\n><n:z\n>x</n:z\n></n:e\n>", '<n:e xmlns:n=a _tree="HTree(&quot;<n:z xmlns:n=a>x</n:z>&quot;)">d</n:e>')
29
+ end
30
+
31
+ def test_attr
32
+ assert_xhtml("<e x=\"1\"\n>d</e\n>", '<e _attr_x=1>d</e>')
33
+ assert_xhtml("<span x=\"1\"\n>d</span\n>", '<span _attr_x=1>d</span>')
34
+ assert_xhtml("<span x=\"&quot;\"\n>d</span\n>", '<span _attr_x=\'"\x22"\'>d</span>')
35
+ end
36
+
37
+ def test_if
38
+ assert_xhtml("<e\n>d</e\n>", '<e _if=true>d</e>')
39
+ assert_xhtml('', '<e _if=false>d</e>')
40
+ assert_xhtml("<f\n>dd</f\n>", '<e _if=false _else=m>d</e><f _template=m>dd</f>')
41
+
42
+ assert_xhtml('d', '<span _if=true>d</span>')
43
+ end
44
+
45
+ def test_iter
46
+ assert_xhtml("<o\n><i\n>1</i\n></o\n><o\n><i\n>2</i\n></o\n><o\n><i\n>3</i\n></o\n>",
47
+ '<o _iter=[1,2,3].each//v><i _text=v /></o>')
48
+ assert_xhtml("<i\n>1</i\n><i\n>2</i\n><i\n>3</i\n>",
49
+ '<span _iter=[1,2,3].each//v><i _text=v /></span>')
50
+ end
51
+
52
+ def test_iter_content
53
+ assert_xhtml("<o\n><i\n>1</i\n><i\n>2</i\n><i\n>3</i\n></o\n>",
54
+ '<o _iter_content=[1,2,3].each//v><i _text=v /></o>')
55
+ assert_xhtml("<i\n>1</i\n><i\n>2</i\n><i\n>3</i\n>",
56
+ '<span _iter_content=[1,2,3].each//v><i _text=v /></span>')
57
+ end
58
+
59
+ def test_iter_local_template
60
+ assert_xhtml("<o\n><i\n>1</i\n></o\n><o\n><i\n>2</i\n></o\n><o\n><i\n>3</i\n></o\n>",
61
+ '<o _iter=[1,2,3].each//v><i _call=m /><i _template=m _text=v></i></o>')
62
+ end
63
+
64
+ def test_call
65
+ assert_xhtml("<f\n>1</f\n>",
66
+ '<e _call=m(1) /><f _template=m(v) _text=v></f>')
67
+ end
68
+
69
+ def test_template
70
+ assert_xhtml('d',
71
+ '<span _template="span()">d</span><e _call="span()"></e>')
72
+ end
73
+
74
+ def test_file
75
+ assert_equal(<<'End'.chop,
76
+ <?xml version="1.0" encoding="US-ASCII"?><html xmlns="http://www.w3.org/1999/xhtml"
77
+ ><title
78
+ >aaa</title
79
+ ></html
80
+ >
81
+ End
82
+ HTree.expand_template("#{File.dirname __FILE__}/template.html", "aaa", ''))
83
+ end
84
+
85
+ def test_whitespace
86
+ assert_xhtml("<x\n></x\n>", '<x> </x>')
87
+ assert_xhtml("<x\n>&#32;</x\n>", '<x>&#32;</x>')
88
+ assert_xhtml("<pre\n> </pre\n>", '<pre> </pre>')
89
+ assert_xhtml(" ", %q{<span _text="' '"> </span>})
90
+ assert_xhtml(" ", %q{<span _text="' '"/>})
91
+ end
92
+
93
+ def test_ignorable
94
+ assert_xhtml("<div\n>a</div\n>", '<div>a</div>')
95
+ assert_xhtml("<span\n>a</span\n>", '<span>a</span>')
96
+ assert_xhtml("1", '<span _text="1">a</span>')
97
+ end
98
+
99
+ def test_not_ignorable
100
+ assert_xhtml("<p\n>1</p\n>", '<p _text="\'1\'">a</p>')
101
+ end
102
+
103
+ def test_template_in_attr
104
+ assert_xhtml("<a x=\"1\"\n></a\n>", '<a _attr_x=1><b _template=m></b></a>')
105
+ end
106
+
107
+ def test_empty_block_argument
108
+ assert_xhtml("vv", '<span _iter="2.times//">v</span>')
109
+ end
110
+
111
+ def test_empty_element
112
+ assert_xhtml("<elem\n/>", '<elem />') # 2004-06-10: reported by Takuo KITAME
113
+ assert_xhtml("<elem x=\"1\"\n/>", '<elem _attr_x=1 />')
114
+ assert_xhtml("<elem\n></elem\n>", '<elem _text=\'""\' />')
115
+ assert_xhtml("<elem\n/>", '<elem _if="true" />')
116
+ assert_xhtml("", '<elem _if="false" />')
117
+ assert_xhtml("<foo\n/>", '<elem _if="false" _else="foo"/><foo _template="foo"/>')
118
+ assert_xhtml("<elem\n/><elem\n/>", '<elem _iter="2.times//" />')
119
+ assert_xhtml("<elem\n></elem\n>", '<elem _iter_content="2.times//" />')
120
+ end
121
+
122
+ def test_empty_element_start_end_tag
123
+ assert_xhtml("<elem\n></elem\n>", '<elem></elem>')
124
+ assert_xhtml("<elem x=\"1\"\n></elem\n>", '<elem _attr_x=1 ></elem>')
125
+ assert_xhtml("<elem\n></elem\n>", '<elem _text=\'""\' ></elem>')
126
+ assert_xhtml("<elem\n></elem\n>", '<elem _if="true" ></elem>')
127
+ assert_xhtml("", '<elem _if="false" ></elem>')
128
+ assert_xhtml("<foo\n></foo\n>", '<elem _if="false" _else="foo"></elem><foo _template="foo"></foo>')
129
+ assert_xhtml("<elem\n></elem\n><elem\n></elem\n>", '<elem _iter="2.times//" ></elem>')
130
+ assert_xhtml("<elem\n></elem\n>", '<elem _iter_content="2.times//" ></elem>')
131
+ end
132
+
133
+ def test_toplevel_local_variable
134
+ eval("htree_test_toplevel_local_variable = :non_modified_value", TOPLEVEL_BINDING)
135
+ HTree.expand_template("#{File.dirname __FILE__}/assign.html", "aaa", '')
136
+ assert_equal(:non_modified_value, eval("htree_test_toplevel_local_variable", TOPLEVEL_BINDING))
137
+ eval("htree_test_toplevel_local_variable = 1", TOPLEVEL_BINDING)
138
+ end
139
+
140
+ def test_extend_compiled_template
141
+ m = HTree.compile_template('<div _template="m">self is <span _text="inspect"></span></div>')
142
+ o = "zzz"
143
+ o.extend m
144
+ assert_equal('<?xml version="1.0" encoding="US-ASCII"?>self is "zzz"',
145
+ HTree.expand_template(''){'<div _call="o.m"></div>'})
146
+ end
147
+
148
+ def test_attr_nbsp
149
+ @t = HTree::Text.parse_pcdata('&nbsp;')
150
+ assert_xhtml("<span x=\"&nbsp;\"\n>d</span\n>", '<span _attr_x="@t">d</span>')
151
+ end
152
+
153
+ def test_text_nbsp
154
+ @t = HTree::Text.parse_pcdata('&nbsp;')
155
+ assert_xhtml("&nbsp;", '<span _text="@t">d</span>')
156
+ end
157
+
158
+ def test_content_text
159
+ assert_xhtml("<e\n>ab</e\n>", '<e _text>"a"+"b"</e>')
160
+ assert_xhtml("<e\n>2</e\n>", '<e _text>1+1</e>')
161
+ end
162
+
163
+ end
164
+
165
+ class MemFile
166
+ def initialize(str)
167
+ @str = str
168
+ end
169
+
170
+ def read
171
+ @str
172
+ end
173
+ end
174
+
175
+ class TestTemplateScopeObj
176
+ Const = 'good_const'
177
+ @@cvar = 'good_cvar'
178
+ def initialize
179
+ @ivar = 'good_ivar'
180
+ end
181
+ end
182
+
183
+ class TestTemplateScope < Test::Unit::TestCase
184
+ Const = 'bad_const'
185
+ @@cvar = 'bad_cvar'
186
+ def setup
187
+ @ivar = 'bad_ivar'
188
+ eval("test_local_variable = 'bad_lvar'", TOPLEVEL_BINDING)
189
+ end
190
+
191
+ XMLDeclStr = '<?xml version="1.0" encoding="US-ASCII"?>'
192
+
193
+ def test_expand_template
194
+ obj = TestTemplateScopeObj.new
195
+ assert_equal("#{XMLDeclStr}[TestTemplateScopeObj]",
196
+ HTree.expand_template(MemFile.new('<span _text="Module.nesting.inspect"/>'), obj, ''))
197
+ assert_equal("#{XMLDeclStr}good_ivar",
198
+ HTree.expand_template(MemFile.new('<span _text="@ivar"/>'), obj, ''))
199
+ assert_equal("#{XMLDeclStr}good_cvar",
200
+ HTree.expand_template(MemFile.new('<span _text="@@cvar"/>'), obj, ''))
201
+ assert_equal("#{XMLDeclStr}good_const",
202
+ HTree.expand_template(MemFile.new('<span _text="Const"/>'), obj, ''))
203
+ test_local_variable = 'bad_lvar'
204
+ assert_equal("#{XMLDeclStr}good_lvar",
205
+ HTree.expand_template(MemFile.new('<span _text="begin test_local_variable rescue NameError; \'good_lvar\' end"/>'), obj, ''))
206
+ end
207
+
208
+ def test_compile_template
209
+ obj = TestTemplateScopeObj.new
210
+ mod = HTree.compile_template(MemFile.new(<<-'End'))
211
+ <span _template=test_nesting _text="Module.nesting.inspect"/>
212
+ <span _template=test_const _text="Const"/>
213
+ <span _template=test_cvar _text="@@cvar"/>
214
+ <span _template=test_ivar _text="@ivar"/>
215
+ End
216
+ mod.module_eval <<-'End'
217
+ Const = 'mod_const'
218
+ @@cvar = 'mod_cvar'
219
+ @ivar = 'mod_ivar'
220
+ End
221
+ assert_equal("[#{mod.inspect}]", mod.test_nesting.extract_text.to_s)
222
+ assert_equal("mod_const", mod.test_const.extract_text.to_s)
223
+ assert_equal("mod_cvar", mod.test_cvar.extract_text.to_s)
224
+ assert_equal("mod_ivar", mod.test_ivar.extract_text.to_s)
225
+ obj = Object.new
226
+ obj.instance_variable_set :@ivar, 'obj_ivar'
227
+ obj.extend mod
228
+ assert_equal("[#{mod.inspect}]", obj.__send__(:test_nesting).extract_text.to_s)
229
+ assert_equal("mod_const", obj.__send__(:test_const).extract_text.to_s)
230
+ assert_equal("mod_cvar", obj.__send__(:test_cvar).extract_text.to_s)
231
+ assert_equal("obj_ivar", obj.__send__(:test_ivar).extract_text.to_s)
232
+ end
233
+ end
234
+
235
+ class TestCDATA < Test::Unit::TestCase
236
+ def test_html_script
237
+ v = "x<y"
238
+ assert_equal("<html><script>x<y</script></html>",
239
+ HTree.expand_template('') {"<html><script _text=\"v\">ab</script>"}.gsub(/\n/, ''))
240
+ end
241
+
242
+ def test_xml_script
243
+ v = "x<y"
244
+ assert_equal("<?xml version=\"1.0\" encoding=\"US-ASCII\"?><html xmlns=\"http://www.w3.org/1999/xhtml\"><script>x&lt;y</script></html>",
245
+ HTree.expand_template('') {"<?xml version=\"1.0\"?><html><script _text=\"v\">ab</script>"}.gsub(/\n/, ''))
246
+ end
247
+
248
+ def test_html_script_invalid_content
249
+ v = "x</y"
250
+ assert_raise(ArgumentError) {
251
+ HTree.expand_template('') {"<html><script _text=\"v\">ab</script>"}
252
+ }
253
+ end
254
+
255
+ def test_stylexxx
256
+ v = "x<y"
257
+ assert_equal("<html><stylexxx>x&lt;y</stylexxx></html>",
258
+ HTree.expand_template('') {"<html><stylexxx _text=\"v\">ab</stylexxx>"}.gsub(/\n/, ''))
259
+ end
260
+
261
+ end
262
+
263
+ class TestCharset2 < Test::Unit::TestCase
264
+ class CharsetString < String
265
+ attr_accessor :charset
266
+ end
267
+
268
+ def with_kcode(kcode)
269
+ if "".respond_to? :force_encoding
270
+ if HTree::Encoder.internal_charset.start_with?(kcode.upcase)
271
+ yield
272
+ end
273
+ else
274
+ old = $KCODE
275
+ begin
276
+ $KCODE = kcode
277
+ yield
278
+ ensure
279
+ $KCODE = old
280
+ end
281
+ end
282
+ end
283
+
284
+ def test_us_ascii
285
+ with_kcode('E') {
286
+ out = HTree.expand_template(CharsetString.new) { "<html>abc" }
287
+ assert_equal(out.charset, 'US-ASCII')
288
+ }
289
+ end
290
+
291
+ def test_euc_jp
292
+ with_kcode('E') {
293
+ out = HTree.expand_template(CharsetString.new) { "<html>\xa1\xa1" }
294
+ assert_equal(out.charset, 'EUC-JP')
295
+ }
296
+ end
297
+
298
+ def test_utf_8
299
+ with_kcode('U') {
300
+ out = HTree.expand_template(CharsetString.new) { "<html>\xc2\xa1" }
301
+ assert_equal(out.charset, 'UTF-8')
302
+ }
303
+ end
304
+
305
+ end
306
+
307
+ class TestTemplateDOCTYPE < Test::Unit::TestCase
308
+ def test_html
309
+ assert_equal(
310
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html></html>',
311
+ HTree.expand_template('') {'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html>'}.gsub(/\n/, ''))
312
+ end
313
+ end