tenderlove-nokogiri 0.0.0.20081001111445
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/Manifest.txt +105 -0
- data/README.txt +51 -0
- data/Rakefile +70 -0
- data/ext/nokogiri/extconf.rb +24 -0
- data/ext/nokogiri/html_document.c +85 -0
- data/ext/nokogiri/html_document.h +10 -0
- data/ext/nokogiri/html_sax_parser.c +32 -0
- data/ext/nokogiri/html_sax_parser.h +11 -0
- data/ext/nokogiri/native.c +35 -0
- data/ext/nokogiri/native.h +32 -0
- data/ext/nokogiri/xml_cdata.c +36 -0
- data/ext/nokogiri/xml_cdata.h +9 -0
- data/ext/nokogiri/xml_document.c +159 -0
- data/ext/nokogiri/xml_document.h +10 -0
- data/ext/nokogiri/xml_node.c +573 -0
- data/ext/nokogiri/xml_node.h +13 -0
- data/ext/nokogiri/xml_node_set.c +90 -0
- data/ext/nokogiri/xml_node_set.h +9 -0
- data/ext/nokogiri/xml_reader.c +420 -0
- data/ext/nokogiri/xml_reader.h +10 -0
- data/ext/nokogiri/xml_sax_parser.c +161 -0
- data/ext/nokogiri/xml_sax_parser.h +10 -0
- data/ext/nokogiri/xml_text.c +25 -0
- data/ext/nokogiri/xml_text.h +9 -0
- data/ext/nokogiri/xml_xpath.c +39 -0
- data/ext/nokogiri/xml_xpath.h +11 -0
- data/ext/nokogiri/xml_xpath_context.c +69 -0
- data/ext/nokogiri/xml_xpath_context.h +9 -0
- data/ext/nokogiri/xslt_stylesheet.c +83 -0
- data/ext/nokogiri/xslt_stylesheet.h +9 -0
- data/lib/nokogiri.rb +45 -0
- data/lib/nokogiri/css.rb +6 -0
- data/lib/nokogiri/css/node.rb +95 -0
- data/lib/nokogiri/css/parser.rb +24 -0
- data/lib/nokogiri/css/parser.y +198 -0
- data/lib/nokogiri/css/tokenizer.rb +9 -0
- data/lib/nokogiri/css/tokenizer.rex +63 -0
- data/lib/nokogiri/css/xpath_visitor.rb +153 -0
- data/lib/nokogiri/decorators.rb +1 -0
- data/lib/nokogiri/decorators/hpricot.rb +3 -0
- data/lib/nokogiri/decorators/hpricot/node.rb +47 -0
- data/lib/nokogiri/decorators/hpricot/node_set.rb +14 -0
- data/lib/nokogiri/decorators/hpricot/xpath_visitor.rb +13 -0
- data/lib/nokogiri/hpricot.rb +46 -0
- data/lib/nokogiri/html.rb +64 -0
- data/lib/nokogiri/html/builder.rb +9 -0
- data/lib/nokogiri/html/document.rb +9 -0
- data/lib/nokogiri/html/sax/parser.rb +21 -0
- data/lib/nokogiri/version.rb +3 -0
- data/lib/nokogiri/xml.rb +29 -0
- data/lib/nokogiri/xml/after_handler.rb +18 -0
- data/lib/nokogiri/xml/before_handler.rb +32 -0
- data/lib/nokogiri/xml/builder.rb +79 -0
- data/lib/nokogiri/xml/document.rb +22 -0
- data/lib/nokogiri/xml/node.rb +162 -0
- data/lib/nokogiri/xml/node_set.rb +136 -0
- data/lib/nokogiri/xml/reader.rb +14 -0
- data/lib/nokogiri/xml/sax.rb +9 -0
- data/lib/nokogiri/xml/sax/document.rb +59 -0
- data/lib/nokogiri/xml/sax/parser.rb +33 -0
- data/lib/nokogiri/xml/text.rb +6 -0
- data/lib/nokogiri/xml/xpath.rb +6 -0
- data/lib/nokogiri/xslt.rb +11 -0
- data/lib/nokogiri/xslt/stylesheet.rb +6 -0
- data/nokogiri.gemspec +33 -0
- data/test/css/test_nthiness.rb +141 -0
- data/test/css/test_parser.rb +214 -0
- data/test/css/test_tokenizer.rb +162 -0
- data/test/files/staff.xml +57 -0
- data/test/files/staff.xslt +32 -0
- data/test/files/tlm.html +850 -0
- data/test/helper.rb +70 -0
- data/test/hpricot/files/basic.xhtml +17 -0
- data/test/hpricot/files/boingboing.html +2266 -0
- data/test/hpricot/files/cy0.html +3653 -0
- data/test/hpricot/files/immob.html +400 -0
- data/test/hpricot/files/pace_application.html +1320 -0
- data/test/hpricot/files/tenderlove.html +16 -0
- data/test/hpricot/files/uswebgen.html +220 -0
- data/test/hpricot/files/utf8.html +1054 -0
- data/test/hpricot/files/week9.html +1723 -0
- data/test/hpricot/files/why.xml +19 -0
- data/test/hpricot/load_files.rb +7 -0
- data/test/hpricot/test_alter.rb +67 -0
- data/test/hpricot/test_builder.rb +27 -0
- data/test/hpricot/test_parser.rb +412 -0
- data/test/hpricot/test_paths.rb +15 -0
- data/test/hpricot/test_preserved.rb +72 -0
- data/test/hpricot/test_xml.rb +26 -0
- data/test/html/sax/test_parser.rb +27 -0
- data/test/html/test_builder.rb +78 -0
- data/test/html/test_document.rb +22 -0
- data/test/test_convert_xpath.rb +173 -0
- data/test/test_nokogiri.rb +36 -0
- data/test/test_reader.rb +222 -0
- data/test/test_xslt_transforms.rb +29 -0
- data/test/xml/sax/test_parser.rb +93 -0
- data/test/xml/test_builder.rb +16 -0
- data/test/xml/test_document.rb +141 -0
- data/test/xml/test_node.rb +148 -0
- data/test/xml/test_node_set.rb +54 -0
- data/test/xml/test_text.rb +13 -0
- metadata +191 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module XML
|
3
|
+
module SAX
|
4
|
+
class Document
|
5
|
+
###
|
6
|
+
# Called when document starts parsing
|
7
|
+
def start_document
|
8
|
+
end
|
9
|
+
|
10
|
+
###
|
11
|
+
# Called when document ends parsing
|
12
|
+
def end_document
|
13
|
+
end
|
14
|
+
|
15
|
+
###
|
16
|
+
# Called at the beginning of an element
|
17
|
+
# +name+ is the name of the tag with +attrs+ as attributes
|
18
|
+
def start_element name, attrs = []
|
19
|
+
end
|
20
|
+
|
21
|
+
###
|
22
|
+
# Called at the end of an element
|
23
|
+
# +name+ is the tag name
|
24
|
+
def end_element name
|
25
|
+
end
|
26
|
+
|
27
|
+
###
|
28
|
+
# Characters read between a tag
|
29
|
+
# +string+ contains the character data
|
30
|
+
def characters string
|
31
|
+
end
|
32
|
+
|
33
|
+
###
|
34
|
+
# Called when comments are encountered
|
35
|
+
# +string+ contains the comment data
|
36
|
+
def comment string
|
37
|
+
end
|
38
|
+
|
39
|
+
###
|
40
|
+
# Called on document warnings
|
41
|
+
# +string+ contains the warning
|
42
|
+
def warning string
|
43
|
+
end
|
44
|
+
|
45
|
+
###
|
46
|
+
# Called on document errors
|
47
|
+
# +string+ contains the error
|
48
|
+
def error string
|
49
|
+
end
|
50
|
+
|
51
|
+
###
|
52
|
+
# Called when cdata blocks are found
|
53
|
+
# +string+ contains the cdata content
|
54
|
+
def cdata_block string
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module XML
|
3
|
+
module SAX
|
4
|
+
class Parser
|
5
|
+
attr_accessor :document
|
6
|
+
def initialize(doc = XML::SAX::Document.new)
|
7
|
+
@document = doc
|
8
|
+
end
|
9
|
+
|
10
|
+
###
|
11
|
+
# Parse given +thing+ which may be a string containing xml, or an
|
12
|
+
# IO object.
|
13
|
+
def parse thing
|
14
|
+
parse_memory(thing.is_a?(IO) ? thing.read : thing)
|
15
|
+
end
|
16
|
+
|
17
|
+
###
|
18
|
+
# Parse given +io+
|
19
|
+
def parse_io io
|
20
|
+
parse_memory io.read
|
21
|
+
end
|
22
|
+
|
23
|
+
###
|
24
|
+
# Parse a file with +filename+
|
25
|
+
def parse_file filename
|
26
|
+
raise Errno::ENOENT unless File.exists?(filename)
|
27
|
+
raise Errno::EISDIR if File.directory?(filename)
|
28
|
+
native_parse_file filename
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/nokogiri.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{nokogiri}
|
3
|
+
s.version = "0.0.0.20081001111445"
|
4
|
+
|
5
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
6
|
+
s.authors = ["Aaron Patterson"]
|
7
|
+
s.date = %q{2008-10-01}
|
8
|
+
s.description = %q{FIX (describe your package)}
|
9
|
+
s.email = ["aaronp@rubyforge.org"]
|
10
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
|
11
|
+
s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "ext/nokogiri/extconf.rb", "ext/nokogiri/html_document.c", "ext/nokogiri/html_document.h", "ext/nokogiri/html_sax_parser.c", "ext/nokogiri/html_sax_parser.h", "ext/nokogiri/native.c", "ext/nokogiri/native.h", "ext/nokogiri/xml_cdata.c", "ext/nokogiri/xml_cdata.h", "ext/nokogiri/xml_document.c", "ext/nokogiri/xml_document.h", "ext/nokogiri/xml_node.c", "ext/nokogiri/xml_node.h", "ext/nokogiri/xml_node_set.c", "ext/nokogiri/xml_node_set.h", "ext/nokogiri/xml_reader.c", "ext/nokogiri/xml_reader.h", "ext/nokogiri/xml_sax_parser.c", "ext/nokogiri/xml_sax_parser.h", "ext/nokogiri/xml_text.c", "ext/nokogiri/xml_text.h", "ext/nokogiri/xml_xpath.c", "ext/nokogiri/xml_xpath.h", "ext/nokogiri/xml_xpath_context.c", "ext/nokogiri/xml_xpath_context.h", "ext/nokogiri/xslt_stylesheet.c", "ext/nokogiri/xslt_stylesheet.h", "lib/nokogiri.rb", "lib/nokogiri/css.rb", "lib/nokogiri/css/generated_parser.rb", "lib/nokogiri/css/generated_tokenizer.rb", "lib/nokogiri/css/node.rb", "lib/nokogiri/css/parser.rb", "lib/nokogiri/css/parser.y", "lib/nokogiri/css/tokenizer.rb", "lib/nokogiri/css/tokenizer.rex", "lib/nokogiri/css/xpath_visitor.rb", "lib/nokogiri/decorators.rb", "lib/nokogiri/decorators/hpricot.rb", "lib/nokogiri/decorators/hpricot/node.rb", "lib/nokogiri/decorators/hpricot/node_set.rb", "lib/nokogiri/decorators/hpricot/xpath_visitor.rb", "lib/nokogiri/hpricot.rb", "lib/nokogiri/html.rb", "lib/nokogiri/html/builder.rb", "lib/nokogiri/html/document.rb", "lib/nokogiri/html/sax/parser.rb", "lib/nokogiri/version.rb", "lib/nokogiri/xml.rb", "lib/nokogiri/xml/after_handler.rb", "lib/nokogiri/xml/before_handler.rb", "lib/nokogiri/xml/builder.rb", "lib/nokogiri/xml/document.rb", "lib/nokogiri/xml/node.rb", "lib/nokogiri/xml/node_set.rb", "lib/nokogiri/xml/reader.rb", "lib/nokogiri/xml/sax.rb", "lib/nokogiri/xml/sax/document.rb", "lib/nokogiri/xml/sax/parser.rb", "lib/nokogiri/xml/text.rb", "lib/nokogiri/xml/xpath.rb", "lib/nokogiri/xslt.rb", "lib/nokogiri/xslt/stylesheet.rb", "nokogiri.gemspec", "test/css/test_nthiness.rb", "test/css/test_parser.rb", "test/css/test_tokenizer.rb", "test/files/staff.xml", "test/files/staff.xslt", "test/files/tlm.html", "test/helper.rb", "test/hpricot/files/basic.xhtml", "test/hpricot/files/boingboing.html", "test/hpricot/files/cy0.html", "test/hpricot/files/immob.html", "test/hpricot/files/pace_application.html", "test/hpricot/files/tenderlove.html", "test/hpricot/files/uswebgen.html", "test/hpricot/files/utf8.html", "test/hpricot/files/week9.html", "test/hpricot/files/why.xml", "test/hpricot/load_files.rb", "test/hpricot/test_alter.rb", "test/hpricot/test_builder.rb", "test/hpricot/test_parser.rb", "test/hpricot/test_paths.rb", "test/hpricot/test_preserved.rb", "test/hpricot/test_xml.rb", "test/html/sax/test_parser.rb", "test/html/test_builder.rb", "test/html/test_document.rb", "test/test_convert_xpath.rb", "test/test_nokogiri.rb", "test/test_reader.rb", "test/test_xslt_transforms.rb", "test/xml/sax/test_parser.rb", "test/xml/test_builder.rb", "test/xml/test_document.rb", "test/xml/test_node.rb", "test/xml/test_node_set.rb", "test/xml/test_text.rb"]
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.homepage = %q{http://github.com/tenderlove/nokogiri/tree/master}
|
14
|
+
s.rdoc_options = ["--main", "README.txt"]
|
15
|
+
s.require_paths = ["lib", "ext"]
|
16
|
+
s.rubyforge_project = %q{nokogiri}
|
17
|
+
s.rubygems_version = %q{1.2.0}
|
18
|
+
s.summary = %q{FIX (describe your package)}
|
19
|
+
s.test_files = ["test/css/test_nthiness.rb", "test/css/test_parser.rb", "test/css/test_tokenizer.rb", "test/hpricot/test_alter.rb", "test/hpricot/test_builder.rb", "test/hpricot/test_parser.rb", "test/hpricot/test_paths.rb", "test/hpricot/test_preserved.rb", "test/hpricot/test_xml.rb", "test/html/sax/test_parser.rb", "test/html/test_builder.rb", "test/html/test_document.rb", "test/test_convert_xpath.rb", "test/test_nokogiri.rb", "test/test_reader.rb", "test/test_xslt_transforms.rb", "test/xml/sax/test_parser.rb", "test/xml/test_builder.rb", "test/xml/test_document.rb", "test/xml/test_node.rb", "test/xml/test_node_set.rb", "test/xml/test_text.rb"]
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 2
|
24
|
+
|
25
|
+
if current_version >= 3 then
|
26
|
+
s.add_development_dependency(%q<hoe>, [">= 1.7.0"])
|
27
|
+
else
|
28
|
+
s.add_dependency(%q<hoe>, [">= 1.7.0"])
|
29
|
+
end
|
30
|
+
else
|
31
|
+
s.add_dependency(%q<hoe>, [">= 1.7.0"])
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
|
2
|
+
|
3
|
+
module Nokogiri
|
4
|
+
module CSS
|
5
|
+
class TestNthiness < Nokogiri::TestCase
|
6
|
+
def setup
|
7
|
+
doc = <<EOF
|
8
|
+
<html>
|
9
|
+
<table>
|
10
|
+
<tr><td>row1 </td></tr>
|
11
|
+
<tr><td>row2 </td></tr>
|
12
|
+
<tr><td>row3 </td></tr>
|
13
|
+
<tr><td>row4 </td></tr>
|
14
|
+
<tr><td>row5 </td></tr>
|
15
|
+
<tr><td>row6 </td></tr>
|
16
|
+
<tr><td>row7 </td></tr>
|
17
|
+
<tr><td>row8 </td></tr>
|
18
|
+
<tr><td>row9 </td></tr>
|
19
|
+
<tr><td>row10 </td></tr>
|
20
|
+
<tr><td>row11 </td></tr>
|
21
|
+
<tr><td>row12 </td></tr>
|
22
|
+
<tr><td>row13 </td></tr>
|
23
|
+
<tr><td>row14 </td></tr>
|
24
|
+
</table>
|
25
|
+
<div>
|
26
|
+
<b>bold1 </b>
|
27
|
+
<i>italic1 </i>
|
28
|
+
<b>bold2 </b>
|
29
|
+
<i>italic2 </i>
|
30
|
+
<p>para1 </p>
|
31
|
+
<b>bold3 </b>
|
32
|
+
</div>
|
33
|
+
<div>
|
34
|
+
<p>para2 </p>
|
35
|
+
<p>para3 </p>
|
36
|
+
</div>
|
37
|
+
<div>
|
38
|
+
<p>para4 </p>
|
39
|
+
</div>
|
40
|
+
<p class='empty'></p>
|
41
|
+
<p class='not-empty'><b></b></p>
|
42
|
+
</html>
|
43
|
+
EOF
|
44
|
+
@parser = Nokogiri.Hpricot doc
|
45
|
+
@xpath = Nokogiri doc
|
46
|
+
@cssparser = Nokogiri::CSS::Parser.new
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def test_even
|
51
|
+
assert_result_rows [2,4,6,8,10,12,14], @parser.search("table/tr:nth(even)")
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_odd
|
55
|
+
assert_result_rows [1,3,5,7,9,11,13], @parser.search("table/tr:nth(odd)")
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_2n
|
59
|
+
assert_equal @parser.search("table/tr:nth(even)").inner_text, @parser.search("table/tr:nth(2n)").inner_text
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_2np1
|
63
|
+
assert_equal @parser.search("table/tr:nth(odd)").inner_text, @parser.search("table/tr:nth(2n+1)").inner_text
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_4np3
|
67
|
+
assert_result_rows [3,7,11], @parser.search("table/tr:nth(4n+3)")
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_3np4
|
71
|
+
assert_result_rows [4,7,10,13], @parser.search("table/tr:nth(3n+4)")
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_mnp3
|
75
|
+
assert_result_rows [1,2,3], @parser.search("table/tr:nth(-n+3)")
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_np3
|
79
|
+
assert_result_rows [3,4,5,6,7,8,9,10,11,12,13,14], @parser.search("table/tr:nth(n+3)")
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_first
|
83
|
+
assert_result_rows [1], @parser.search("table/tr:first")
|
84
|
+
assert_result_rows [1], @parser.search("table/tr:first()")
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_last
|
88
|
+
assert_result_rows [14], @parser.search("table/tr:last")
|
89
|
+
assert_result_rows [14], @parser.search("table/tr:last()")
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_first_child
|
93
|
+
assert_result_rows [1], @parser.search("div/b:first-child"), "bold"
|
94
|
+
assert_result_rows [1], @parser.search("table/tr:first-child")
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_last_child
|
98
|
+
assert_result_rows [3], @parser.search("div/b:last-child"), "bold"
|
99
|
+
assert_result_rows [14], @parser.search("table/tr:last-child")
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_first_of_type
|
103
|
+
assert_result_rows [1], @parser.search("table/tr:first-of-type")
|
104
|
+
assert_result_rows [1], @parser.search("div/b:first-of-type"), "bold"
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_last_of_type
|
108
|
+
assert_result_rows [14], @parser.search("table/tr:last-of-type")
|
109
|
+
assert_result_rows [3], @parser.search("div/b:last-of-type"), "bold"
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_only_of_type
|
113
|
+
assert_result_rows [1,4], @parser.search("div/p:only-of-type"), "para"
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_only_child
|
117
|
+
assert_result_rows [4], @parser.search("div/p:only-child"), "para"
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_empty
|
121
|
+
result = @parser.search("p:empty")
|
122
|
+
assert_equal 1, result.size, "unexpected number of rows returned: '#{result.inner_text}'"
|
123
|
+
assert_equal 'empty', result.first['class']
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_parent
|
127
|
+
result = @parser.search("p:parent")
|
128
|
+
assert_equal 5, result.size
|
129
|
+
0.upto(3) do |j|
|
130
|
+
assert_equal "para#{j+1} ", result[j].inner_text
|
131
|
+
end
|
132
|
+
assert_equal "not-empty", result[4]['class']
|
133
|
+
end
|
134
|
+
|
135
|
+
def assert_result_rows intarray, result, word="row"
|
136
|
+
assert_equal intarray.size, result.size, "unexpected number of rows returned: '#{result.inner_text}'"
|
137
|
+
assert_equal intarray.map{|j| "#{word}#{j}"}.join(' '), result.inner_text.strip, result.inner_text
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', "helper"))
|
2
|
+
|
3
|
+
module Nokogiri
|
4
|
+
module CSS
|
5
|
+
class TestParser < Nokogiri::TestCase
|
6
|
+
def setup
|
7
|
+
@parser = Nokogiri::CSS::Parser.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_find_by_type
|
11
|
+
ast = @parser.parse("a:nth-child(2)").first
|
12
|
+
matches = ast.find_by_type(
|
13
|
+
[:CONDITIONAL_SELECTOR,
|
14
|
+
[:ELEMENT_NAME],
|
15
|
+
[:PSEUDO_CLASS,
|
16
|
+
[:FUNCTION]
|
17
|
+
]
|
18
|
+
]
|
19
|
+
)
|
20
|
+
assert_equal(1, matches.length)
|
21
|
+
assert_equal(ast, matches.first)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_to_type
|
25
|
+
ast = @parser.parse("a:nth-child(2)").first
|
26
|
+
assert_equal(
|
27
|
+
[:CONDITIONAL_SELECTOR,
|
28
|
+
[:ELEMENT_NAME],
|
29
|
+
[:PSEUDO_CLASS,
|
30
|
+
[:FUNCTION]
|
31
|
+
]
|
32
|
+
], ast.to_type
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_to_a
|
37
|
+
asts = @parser.parse("a:nth-child(2)")
|
38
|
+
assert_equal(
|
39
|
+
[:CONDITIONAL_SELECTOR,
|
40
|
+
[:ELEMENT_NAME, ["a"]],
|
41
|
+
[:PSEUDO_CLASS,
|
42
|
+
[:FUNCTION, ["nth-child("], ["2"]]
|
43
|
+
]
|
44
|
+
], asts.first.to_a
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_function_with_arguments
|
49
|
+
assert_xpath "//*[position() = 2 and self::a]",
|
50
|
+
@parser.parse("a[2]")
|
51
|
+
assert_xpath "//*[position() = 2 and self::a]",
|
52
|
+
@parser.parse("a:nth-child(2)")
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_attributes_with_at
|
56
|
+
## This is non standard CSS
|
57
|
+
assert_xpath "//a[@id = 'Boing']",
|
58
|
+
@parser.parse("a[@id='Boing']")
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_not_equal
|
62
|
+
## This is non standard CSS
|
63
|
+
assert_xpath "//a[child::text() != 'Boing']",
|
64
|
+
@parser.parse("a[text()!='Boing']")
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_function
|
68
|
+
## This is non standard CSS
|
69
|
+
assert_xpath "//a[child::text()]",
|
70
|
+
@parser.parse("a[text()]")
|
71
|
+
|
72
|
+
## This is non standard CSS
|
73
|
+
assert_xpath "//child::text()",
|
74
|
+
@parser.parse("text()")
|
75
|
+
|
76
|
+
## This is non standard CSS
|
77
|
+
assert_xpath "//a[contains(child::text(), 'Boing')]",
|
78
|
+
@parser.parse("a[text()*='Boing']")
|
79
|
+
|
80
|
+
## This is non standard CSS
|
81
|
+
assert_xpath "//script//comment()",
|
82
|
+
@parser.parse("script comment()")
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_nonstandard_nth_selectors
|
86
|
+
## These are non standard CSS
|
87
|
+
assert_xpath '//a[position() = 99]', @parser.parse('a:eq(99)')
|
88
|
+
assert_xpath '//a[position() = 1]', @parser.parse('a:first') # no parens
|
89
|
+
assert_xpath '//a[position() = last()]', @parser.parse('a:last') # no parens
|
90
|
+
assert_xpath '//a[position() = 99]', @parser.parse('a:nth(99)')
|
91
|
+
assert_xpath '//a[position() = 1]', @parser.parse('a:first()')
|
92
|
+
assert_xpath '//a[position() = last()]', @parser.parse('a:last()')
|
93
|
+
assert_xpath '//a[node()]', @parser.parse('a:parent')
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_standard_nth_selectors
|
97
|
+
assert_xpath '//a[position() = 99]', @parser.parse('a:nth-of-type(99)')
|
98
|
+
assert_xpath '//a[position() = 1]', @parser.parse('a:first-of-type()')
|
99
|
+
assert_xpath '//a[position() = last()]', @parser.parse('a:last-of-type()')
|
100
|
+
assert_xpath '//a[position() = 1]', @parser.parse('a:first-of-type') # no parens
|
101
|
+
assert_xpath '//a[position() = last()]', @parser.parse('a:last-of-type') # no parens
|
102
|
+
assert_xpath '//a[position() = last() - 99]', @parser.parse('a:nth-last-of-type(99)')
|
103
|
+
assert_xpath '//a[position() = last() - 99]', @parser.parse('a:nth-last-of-type(99)')
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_nth_child_selectors
|
107
|
+
assert_xpath '//*[position() = 1 and self::a]', @parser.parse('a:first-child')
|
108
|
+
assert_xpath '//*[position() = last() and self::a]', @parser.parse('a:last-child')
|
109
|
+
assert_xpath '//*[position() = 99 and self::a]', @parser.parse('a:nth-child(99)')
|
110
|
+
assert_xpath '//*[position() = last() - 99 and self::a]', @parser.parse('a:nth-last-child(99)')
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_miscellaneous_selectors
|
114
|
+
assert_xpath '//*[last() = 1 and self::a]',
|
115
|
+
@parser.parse('a:only-child')
|
116
|
+
assert_xpath '//a[last() = 1]', @parser.parse('a:only-of-type')
|
117
|
+
assert_xpath '//a[not(node())]', @parser.parse('a:empty')
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_nth_a_n_plus_b
|
121
|
+
assert_xpath '//a[(position() mod 2) = 0]', @parser.parse('a:nth-of-type(2n)')
|
122
|
+
assert_xpath '//a[(position() >= 1) and (((position()-1) mod 2) = 0)]', @parser.parse('a:nth-of-type(2n+1)')
|
123
|
+
assert_xpath '//a[(position() mod 2) = 0]', @parser.parse('a:nth-of-type(even)')
|
124
|
+
assert_xpath '//a[(position() >= 1) and (((position()-1) mod 2) = 0)]', @parser.parse('a:nth-of-type(odd)')
|
125
|
+
assert_xpath '//a[(position() >= 3) and (((position()-3) mod 4) = 0)]', @parser.parse('a:nth-of-type(4n+3)')
|
126
|
+
assert_xpath '//a[(position() <= 3) and (((position()-3) mod 1) = 0)]', @parser.parse('a:nth-of-type(-1n+3)')
|
127
|
+
assert_xpath '//a[(position() <= 3) and (((position()-3) mod 1) = 0)]', @parser.parse('a:nth-of-type(-n+3)')
|
128
|
+
assert_xpath '//a[(position() >= 3) and (((position()-3) mod 1) = 0)]', @parser.parse('a:nth-of-type(1n+3)')
|
129
|
+
assert_xpath '//a[(position() >= 3) and (((position()-3) mod 1) = 0)]', @parser.parse('a:nth-of-type(n+3)')
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_preceding_selector
|
133
|
+
assert_xpath "//F[preceding-sibling::E]",
|
134
|
+
@parser.parse("E ~ F")
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_attribute
|
138
|
+
assert_xpath "//h1[child::a = 'Tender Lovemaking']",
|
139
|
+
@parser.parse("h1[a='Tender Lovemaking']")
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_id
|
143
|
+
assert_xpath "//*[@id = 'foo']", @parser.parse('#foo')
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_pseudo_class_no_ident
|
147
|
+
assert_xpath "//*[1 = 1]", @parser.parse(':link')
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_pseudo_class
|
151
|
+
assert_xpath "//a[1 = 1]", @parser.parse('a:link')
|
152
|
+
assert_xpath "//a[1 = 1]", @parser.parse('a:visited')
|
153
|
+
assert_xpath "//a[1 = 1]", @parser.parse('a:hover')
|
154
|
+
assert_xpath "//a[1 = 1]", @parser.parse('a:active')
|
155
|
+
assert_xpath "//a[1 = 1 and contains(@class, 'foo')]",
|
156
|
+
@parser.parse('a:active.foo')
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_star
|
160
|
+
assert_xpath "//*", @parser.parse('*')
|
161
|
+
assert_xpath "//*[contains(@class, 'pastoral')]",
|
162
|
+
@parser.parse('*.pastoral')
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_class
|
166
|
+
assert_xpath "//*[contains(@class, 'a') and contains(@class, 'b')]",
|
167
|
+
@parser.parse('.a.b')
|
168
|
+
assert_xpath "//*[contains(@class, 'awesome')]",
|
169
|
+
@parser.parse('.awesome')
|
170
|
+
assert_xpath "//foo[contains(@class, 'awesome')]",
|
171
|
+
@parser.parse('foo.awesome')
|
172
|
+
assert_xpath "//foo//*[contains(@class, 'awesome')]",
|
173
|
+
@parser.parse('foo .awesome')
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_ident
|
177
|
+
assert_xpath '//x', @parser.parse('x')
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_parse_space
|
181
|
+
assert_xpath '//x//y', @parser.parse('x y')
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_parse_descendant
|
185
|
+
assert_xpath '//x/y', @parser.parse('x > y')
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_parse_slash
|
189
|
+
## This is non standard CSS
|
190
|
+
assert_xpath '//x/y', @parser.parse('x/y')
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_parse_doubleslash
|
194
|
+
## This is non standard CSS
|
195
|
+
assert_xpath '//x//y', @parser.parse('x//y')
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_multi_path
|
199
|
+
assert_xpath ['//x/y', '//y/z'], @parser.parse('x > y, y > z')
|
200
|
+
assert_xpath ['//x/y', '//y/z'], @parser.parse('x > y,y > z')
|
201
|
+
###
|
202
|
+
# TODO: should we make this work?
|
203
|
+
# assert_xpath ['//x/y', '//y/z'], @parser.parse('x > y | y > z')
|
204
|
+
end
|
205
|
+
|
206
|
+
def assert_xpath expecteds, asts
|
207
|
+
expecteds = [expecteds].flatten
|
208
|
+
expecteds.zip(asts).each do |expected, actual|
|
209
|
+
assert_equal expected, actual.to_xpath
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|