htree 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +4 -0
- data/Makefile +20 -0
- data/Manifest +58 -0
- data/README +61 -0
- data/Rakefile +37 -0
- data/htree.gemspec +32 -0
- data/init.rb +1 -0
- data/install.rb +112 -0
- data/lib/htree.rb +97 -0
- data/lib/htree/container.rb +8 -0
- data/lib/htree/context.rb +69 -0
- data/lib/htree/display.rb +46 -0
- data/lib/htree/doc.rb +149 -0
- data/lib/htree/elem.rb +262 -0
- data/lib/htree/encoder.rb +217 -0
- data/lib/htree/equality.rb +219 -0
- data/lib/htree/extract_text.rb +37 -0
- data/lib/htree/fstr.rb +32 -0
- data/lib/htree/gencode.rb +193 -0
- data/lib/htree/htmlinfo.rb +672 -0
- data/lib/htree/inspect.rb +108 -0
- data/lib/htree/leaf.rb +92 -0
- data/lib/htree/loc.rb +369 -0
- data/lib/htree/modules.rb +49 -0
- data/lib/htree/name.rb +122 -0
- data/lib/htree/output.rb +212 -0
- data/lib/htree/parse.rb +410 -0
- data/lib/htree/raw_string.rb +127 -0
- data/lib/htree/regexp-util.rb +19 -0
- data/lib/htree/rexml.rb +131 -0
- data/lib/htree/scan.rb +176 -0
- data/lib/htree/tag.rb +113 -0
- data/lib/htree/template.rb +961 -0
- data/lib/htree/text.rb +115 -0
- data/lib/htree/traverse.rb +497 -0
- data/test-all.rb +5 -0
- data/test/assign.html +1 -0
- data/test/template.html +4 -0
- data/test/test-attr.rb +67 -0
- data/test/test-charset.rb +79 -0
- data/test/test-context.rb +29 -0
- data/test/test-display_xml.rb +45 -0
- data/test/test-elem-new.rb +101 -0
- data/test/test-encoder.rb +53 -0
- data/test/test-equality.rb +55 -0
- data/test/test-extract_text.rb +18 -0
- data/test/test-gencode.rb +27 -0
- data/test/test-leaf.rb +25 -0
- data/test/test-loc.rb +60 -0
- data/test/test-namespace.rb +147 -0
- data/test/test-output.rb +133 -0
- data/test/test-parse.rb +115 -0
- data/test/test-raw_string.rb +17 -0
- data/test/test-rexml.rb +70 -0
- data/test/test-scan.rb +153 -0
- data/test/test-security.rb +37 -0
- data/test/test-subnode.rb +142 -0
- data/test/test-template.rb +313 -0
- data/test/test-text.rb +43 -0
- data/test/test-traverse.rb +69 -0
- metadata +166 -0
- 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
|
data/test/test-rexml.rb
ADDED
@@ -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<b</style>', HTree.parse('<html><style>a<b</style></html>').to_rexml.to_s[/<style.*style>/])
|
69
|
+
end
|
70
|
+
end if defined? REXML
|
data/test/test-scan.rb
ADDED
@@ -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("<z>x</z>")">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("<n:z xmlns:n=a>x</n:z>")">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=\""\"\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> </x\n>", '<x> </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(' ')
|
150
|
+
assert_xhtml("<span x=\" \"\n>d</span\n>", '<span _attr_x="@t">d</span>')
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_text_nbsp
|
154
|
+
@t = HTree::Text.parse_pcdata(' ')
|
155
|
+
assert_xhtml(" ", '<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<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<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
|