cocoa-xml 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.rdoc +6 -0
- data/Manifest.txt +20 -0
- data/README.rdoc +105 -0
- data/Rakefile +23 -0
- data/lib/cocoa-xml.rb +48 -0
- data/lib/cocoa-xml/nodeset.rb +57 -0
- data/lib/cocoa-xml/nsxmldocument_extras.rb +48 -0
- data/lib/cocoa-xml/nsxmlnode_extras.rb +106 -0
- data/lib/cocoa-xml/version.rb +3 -0
- data/lib/nokogiri/css.rb +27 -0
- data/lib/nokogiri/css/generated_parser.rb +646 -0
- data/lib/nokogiri/css/generated_tokenizer.rb +143 -0
- data/lib/nokogiri/css/node.rb +100 -0
- data/lib/nokogiri/css/parser.rb +83 -0
- data/lib/nokogiri/css/parser.y +230 -0
- data/lib/nokogiri/css/syntax_error.rb +7 -0
- data/lib/nokogiri/css/tokenizer.rb +8 -0
- data/lib/nokogiri/css/tokenizer.rex +55 -0
- data/lib/nokogiri/css/xpath_visitor.rb +165 -0
- data/lib/nokogiri/syntax_error.rb +4 -0
- metadata +123 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module CSS
|
3
|
+
class GeneratedTokenizer < GeneratedParser
|
4
|
+
|
5
|
+
macro
|
6
|
+
nl \n|\r\n|\r|\f
|
7
|
+
w [\s\r\n\f]*
|
8
|
+
nonascii [^\0-\177]
|
9
|
+
num -?([0-9]+|[0-9]*\.[0-9]+)
|
10
|
+
unicode \\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?
|
11
|
+
|
12
|
+
escape {unicode}|\\[^\n\r\f0-9A-Fa-f]
|
13
|
+
nmchar [_A-Za-z0-9-]|{nonascii}|{escape}
|
14
|
+
nmstart [_A-Za-z]|{nonascii}|{escape}
|
15
|
+
ident [-@]?({nmstart})({nmchar})*
|
16
|
+
name ({nmchar})+
|
17
|
+
string1 "([^\n\r\f"]|{nl}|{nonascii}|{escape})*"
|
18
|
+
string2 '([^\n\r\f']|{nl}|{nonascii}|{escape})*'
|
19
|
+
string {string1}|{string2}
|
20
|
+
|
21
|
+
rule
|
22
|
+
|
23
|
+
# [:state] pattern [actions]
|
24
|
+
|
25
|
+
has\({w} { [:HAS, text] }
|
26
|
+
{ident}\({w} { [:FUNCTION, text] }
|
27
|
+
{ident} { [:IDENT, text] }
|
28
|
+
\#{name} { [:HASH, text] }
|
29
|
+
{w}~={w} { [:INCLUDES, text] }
|
30
|
+
{w}\|={w} { [:DASHMATCH, text] }
|
31
|
+
{w}\^={w} { [:PREFIXMATCH, text] }
|
32
|
+
{w}\$={w} { [:SUFFIXMATCH, text] }
|
33
|
+
{w}\*={w} { [:SUBSTRINGMATCH, text] }
|
34
|
+
{w}!={w} { [:NOT_EQUAL, text] }
|
35
|
+
{w}={w} { [:EQUAL, text] }
|
36
|
+
{w}\) { [:RPAREN, text] }
|
37
|
+
{w}\[{w} { [:LSQUARE, text] }
|
38
|
+
{w}\] { [:RSQUARE, text] }
|
39
|
+
{w}\+{w} { [:PLUS, text] }
|
40
|
+
{w}>{w} { [:GREATER, text] }
|
41
|
+
{w},{w} { [:COMMA, text] }
|
42
|
+
{w}~{w} { [:TILDE, text] }
|
43
|
+
\:not\({w} { [:NOT, text] }
|
44
|
+
{num} { [:NUMBER, text] }
|
45
|
+
{w}\/\/{w} { [:DOUBLESLASH, text] }
|
46
|
+
{w}\/{w} { [:SLASH, text] }
|
47
|
+
|
48
|
+
U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})? {[:UNICODE_RANGE, text] }
|
49
|
+
|
50
|
+
[\s\t\r\n\f]+ { [:S, text] }
|
51
|
+
{string} { [:STRING, text] }
|
52
|
+
. { [text, text] }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module CSS
|
3
|
+
# @private
|
4
|
+
class XPathVisitor
|
5
|
+
def visit_function node
|
6
|
+
# note that nth-child and nth-last-child are preprocessed in css/node.rb.
|
7
|
+
msg = :"visit_function_#{node.value.first.gsub(/[(]/, '')}"
|
8
|
+
return self.send(msg, node) if self.respond_to?(msg)
|
9
|
+
|
10
|
+
case node.value.first
|
11
|
+
when /^text\(/
|
12
|
+
'child::text()'
|
13
|
+
when /^self\(/
|
14
|
+
"self::#{node.value[1]}"
|
15
|
+
when /^(eq|nth|nth-of-type|nth-child)\(/
|
16
|
+
if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :AN_PLUS_B
|
17
|
+
an_plus_b(node.value[1])
|
18
|
+
else
|
19
|
+
"position() = " + node.value[1]
|
20
|
+
end
|
21
|
+
when /^(first|first-of-type)\(/
|
22
|
+
"position() = 1"
|
23
|
+
when /^(last|last-of-type)\(/
|
24
|
+
"position() = last()"
|
25
|
+
when /^(nth-last-child|nth-last-of-type)\(/
|
26
|
+
"position() = last() - #{node.value[1]}"
|
27
|
+
when /^contains\(/
|
28
|
+
"contains(., #{node.value[1]})"
|
29
|
+
when /^gt\(/
|
30
|
+
"position() > #{node.value[1]}"
|
31
|
+
when /^only-child\(/
|
32
|
+
"last() = 1"
|
33
|
+
when /^comment\(/
|
34
|
+
"comment()"
|
35
|
+
when /^has\(/
|
36
|
+
node.value[1].accept(self)
|
37
|
+
else
|
38
|
+
args = ['.'] + node.value[1..-1]
|
39
|
+
"#{node.value.first}#{args.join(', ')})"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def visit_not node
|
44
|
+
'not(' + node.value.first.accept(self) + ')'
|
45
|
+
end
|
46
|
+
|
47
|
+
def visit_preceding_selector node
|
48
|
+
node.value.last.accept(self) +
|
49
|
+
'[preceding-sibling::' +
|
50
|
+
node.value.first.accept(self) +
|
51
|
+
']'
|
52
|
+
end
|
53
|
+
|
54
|
+
def visit_id node
|
55
|
+
node.value.first =~ /^#(.*)$/
|
56
|
+
"@id = '#{$1}'"
|
57
|
+
end
|
58
|
+
|
59
|
+
def visit_attribute_condition node
|
60
|
+
attribute = if (node.value.first.type == :FUNCTION) or (node.value.first.value.first =~ /::/)
|
61
|
+
''
|
62
|
+
else
|
63
|
+
'@'
|
64
|
+
end
|
65
|
+
attribute += node.value.first.accept(self)
|
66
|
+
|
67
|
+
# Support non-standard css
|
68
|
+
attribute.gsub!(/^@@/, '@')
|
69
|
+
|
70
|
+
return attribute unless node.value.length == 3
|
71
|
+
|
72
|
+
value = node.value.last
|
73
|
+
value = "'#{value}'" if value !~ /^['"]/
|
74
|
+
|
75
|
+
case node.value[1]
|
76
|
+
when :equal
|
77
|
+
attribute + " = " + "#{value}"
|
78
|
+
when :not_equal
|
79
|
+
attribute + " != " + "#{value}"
|
80
|
+
when :substring_match
|
81
|
+
"contains(#{attribute}, #{value})"
|
82
|
+
when :prefix_match
|
83
|
+
"starts-with(#{attribute}, #{value})"
|
84
|
+
when :dash_match
|
85
|
+
"#{attribute} = #{value} or starts-with(#{attribute}, concat(#{value}, '-'))"
|
86
|
+
when :includes
|
87
|
+
"contains(concat(\" \", #{attribute}, \" \"),concat(\" \", #{value}, \" \"))"
|
88
|
+
when :suffix_match
|
89
|
+
"substring(#{attribute}, string-length(#{attribute}) - " +
|
90
|
+
"string-length(#{value}) + 1, string-length(#{value})) = #{value}"
|
91
|
+
else
|
92
|
+
attribute + " #{node.value[1]} " + "#{value}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def visit_pseudo_class node
|
97
|
+
if node.value.first.is_a?(Nokogiri::CSS::Node) and node.value.first.type == :FUNCTION
|
98
|
+
node.value.first.accept(self)
|
99
|
+
else
|
100
|
+
msg = :"visit_pseudo_class_#{node.value.first.gsub(/[(]/, '')}"
|
101
|
+
return self.send(msg, node) if self.respond_to?(msg)
|
102
|
+
|
103
|
+
case node.value.first
|
104
|
+
when "first" then "position() = 1"
|
105
|
+
when "last" then "position() = last()"
|
106
|
+
when "first-of-type" then "position() = 1"
|
107
|
+
when "last-of-type" then "position() = last()"
|
108
|
+
when "only-of-type" then "last() = 1"
|
109
|
+
when "empty" then "not(node())"
|
110
|
+
when "parent" then "node()"
|
111
|
+
when "root" then "not(parent::*)"
|
112
|
+
else
|
113
|
+
node.value.first + "(.)"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def visit_class_condition node
|
119
|
+
"contains(concat(' ', @class, ' '), ' #{node.value.first} ')"
|
120
|
+
end
|
121
|
+
|
122
|
+
{
|
123
|
+
'combinator' => ' and ',
|
124
|
+
'direct_adjacent_selector' => "/following-sibling::*[1]/self::",
|
125
|
+
'descendant_selector' => '//',
|
126
|
+
'child_selector' => '/',
|
127
|
+
}.each do |k,v|
|
128
|
+
class_eval %{
|
129
|
+
def visit_#{k} node
|
130
|
+
"\#{node.value.first.accept(self)}#{v}\#{node.value.last.accept(self)}"
|
131
|
+
end
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
def visit_conditional_selector node
|
136
|
+
node.value.first.accept(self) + '[' +
|
137
|
+
node.value.last.accept(self) + ']'
|
138
|
+
end
|
139
|
+
|
140
|
+
def visit_element_name node
|
141
|
+
node.value.first
|
142
|
+
end
|
143
|
+
|
144
|
+
def accept node
|
145
|
+
node.accept(self)
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
def an_plus_b node
|
150
|
+
raise ArgumentError, "expected an+b node to contain 4 tokens, but is #{node.value.inspect}" unless node.value.size == 4
|
151
|
+
|
152
|
+
a = node.value[0].to_i
|
153
|
+
b = node.value[3].to_i
|
154
|
+
|
155
|
+
if (b == 0)
|
156
|
+
return "(position() mod #{a}) = 0"
|
157
|
+
else
|
158
|
+
compare = (a < 0) ? "<=" : ">="
|
159
|
+
return "(position() #{compare} #{b}) and (((position()-#{b}) mod #{a.abs}) = 0)"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cocoa-xml
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Hoffman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-30 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rubyforge
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.0.3
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: gemcutter
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.3.0
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: hoe-yard
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.1.2
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: hoe
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.5.0
|
54
|
+
version:
|
55
|
+
description: |-
|
56
|
+
Cocoa-xml provides a more ruby like interface to Cocoa's NSXMLDocument
|
57
|
+
and classes that inherit from NSXMLNode. It provides access to XPath,
|
58
|
+
XQuery, and CSS selectors for searching documents.
|
59
|
+
email:
|
60
|
+
- cehoffman@gmail.com
|
61
|
+
executables: []
|
62
|
+
|
63
|
+
extensions: []
|
64
|
+
|
65
|
+
extra_rdoc_files:
|
66
|
+
- Manifest.txt
|
67
|
+
- History.rdoc
|
68
|
+
files:
|
69
|
+
- History.rdoc
|
70
|
+
- Manifest.txt
|
71
|
+
- README.rdoc
|
72
|
+
- Rakefile
|
73
|
+
- lib/cocoa-xml.rb
|
74
|
+
- lib/cocoa-xml/nodeset.rb
|
75
|
+
- lib/cocoa-xml/version.rb
|
76
|
+
- lib/cocoa-xml/nsxmlnode_extras.rb
|
77
|
+
- lib/cocoa-xml/nsxmldocument_extras.rb
|
78
|
+
- lib/nokogiri/css.rb
|
79
|
+
- lib/nokogiri/syntax_error.rb
|
80
|
+
- lib/nokogiri/css/generated_parser.rb
|
81
|
+
- lib/nokogiri/css/generated_tokenizer.rb
|
82
|
+
- lib/nokogiri/css/node.rb
|
83
|
+
- lib/nokogiri/css/parser.rb
|
84
|
+
- lib/nokogiri/css/parser.y
|
85
|
+
- lib/nokogiri/css/syntax_error.rb
|
86
|
+
- lib/nokogiri/css/tokenizer.rb
|
87
|
+
- lib/nokogiri/css/tokenizer.rex
|
88
|
+
- lib/nokogiri/css/xpath_visitor.rb
|
89
|
+
has_rdoc: yard
|
90
|
+
homepage: http://github.com/cehoffman/cocoa-xml
|
91
|
+
licenses: []
|
92
|
+
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options:
|
95
|
+
- --no-private
|
96
|
+
- --title
|
97
|
+
- Cocoa-XML
|
98
|
+
- --markup
|
99
|
+
- rdoc
|
100
|
+
- --quiet
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: "0"
|
108
|
+
version:
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: "0"
|
114
|
+
version:
|
115
|
+
requirements: []
|
116
|
+
|
117
|
+
rubyforge_project: cocoa-xml
|
118
|
+
rubygems_version: 1.3.5
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: Cocoa-xml provides a more ruby like interface to Cocoa's NSXMLDocument and classes that inherit from NSXMLNode
|
122
|
+
test_files: []
|
123
|
+
|