nokogiri 1.12.5 → 1.13.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of nokogiri might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/README.md +9 -7
- data/bin/nokogiri +63 -50
- data/dependencies.yml +13 -64
- data/ext/nokogiri/extconf.rb +81 -46
- data/ext/nokogiri/gumbo.c +1 -1
- data/ext/nokogiri/html4_sax_parser_context.c +2 -3
- data/ext/nokogiri/nokogiri.h +9 -0
- data/ext/nokogiri/xml_attr.c +2 -2
- data/ext/nokogiri/xml_attribute_decl.c +3 -3
- data/ext/nokogiri/xml_cdata.c +1 -1
- data/ext/nokogiri/xml_document.c +41 -37
- data/ext/nokogiri/xml_document_fragment.c +0 -2
- data/ext/nokogiri/xml_dtd.c +10 -10
- data/ext/nokogiri/xml_element_decl.c +3 -3
- data/ext/nokogiri/xml_encoding_handler.c +25 -11
- data/ext/nokogiri/xml_entity_decl.c +5 -5
- data/ext/nokogiri/xml_namespace.c +41 -5
- data/ext/nokogiri/xml_node.c +708 -382
- data/ext/nokogiri/xml_node_set.c +4 -4
- data/ext/nokogiri/xml_reader.c +88 -11
- data/ext/nokogiri/xml_sax_parser_context.c +10 -3
- data/ext/nokogiri/xml_schema.c +3 -3
- data/ext/nokogiri/xml_text.c +1 -1
- data/ext/nokogiri/xml_xpath_context.c +76 -50
- data/ext/nokogiri/xslt_stylesheet.c +107 -9
- data/gumbo-parser/src/parser.c +0 -11
- data/lib/nokogiri/class_resolver.rb +67 -0
- data/lib/nokogiri/css/node.rb +9 -8
- data/lib/nokogiri/css/parser.rb +360 -341
- data/lib/nokogiri/css/parser.y +249 -244
- data/lib/nokogiri/css/parser_extras.rb +22 -20
- data/lib/nokogiri/css/syntax_error.rb +1 -0
- data/lib/nokogiri/css/tokenizer.rb +4 -3
- data/lib/nokogiri/css/tokenizer.rex +3 -2
- data/lib/nokogiri/css/xpath_visitor.rb +179 -82
- data/lib/nokogiri/css.rb +38 -6
- data/lib/nokogiri/decorators/slop.rb +8 -7
- data/lib/nokogiri/extension.rb +1 -1
- data/lib/nokogiri/gumbo.rb +1 -0
- data/lib/nokogiri/html.rb +16 -10
- data/lib/nokogiri/html4/builder.rb +1 -0
- data/lib/nokogiri/html4/document.rb +88 -77
- data/lib/nokogiri/html4/document_fragment.rb +11 -7
- data/lib/nokogiri/html4/element_description.rb +1 -0
- data/lib/nokogiri/html4/element_description_defaults.rb +426 -520
- data/lib/nokogiri/html4/entity_lookup.rb +2 -1
- data/lib/nokogiri/html4/sax/parser.rb +5 -2
- data/lib/nokogiri/html4/sax/parser_context.rb +1 -0
- data/lib/nokogiri/html4/sax/push_parser.rb +7 -7
- data/lib/nokogiri/html4.rb +11 -5
- data/lib/nokogiri/html5/document.rb +27 -10
- data/lib/nokogiri/html5/document_fragment.rb +5 -2
- data/lib/nokogiri/html5/node.rb +10 -3
- data/lib/nokogiri/html5.rb +69 -64
- data/lib/nokogiri/jruby/dependencies.rb +10 -9
- data/lib/nokogiri/syntax_error.rb +1 -0
- data/lib/nokogiri/version/constant.rb +2 -1
- data/lib/nokogiri/version/info.rb +20 -13
- data/lib/nokogiri/version.rb +1 -0
- data/lib/nokogiri/xml/attr.rb +5 -3
- data/lib/nokogiri/xml/attribute_decl.rb +2 -1
- data/lib/nokogiri/xml/builder.rb +34 -32
- data/lib/nokogiri/xml/cdata.rb +2 -1
- data/lib/nokogiri/xml/character_data.rb +1 -0
- data/lib/nokogiri/xml/document.rb +144 -103
- data/lib/nokogiri/xml/document_fragment.rb +41 -38
- data/lib/nokogiri/xml/dtd.rb +3 -2
- data/lib/nokogiri/xml/element_content.rb +1 -0
- data/lib/nokogiri/xml/element_decl.rb +2 -1
- data/lib/nokogiri/xml/entity_decl.rb +3 -2
- data/lib/nokogiri/xml/entity_reference.rb +1 -0
- data/lib/nokogiri/xml/namespace.rb +2 -0
- data/lib/nokogiri/xml/node/save_options.rb +8 -4
- data/lib/nokogiri/xml/node.rb +521 -351
- data/lib/nokogiri/xml/node_set.rb +50 -54
- data/lib/nokogiri/xml/notation.rb +12 -0
- data/lib/nokogiri/xml/parse_options.rb +12 -7
- data/lib/nokogiri/xml/pp/character_data.rb +8 -6
- data/lib/nokogiri/xml/pp/node.rb +24 -26
- data/lib/nokogiri/xml/pp.rb +1 -0
- data/lib/nokogiri/xml/processing_instruction.rb +2 -1
- data/lib/nokogiri/xml/reader.rb +20 -24
- data/lib/nokogiri/xml/relax_ng.rb +1 -0
- data/lib/nokogiri/xml/sax/document.rb +20 -19
- data/lib/nokogiri/xml/sax/parser.rb +37 -34
- data/lib/nokogiri/xml/sax/parser_context.rb +7 -3
- data/lib/nokogiri/xml/sax/push_parser.rb +5 -5
- data/lib/nokogiri/xml/sax.rb +1 -0
- data/lib/nokogiri/xml/schema.rb +7 -6
- data/lib/nokogiri/xml/searchable.rb +93 -62
- data/lib/nokogiri/xml/syntax_error.rb +5 -4
- data/lib/nokogiri/xml/text.rb +1 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
- data/lib/nokogiri/xml/xpath.rb +12 -0
- data/lib/nokogiri/xml/xpath_context.rb +2 -3
- data/lib/nokogiri/xml.rb +4 -3
- data/lib/nokogiri/xslt/stylesheet.rb +1 -0
- data/lib/nokogiri/xslt.rb +21 -13
- data/lib/nokogiri.rb +19 -16
- data/lib/xsd/xmlparser/nokogiri.rb +25 -24
- data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
- data/patches/libxslt/0001-update-automake-files-for-arm64.patch +2445 -1919
- data/ports/archives/libxml2-2.10.3.tar.xz +0 -0
- data/ports/archives/libxslt-1.1.37.tar.xz +0 -0
- metadata +103 -34
- data/patches/libxml2/0004-use-glibc-strlen.patch +0 -53
- data/patches/libxml2/0006-update-automake-files-for-arm64.patch +0 -2511
- data/patches/libxml2/0007-Fix-XPath-recursion-limit.patch +0 -31
- data/patches/libxslt/0002-Fix-xml2-config-check-in-configure-script.patch +0 -19
- data/ports/archives/libxml2-2.9.12.tar.gz +0 -0
- data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
data/lib/nokogiri/css/parser.y
CHANGED
@@ -5,256 +5,261 @@ token COMMA NUMBER PREFIXMATCH SUFFIXMATCH SUBSTRINGMATCH TILDE NOT_EQUAL
|
|
5
5
|
token SLASH DOUBLESLASH NOT EQUAL RPAREN LSQUARE RSQUARE HAS
|
6
6
|
|
7
7
|
rule
|
8
|
-
selector
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
class
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
}
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
attrib
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
hcap_1toN
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
: S
|
250
|
-
|
|
251
|
-
;
|
8
|
+
selector:
|
9
|
+
selector COMMA simple_selector_1toN {
|
10
|
+
result = [val[0], val[2]].flatten
|
11
|
+
}
|
12
|
+
| prefixless_combinator_selector { result = val.flatten }
|
13
|
+
| optional_S simple_selector_1toN { result = [val[1]].flatten }
|
14
|
+
;
|
15
|
+
|
16
|
+
combinator:
|
17
|
+
PLUS { result = :DIRECT_ADJACENT_SELECTOR }
|
18
|
+
| GREATER { result = :CHILD_SELECTOR }
|
19
|
+
| TILDE { result = :FOLLOWING_SELECTOR }
|
20
|
+
| DOUBLESLASH { result = :DESCENDANT_SELECTOR }
|
21
|
+
| SLASH { result = :CHILD_SELECTOR }
|
22
|
+
;
|
23
|
+
|
24
|
+
xpath_attribute_name:
|
25
|
+
'@' IDENT { result = val[1] }
|
26
|
+
;
|
27
|
+
|
28
|
+
xpath_attribute:
|
29
|
+
xpath_attribute_name { result = Node.new(:ATTRIB_NAME, [val[0]]) }
|
30
|
+
;
|
31
|
+
|
32
|
+
simple_selector:
|
33
|
+
element_name hcap_0toN {
|
34
|
+
result = if val[1].nil?
|
35
|
+
val[0]
|
36
|
+
else
|
37
|
+
Node.new(:CONDITIONAL_SELECTOR, [val[0], val[1]])
|
38
|
+
end
|
39
|
+
}
|
40
|
+
| function
|
41
|
+
| function pseudo { result = Node.new(:CONDITIONAL_SELECTOR, val) }
|
42
|
+
| function attrib { result = Node.new(:CONDITIONAL_SELECTOR, val) }
|
43
|
+
| hcap_1toN { result = Node.new(:CONDITIONAL_SELECTOR, [Node.new(:ELEMENT_NAME, ['*']), val[0]]) }
|
44
|
+
| xpath_attribute
|
45
|
+
;
|
46
|
+
|
47
|
+
prefixless_combinator_selector:
|
48
|
+
combinator simple_selector_1toN { result = Node.new(val[0], [nil, val[1]]) }
|
49
|
+
;
|
50
|
+
|
51
|
+
simple_selector_1toN:
|
52
|
+
simple_selector combinator simple_selector_1toN { result = Node.new(val[1], [val[0], val[2]]) }
|
53
|
+
| simple_selector S simple_selector_1toN { result = Node.new(:DESCENDANT_SELECTOR, [val[0], val[2]]) }
|
54
|
+
| simple_selector
|
55
|
+
;
|
56
|
+
|
57
|
+
class:
|
58
|
+
'.' IDENT { result = Node.new(:CLASS_CONDITION, [unescape_css_identifier(val[1])]) }
|
59
|
+
;
|
60
|
+
|
61
|
+
element_name:
|
62
|
+
namespaced_ident
|
63
|
+
| '*' { result = Node.new(:ELEMENT_NAME, val) }
|
64
|
+
;
|
65
|
+
|
66
|
+
namespaced_ident:
|
67
|
+
namespace '|' IDENT { result = Node.new(:ELEMENT_NAME, [[val[0], val[2]].compact.join(':')]) }
|
68
|
+
| IDENT {
|
69
|
+
name = @namespaces.key?('xmlns') ? "xmlns:#{val[0]}" : val[0]
|
70
|
+
result = Node.new(:ELEMENT_NAME, [name])
|
71
|
+
}
|
72
|
+
;
|
73
|
+
|
74
|
+
namespace:
|
75
|
+
IDENT { result = val[0] }
|
76
|
+
|
|
77
|
+
;
|
78
|
+
|
79
|
+
attrib:
|
80
|
+
LSQUARE attrib_name attrib_val_0or1 RSQUARE {
|
81
|
+
result = Node.new(:ATTRIBUTE_CONDITION, [val[1]] + (val[2] || []))
|
82
|
+
}
|
83
|
+
| LSQUARE function attrib_val_0or1 RSQUARE {
|
84
|
+
result = Node.new(:ATTRIBUTE_CONDITION, [val[1]] + (val[2] || []))
|
85
|
+
}
|
86
|
+
| LSQUARE NUMBER RSQUARE {
|
87
|
+
result = Node.new(:PSEUDO_CLASS, [Node.new(:FUNCTION, ['nth-child(', val[1]])])
|
88
|
+
}
|
89
|
+
;
|
90
|
+
|
91
|
+
attrib_name:
|
92
|
+
namespace '|' IDENT { result = Node.new(:ATTRIB_NAME, [[val[0], val[2]].compact.join(':')]) }
|
93
|
+
| IDENT { result = Node.new(:ATTRIB_NAME, [val[0]]) }
|
94
|
+
| xpath_attribute
|
95
|
+
;
|
96
|
+
|
97
|
+
function:
|
98
|
+
FUNCTION RPAREN {
|
99
|
+
result = Node.new(:FUNCTION, [val[0].strip])
|
100
|
+
}
|
101
|
+
| FUNCTION expr RPAREN {
|
102
|
+
result = Node.new(:FUNCTION, [val[0].strip, val[1]].flatten)
|
103
|
+
}
|
104
|
+
| FUNCTION nth RPAREN {
|
105
|
+
result = Node.new(:FUNCTION, [val[0].strip, val[1]].flatten)
|
106
|
+
}
|
107
|
+
| NOT expr RPAREN {
|
108
|
+
result = Node.new(:FUNCTION, [val[0].strip, val[1]].flatten)
|
109
|
+
}
|
110
|
+
| HAS selector RPAREN {
|
111
|
+
result = Node.new(:FUNCTION, [val[0].strip, val[1]].flatten)
|
112
|
+
}
|
113
|
+
;
|
114
|
+
|
115
|
+
expr:
|
116
|
+
NUMBER COMMA expr { result = [val[0], val[2]] }
|
117
|
+
| STRING COMMA expr { result = [val[0], val[2]] }
|
118
|
+
| IDENT COMMA expr { result = [val[0], val[2]] }
|
119
|
+
| xpath_attribute COMMA expr { result = [val[0], val[2]] }
|
120
|
+
| NUMBER
|
121
|
+
| STRING
|
122
|
+
| IDENT {
|
123
|
+
case val[0]
|
124
|
+
when 'even'
|
125
|
+
result = Node.new(:NTH, ['2','n','+','0'])
|
126
|
+
when 'odd'
|
127
|
+
result = Node.new(:NTH, ['2','n','+','1'])
|
128
|
+
when 'n'
|
129
|
+
result = Node.new(:NTH, ['1','n','+','0'])
|
130
|
+
else
|
131
|
+
result = val
|
132
|
+
end
|
133
|
+
}
|
134
|
+
| xpath_attribute
|
135
|
+
;
|
136
|
+
|
137
|
+
nth:
|
138
|
+
NUMBER IDENT PLUS NUMBER # 5n+3 -5n+3
|
139
|
+
{
|
140
|
+
if val[1] == 'n'
|
141
|
+
result = Node.new(:NTH, val)
|
142
|
+
else
|
143
|
+
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
144
|
+
end
|
145
|
+
}
|
146
|
+
| IDENT PLUS NUMBER { # n+3, -n+3
|
147
|
+
if val[0] == 'n'
|
148
|
+
val.unshift("1")
|
149
|
+
result = Node.new(:NTH, val)
|
150
|
+
elsif val[0] == '-n'
|
151
|
+
val[0] = 'n'
|
152
|
+
val.unshift("-1")
|
153
|
+
result = Node.new(:NTH, val)
|
154
|
+
else
|
155
|
+
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
156
|
+
end
|
157
|
+
}
|
158
|
+
| NUMBER IDENT { # 5n, -5n, 10n-1
|
159
|
+
n = val[1]
|
160
|
+
if n[0, 2] == 'n-'
|
161
|
+
val[1] = 'n'
|
162
|
+
val << "-"
|
163
|
+
# b is contained in n as n is the string "n-b"
|
164
|
+
val << n[2, n.size]
|
165
|
+
result = Node.new(:NTH, val)
|
166
|
+
elsif n == 'n'
|
167
|
+
val << "+"
|
168
|
+
val << "0"
|
169
|
+
result = Node.new(:NTH, val)
|
170
|
+
else
|
171
|
+
raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
|
172
|
+
end
|
173
|
+
}
|
174
|
+
;
|
175
|
+
|
176
|
+
pseudo:
|
177
|
+
':' function {
|
178
|
+
result = Node.new(:PSEUDO_CLASS, [val[1]])
|
179
|
+
}
|
180
|
+
| ':' IDENT { result = Node.new(:PSEUDO_CLASS, [val[1]]) }
|
181
|
+
;
|
182
|
+
|
183
|
+
hcap_0toN:
|
184
|
+
hcap_1toN
|
185
|
+
|
|
186
|
+
;
|
187
|
+
|
188
|
+
hcap_1toN:
|
189
|
+
attribute_id hcap_1toN {
|
190
|
+
result = Node.new(:COMBINATOR, val)
|
191
|
+
}
|
192
|
+
| class hcap_1toN {
|
193
|
+
result = Node.new(:COMBINATOR, val)
|
194
|
+
}
|
195
|
+
| attrib hcap_1toN {
|
196
|
+
result = Node.new(:COMBINATOR, val)
|
197
|
+
}
|
198
|
+
| pseudo hcap_1toN {
|
199
|
+
result = Node.new(:COMBINATOR, val)
|
200
|
+
}
|
201
|
+
| negation hcap_1toN {
|
202
|
+
result = Node.new(:COMBINATOR, val)
|
203
|
+
}
|
204
|
+
| attribute_id
|
205
|
+
| class
|
206
|
+
| attrib
|
207
|
+
| pseudo
|
208
|
+
| negation
|
209
|
+
;
|
210
|
+
|
211
|
+
attribute_id:
|
212
|
+
HASH { result = Node.new(:ID, [unescape_css_identifier(val[0])]) }
|
213
|
+
;
|
214
|
+
|
215
|
+
attrib_val_0or1:
|
216
|
+
eql_incl_dash IDENT { result = [val[0], unescape_css_identifier(val[1])] }
|
217
|
+
| eql_incl_dash STRING { result = [val[0], unescape_css_string(val[1])] }
|
218
|
+
| eql_incl_dash NUMBER { result = [val[0], val[1]] }
|
219
|
+
|
|
220
|
+
;
|
221
|
+
|
222
|
+
eql_incl_dash:
|
223
|
+
EQUAL { result = :equal }
|
224
|
+
| PREFIXMATCH { result = :prefix_match }
|
225
|
+
| SUFFIXMATCH { result = :suffix_match }
|
226
|
+
| SUBSTRINGMATCH { result = :substring_match }
|
227
|
+
| NOT_EQUAL { result = :not_equal }
|
228
|
+
| INCLUDES { result = :includes }
|
229
|
+
| DASHMATCH { result = :dash_match }
|
230
|
+
;
|
231
|
+
|
232
|
+
negation:
|
233
|
+
NOT negation_arg RPAREN {
|
234
|
+
result = Node.new(:NOT, [val[1]])
|
235
|
+
}
|
236
|
+
;
|
237
|
+
|
238
|
+
negation_arg:
|
239
|
+
element_name
|
240
|
+
| element_name hcap_1toN
|
241
|
+
| hcap_1toN
|
242
|
+
;
|
243
|
+
|
244
|
+
optional_S:
|
245
|
+
S
|
246
|
+
|
|
247
|
+
;
|
248
|
+
|
252
249
|
end
|
253
250
|
|
254
251
|
---- header
|
255
252
|
|
256
253
|
require_relative "parser_extras"
|
257
254
|
|
255
|
+
module Nokogiri
|
256
|
+
module CSS
|
257
|
+
# :nodoc: all
|
258
|
+
class Parser < Racc::Parser
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
258
263
|
---- inner
|
259
264
|
|
260
265
|
def unescape_css_identifier(identifier)
|
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "thread"
|
3
4
|
|
4
5
|
module Nokogiri
|
5
6
|
module CSS
|
6
|
-
class Parser < Racc::Parser
|
7
|
+
class Parser < Racc::Parser # :nodoc:
|
7
8
|
CACHE_SWITCH_NAME = :nokogiri_css_parser_cache_is_off
|
8
9
|
|
9
10
|
@cache = {}
|
@@ -16,19 +17,21 @@ module Nokogiri
|
|
16
17
|
end
|
17
18
|
|
18
19
|
# Set a thread-local boolean to turn cacheing on and off. Truthy values turn the cache on, falsey values turn the cache off.
|
19
|
-
def set_cache(value)
|
20
|
+
def set_cache(value) # rubocop:disable Naming/AccessorMethodName
|
20
21
|
Thread.current[CACHE_SWITCH_NAME] = !value
|
21
22
|
end
|
22
23
|
|
23
24
|
# Get the css selector in +string+ from the cache
|
24
25
|
def [](string)
|
25
|
-
return unless cache_on?
|
26
|
+
return nil unless cache_on?
|
27
|
+
|
26
28
|
@mutex.synchronize { @cache[string] }
|
27
29
|
end
|
28
30
|
|
29
31
|
# Set the css selector in +string+ in the cache to +value+
|
30
32
|
def []=(string, value)
|
31
33
|
return value unless cache_on?
|
34
|
+
|
32
35
|
@mutex.synchronize { @cache[string] = value }
|
33
36
|
end
|
34
37
|
|
@@ -46,10 +49,10 @@ module Nokogiri
|
|
46
49
|
# Execute +block+ without cache
|
47
50
|
def without_cache(&block)
|
48
51
|
original_cache_setting = cache_on?
|
49
|
-
set_cache
|
50
|
-
|
52
|
+
set_cache(false)
|
53
|
+
yield
|
51
54
|
ensure
|
52
|
-
set_cache
|
55
|
+
set_cache(original_cache_setting)
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
@@ -61,7 +64,7 @@ module Nokogiri
|
|
61
64
|
end
|
62
65
|
|
63
66
|
def parse(string)
|
64
|
-
@tokenizer.scan_setup
|
67
|
+
@tokenizer.scan_setup(string)
|
65
68
|
do_parse
|
66
69
|
end
|
67
70
|
|
@@ -70,24 +73,23 @@ module Nokogiri
|
|
70
73
|
end
|
71
74
|
|
72
75
|
# Get the xpath for +string+ using +options+
|
73
|
-
def xpath_for(string,
|
74
|
-
key =
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
args = [
|
79
|
-
options[:prefix] || "//",
|
80
|
-
options[:visitor] || XPathVisitor.new,
|
81
|
-
]
|
82
|
-
self.class[key] = parse(string).map { |ast|
|
83
|
-
ast.to_xpath(*args)
|
84
|
-
}
|
76
|
+
def xpath_for(string, prefix, visitor)
|
77
|
+
key = cache_key(string, prefix, visitor)
|
78
|
+
self.class[key] ||= parse(string).map do |ast|
|
79
|
+
ast.to_xpath(prefix, visitor)
|
80
|
+
end
|
85
81
|
end
|
86
82
|
|
87
83
|
# On CSS parser error, raise an exception
|
88
84
|
def on_error(error_token_id, error_value, value_stack)
|
89
85
|
after = value_stack.compact.last
|
90
|
-
raise SyntaxError
|
86
|
+
raise SyntaxError, "unexpected '#{error_value}' after '#{after}'"
|
87
|
+
end
|
88
|
+
|
89
|
+
def cache_key(query, prefix, visitor)
|
90
|
+
if self.class.cache_on?
|
91
|
+
[query, prefix, @namespaces, visitor.config]
|
92
|
+
end
|
91
93
|
end
|
92
94
|
end
|
93
95
|
end
|
@@ -7,7 +7,8 @@
|
|
7
7
|
|
8
8
|
module Nokogiri
|
9
9
|
module CSS
|
10
|
-
|
10
|
+
# :nodoc: all
|
11
|
+
class Tokenizer
|
11
12
|
require 'strscan'
|
12
13
|
|
13
14
|
class ScanError < StandardError ; end
|
@@ -62,10 +63,10 @@ class Tokenizer # :nodoc:
|
|
62
63
|
when (text = @ss.scan(/has\([\s]*/))
|
63
64
|
action { [:HAS, text] }
|
64
65
|
|
65
|
-
when (text = @ss.scan(
|
66
|
+
when (text = @ss.scan(/-?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*\([\s]*/))
|
66
67
|
action { [:FUNCTION, text] }
|
67
68
|
|
68
|
-
when (text = @ss.scan(
|
69
|
+
when (text = @ss.scan(/-?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])*/))
|
69
70
|
action { [:IDENT, text] }
|
70
71
|
|
71
72
|
when (text = @ss.scan(/\#([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s])?|\\[^\n\r\f0-9A-Fa-f])+/))
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Nokogiri
|
2
2
|
module CSS
|
3
|
-
|
3
|
+
# :nodoc: all
|
4
|
+
class Tokenizer
|
4
5
|
|
5
6
|
macro
|
6
7
|
nl \n|\r\n|\r|\f
|
@@ -12,7 +13,7 @@ macro
|
|
12
13
|
escape {unicode}|\\[^\n\r\f0-9A-Fa-f]
|
13
14
|
nmchar [_A-Za-z0-9-]|{nonascii}|{escape}
|
14
15
|
nmstart [_A-Za-z]|{nonascii}|{escape}
|
15
|
-
ident
|
16
|
+
ident -?({nmstart})({nmchar})*
|
16
17
|
name ({nmchar})+
|
17
18
|
string1 "([^\n\r\f"]|{nl}|{nonascii}|{escape})*(?<!\\)(?:\\{2})*"
|
18
19
|
string2 '([^\n\r\f']|{nl}|{nonascii}|{escape})*(?<!\\)(?:\\{2})*'
|