nokogiri 1.11.3 → 1.13.8

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.

Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/LICENSE-DEPENDENCIES.md +243 -22
  4. data/LICENSE.md +1 -1
  5. data/README.md +14 -11
  6. data/bin/nokogiri +63 -50
  7. data/dependencies.yml +13 -64
  8. data/ext/nokogiri/depend +35 -34
  9. data/ext/nokogiri/extconf.rb +237 -133
  10. data/ext/nokogiri/gumbo.c +584 -0
  11. data/ext/nokogiri/{html_document.c → html4_document.c} +8 -8
  12. data/ext/nokogiri/{html_element_description.c → html4_element_description.c} +21 -19
  13. data/ext/nokogiri/{html_entity_lookup.c → html4_entity_lookup.c} +7 -7
  14. data/ext/nokogiri/{html_sax_parser_context.c → html4_sax_parser_context.c} +8 -8
  15. data/ext/nokogiri/{html_sax_push_parser.c → html4_sax_push_parser.c} +4 -4
  16. data/ext/nokogiri/libxml2_backwards_compat.c +30 -30
  17. data/ext/nokogiri/nokogiri.c +70 -38
  18. data/ext/nokogiri/nokogiri.h +27 -9
  19. data/ext/nokogiri/xml_attr.c +2 -2
  20. data/ext/nokogiri/xml_attribute_decl.c +3 -3
  21. data/ext/nokogiri/xml_cdata.c +1 -1
  22. data/ext/nokogiri/xml_document.c +50 -50
  23. data/ext/nokogiri/xml_document_fragment.c +0 -2
  24. data/ext/nokogiri/xml_dtd.c +10 -10
  25. data/ext/nokogiri/xml_element_content.c +2 -0
  26. data/ext/nokogiri/xml_element_decl.c +3 -3
  27. data/ext/nokogiri/xml_encoding_handler.c +31 -12
  28. data/ext/nokogiri/xml_entity_decl.c +5 -5
  29. data/ext/nokogiri/xml_namespace.c +4 -2
  30. data/ext/nokogiri/xml_node.c +833 -492
  31. data/ext/nokogiri/xml_node_set.c +24 -24
  32. data/ext/nokogiri/xml_reader.c +90 -11
  33. data/ext/nokogiri/xml_sax_parser.c +6 -6
  34. data/ext/nokogiri/xml_sax_parser_context.c +12 -3
  35. data/ext/nokogiri/xml_schema.c +5 -3
  36. data/ext/nokogiri/xml_text.c +1 -1
  37. data/ext/nokogiri/xml_xpath_context.c +110 -85
  38. data/ext/nokogiri/xslt_stylesheet.c +109 -10
  39. data/gumbo-parser/CHANGES.md +63 -0
  40. data/gumbo-parser/Makefile +101 -0
  41. data/gumbo-parser/THANKS +27 -0
  42. data/gumbo-parser/src/Makefile +34 -0
  43. data/gumbo-parser/src/README.md +41 -0
  44. data/gumbo-parser/src/ascii.c +75 -0
  45. data/gumbo-parser/src/ascii.h +115 -0
  46. data/gumbo-parser/src/attribute.c +42 -0
  47. data/gumbo-parser/src/attribute.h +17 -0
  48. data/gumbo-parser/src/char_ref.c +22225 -0
  49. data/gumbo-parser/src/char_ref.h +29 -0
  50. data/gumbo-parser/src/char_ref.rl +2154 -0
  51. data/gumbo-parser/src/error.c +626 -0
  52. data/gumbo-parser/src/error.h +148 -0
  53. data/gumbo-parser/src/foreign_attrs.c +104 -0
  54. data/gumbo-parser/src/foreign_attrs.gperf +27 -0
  55. data/gumbo-parser/src/gumbo.h +943 -0
  56. data/gumbo-parser/src/insertion_mode.h +33 -0
  57. data/gumbo-parser/src/macros.h +91 -0
  58. data/gumbo-parser/src/parser.c +4875 -0
  59. data/gumbo-parser/src/parser.h +41 -0
  60. data/gumbo-parser/src/replacement.h +33 -0
  61. data/gumbo-parser/src/string_buffer.c +103 -0
  62. data/gumbo-parser/src/string_buffer.h +68 -0
  63. data/gumbo-parser/src/string_piece.c +48 -0
  64. data/gumbo-parser/src/svg_attrs.c +174 -0
  65. data/gumbo-parser/src/svg_attrs.gperf +77 -0
  66. data/gumbo-parser/src/svg_tags.c +137 -0
  67. data/gumbo-parser/src/svg_tags.gperf +55 -0
  68. data/gumbo-parser/src/tag.c +222 -0
  69. data/gumbo-parser/src/tag_lookup.c +382 -0
  70. data/gumbo-parser/src/tag_lookup.gperf +169 -0
  71. data/gumbo-parser/src/tag_lookup.h +13 -0
  72. data/gumbo-parser/src/token_buffer.c +79 -0
  73. data/gumbo-parser/src/token_buffer.h +71 -0
  74. data/gumbo-parser/src/token_type.h +17 -0
  75. data/gumbo-parser/src/tokenizer.c +3463 -0
  76. data/gumbo-parser/src/tokenizer.h +112 -0
  77. data/gumbo-parser/src/tokenizer_states.h +339 -0
  78. data/gumbo-parser/src/utf8.c +245 -0
  79. data/gumbo-parser/src/utf8.h +164 -0
  80. data/gumbo-parser/src/util.c +68 -0
  81. data/gumbo-parser/src/util.h +30 -0
  82. data/gumbo-parser/src/vector.c +111 -0
  83. data/gumbo-parser/src/vector.h +45 -0
  84. data/lib/nokogiri/class_resolver.rb +67 -0
  85. data/lib/nokogiri/css/node.rb +9 -8
  86. data/lib/nokogiri/css/parser.rb +361 -342
  87. data/lib/nokogiri/css/parser.y +250 -245
  88. data/lib/nokogiri/css/parser_extras.rb +22 -20
  89. data/lib/nokogiri/css/syntax_error.rb +2 -1
  90. data/lib/nokogiri/css/tokenizer.rb +4 -3
  91. data/lib/nokogiri/css/tokenizer.rex +3 -2
  92. data/lib/nokogiri/css/xpath_visitor.rb +179 -82
  93. data/lib/nokogiri/css.rb +49 -17
  94. data/lib/nokogiri/decorators/slop.rb +8 -7
  95. data/lib/nokogiri/extension.rb +8 -3
  96. data/lib/nokogiri/gumbo.rb +15 -0
  97. data/lib/nokogiri/html.rb +37 -27
  98. data/lib/nokogiri/{html → html4}/builder.rb +3 -2
  99. data/lib/nokogiri/{html → html4}/document.rb +92 -81
  100. data/lib/nokogiri/{html → html4}/document_fragment.rb +13 -9
  101. data/lib/nokogiri/{html → html4}/element_description.rb +2 -1
  102. data/lib/nokogiri/html4/element_description_defaults.rb +578 -0
  103. data/lib/nokogiri/{html → html4}/entity_lookup.rb +3 -2
  104. data/lib/nokogiri/{html → html4}/sax/parser.rb +16 -16
  105. data/lib/nokogiri/html4/sax/parser_context.rb +20 -0
  106. data/lib/nokogiri/{html → html4}/sax/push_parser.rb +11 -11
  107. data/lib/nokogiri/html4.rb +46 -0
  108. data/lib/nokogiri/html5/document.rb +91 -0
  109. data/lib/nokogiri/html5/document_fragment.rb +83 -0
  110. data/lib/nokogiri/html5/node.rb +100 -0
  111. data/lib/nokogiri/html5.rb +478 -0
  112. data/lib/nokogiri/jruby/dependencies.rb +10 -9
  113. data/lib/nokogiri/syntax_error.rb +1 -0
  114. data/lib/nokogiri/version/constant.rb +2 -1
  115. data/lib/nokogiri/version/info.rb +31 -14
  116. data/lib/nokogiri/version.rb +1 -0
  117. data/lib/nokogiri/xml/attr.rb +5 -3
  118. data/lib/nokogiri/xml/attribute_decl.rb +2 -1
  119. data/lib/nokogiri/xml/builder.rb +71 -31
  120. data/lib/nokogiri/xml/cdata.rb +2 -1
  121. data/lib/nokogiri/xml/character_data.rb +1 -0
  122. data/lib/nokogiri/xml/document.rb +183 -96
  123. data/lib/nokogiri/xml/document_fragment.rb +41 -38
  124. data/lib/nokogiri/xml/dtd.rb +3 -2
  125. data/lib/nokogiri/xml/element_content.rb +1 -0
  126. data/lib/nokogiri/xml/element_decl.rb +2 -1
  127. data/lib/nokogiri/xml/entity_decl.rb +3 -2
  128. data/lib/nokogiri/xml/entity_reference.rb +1 -0
  129. data/lib/nokogiri/xml/namespace.rb +2 -0
  130. data/lib/nokogiri/xml/node/save_options.rb +9 -5
  131. data/lib/nokogiri/xml/node.rb +525 -354
  132. data/lib/nokogiri/xml/node_set.rb +50 -54
  133. data/lib/nokogiri/xml/notation.rb +12 -0
  134. data/lib/nokogiri/xml/parse_options.rb +13 -6
  135. data/lib/nokogiri/xml/pp/character_data.rb +8 -6
  136. data/lib/nokogiri/xml/pp/node.rb +24 -26
  137. data/lib/nokogiri/xml/pp.rb +3 -2
  138. data/lib/nokogiri/xml/processing_instruction.rb +2 -1
  139. data/lib/nokogiri/xml/reader.rb +20 -24
  140. data/lib/nokogiri/xml/relax_ng.rb +1 -0
  141. data/lib/nokogiri/xml/sax/document.rb +44 -49
  142. data/lib/nokogiri/xml/sax/parser.rb +37 -34
  143. data/lib/nokogiri/xml/sax/parser_context.rb +7 -3
  144. data/lib/nokogiri/xml/sax/push_parser.rb +5 -5
  145. data/lib/nokogiri/xml/sax.rb +5 -4
  146. data/lib/nokogiri/xml/schema.rb +7 -6
  147. data/lib/nokogiri/xml/searchable.rb +93 -62
  148. data/lib/nokogiri/xml/syntax_error.rb +5 -4
  149. data/lib/nokogiri/xml/text.rb +1 -0
  150. data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
  151. data/lib/nokogiri/xml/xpath.rb +13 -1
  152. data/lib/nokogiri/xml/xpath_context.rb +2 -3
  153. data/lib/nokogiri/xml.rb +37 -37
  154. data/lib/nokogiri/xslt/stylesheet.rb +2 -1
  155. data/lib/nokogiri/xslt.rb +28 -20
  156. data/lib/nokogiri.rb +48 -43
  157. data/lib/xsd/xmlparser/nokogiri.rb +25 -24
  158. data/patches/libxml2/{0002-Remove-script-macro-support.patch → 0001-Remove-script-macro-support.patch} +0 -0
  159. data/patches/libxml2/{0003-Update-entities-to-remove-handling-of-ssi.patch → 0002-Update-entities-to-remove-handling-of-ssi.patch} +0 -0
  160. data/patches/libxml2/{0004-libxml2.la-is-in-top_builddir.patch → 0003-libxml2.la-is-in-top_builddir.patch} +1 -1
  161. data/patches/libxml2/{0008-use-glibc-strlen.patch → 0004-use-glibc-strlen.patch} +3 -3
  162. data/patches/libxml2/{0009-avoid-isnan-isinf.patch → 0005-avoid-isnan-isinf.patch} +4 -4
  163. data/patches/libxml2/0006-update-automake-files-for-arm64.patch +3040 -0
  164. data/patches/libxml2/0008-htmlParseComment-handle-abruptly-closed-comments.patch +61 -0
  165. data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
  166. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +2445 -1919
  167. data/ports/archives/libxml2-2.9.14.tar.xz +0 -0
  168. data/ports/archives/libxslt-1.1.35.tar.xz +0 -0
  169. metadata +204 -93
  170. data/lib/nokogiri/html/element_description_defaults.rb +0 -672
  171. data/lib/nokogiri/html/sax/parser_context.rb +0 -17
  172. data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +0 -78
  173. data/patches/libxml2/0005-Fix-infinite-loop-in-xmlStringLenDecodeEntities.patch +0 -32
  174. data/patches/libxml2/0006-htmlParseComment-treat-as-if-it-closed-the-comment.patch +0 -73
  175. data/patches/libxml2/0007-use-new-htmlParseLookupCommentEnd-to-find-comment-en.patch +0 -103
  176. data/patches/libxml2/0010-parser.c-shrink-the-input-buffer-when-appropriate.patch +0 -70
  177. data/patches/libxml2/0011-update-automake-files-for-arm64.patch +0 -2511
  178. data/ports/archives/libxml2-2.9.10.tar.gz +0 -0
  179. data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
@@ -1,22 +1,25 @@
1
+ # coding: utf-8
1
2
  # frozen_string_literal: true
3
+
2
4
  module Nokogiri
3
5
  module XML
4
6
  #
5
7
  # The Searchable module declares the interface used for searching your DOM.
6
8
  #
7
- # It implements the public methods `search`, `css`, and `xpath`,
9
+ # It implements the public methods #search, #css, and #xpath,
8
10
  # as well as allowing specific implementations to specialize some
9
11
  # of the important behaviors.
10
12
  #
11
13
  module Searchable
12
14
  # Regular expression used by Searchable#search to determine if a query
13
15
  # string is CSS or XPath
14
- LOOKS_LIKE_XPATH = /^(\.\/|\/|\.\.|\.$)/
16
+ LOOKS_LIKE_XPATH = %r{^(\./|/|\.\.|\.$)}
15
17
 
16
- # @!group Searching via XPath or CSS Queries
18
+ # :section: Searching via XPath or CSS Queries
17
19
 
18
20
  ###
19
- # call-seq: search *paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class]
21
+ # call-seq:
22
+ # search(*paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class])
20
23
  #
21
24
  # Search this object for +paths+. +paths+ must be one or more XPath or CSS queries:
22
25
  #
@@ -27,41 +30,39 @@ module Nokogiri
27
30
  # node.search('.//bike:tire', {'bike' => 'http://schwinn.com/'})
28
31
  # node.search('bike|tire', {'bike' => 'http://schwinn.com/'})
29
32
  #
30
- # For XPath queries, a hash of variable bindings may also be
31
- # appended to the namespace bindings. For example:
33
+ # For XPath queries, a hash of variable bindings may also be appended to the namespace
34
+ # bindings. For example:
32
35
  #
33
36
  # node.search('.//address[@domestic=$value]', nil, {:value => 'Yes'})
34
37
  #
35
- # Custom XPath functions and CSS pseudo-selectors may also be
36
- # defined. To define custom functions create a class and
37
- # implement the function you want to define. The first argument
38
- # to the method will be the current matching NodeSet. Any other
39
- # arguments are ones that you pass in. Note that this class may
40
- # appear anywhere in the argument list. For example:
41
- #
42
- # node.search('.//title[regex(., "\w+")]', 'div.employee:regex("[0-9]+")'
43
- # Class.new {
44
- # def regex node_set, regex
45
- # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
46
- # end
47
- # }.new
48
- # )
38
+ # 💡 Custom XPath functions and CSS pseudo-selectors may also be defined. To define custom
39
+ # functions create a class and implement the function you want to define. The first argument
40
+ # to the method will be the current matching NodeSet. Any other arguments are ones that you
41
+ # pass in. Note that this class may appear anywhere in the argument list. For example:
42
+ #
43
+ # handler = Class.new {
44
+ # def regex node_set, regex
45
+ # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
46
+ # end
47
+ # }.new
48
+ # node.search('.//title[regex(., "\w+")]', 'div.employee:regex("[0-9]+")', handler)
49
49
  #
50
50
  # See Searchable#xpath and Searchable#css for further usage help.
51
51
  def search(*args)
52
52
  paths, handler, ns, binds = extract_params(args)
53
53
 
54
54
  xpaths = paths.map(&:to_s).map do |path|
55
- (path =~ LOOKS_LIKE_XPATH) ? path : xpath_query_from_css_rule(path, ns)
55
+ LOOKS_LIKE_XPATH.match?(path) ? path : xpath_query_from_css_rule(path, ns)
56
56
  end.flatten.uniq
57
57
 
58
58
  xpath(*(xpaths + [ns, handler, binds].compact))
59
59
  end
60
60
 
61
- alias :/ :search
61
+ alias_method :/, :search
62
62
 
63
63
  ###
64
- # call-seq: search *paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class]
64
+ # call-seq:
65
+ # at(*paths, [namespace-bindings, xpath-variable-bindings, custom-handler-class])
65
66
  #
66
67
  # Search this object for +paths+, and return only the first
67
68
  # result. +paths+ must be one or more XPath or CSS queries.
@@ -71,10 +72,11 @@ module Nokogiri
71
72
  search(*args).first
72
73
  end
73
74
 
74
- alias :% :at
75
+ alias_method :%, :at
75
76
 
76
77
  ###
77
- # call-seq: css *rules, [namespace-bindings, custom-pseudo-class]
78
+ # call-seq:
79
+ # css(*rules, [namespace-bindings, custom-pseudo-class])
78
80
  #
79
81
  # Search this object for CSS +rules+. +rules+ must be one or more CSS
80
82
  # selectors. For example:
@@ -87,33 +89,49 @@ module Nokogiri
87
89
  #
88
90
  # node.css('bike|tire', {'bike' => 'http://schwinn.com/'})
89
91
  #
90
- # Custom CSS pseudo classes may also be defined. To define
91
- # custom pseudo classes, create a class and implement the custom
92
- # pseudo class you want defined. The first argument to the
93
- # method will be the current matching NodeSet. Any other
94
- # arguments are ones that you pass in. For example:
92
+ # 💡 Custom CSS pseudo classes may also be defined which are mapped to a custom XPath
93
+ # function. To define custom pseudo classes, create a class and implement the custom pseudo
94
+ # class you want defined. The first argument to the method will be the matching context
95
+ # NodeSet. Any other arguments are ones that you pass in. For example:
95
96
  #
96
- # node.css('title:regex("\w+")', Class.new {
97
- # def regex node_set, regex
97
+ # handler = Class.new {
98
+ # def regex(node_set, regex)
98
99
  # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
99
100
  # end
100
- # }.new)
101
+ # }.new
102
+ # node.css('title:regex("\w+")', handler)
103
+ #
104
+ # 💡 Some XPath syntax is supported in CSS queries. For example, to query for an attribute:
105
+ #
106
+ # node.css('img > @href') # returns all +href+ attributes on an +img+ element
107
+ # node.css('img / @href') # same
108
+ #
109
+ # # ⚠ this returns +class+ attributes from all +div+ elements AND THEIR CHILDREN!
110
+ # node.css('div @class')
101
111
  #
102
- # Note that the CSS query string is case-sensitive with regards
103
- # to your document type. That is, if you're looking for "H1" in
104
- # an HTML document, you'll never find anything, since HTML tags
105
- # will match only lowercase CSS queries. However, "H1" might be
106
- # found in an XML document, where tags names are case-sensitive
107
- # (e.g., "H1" is distinct from "h1").
112
+ # node.css
108
113
  #
114
+ # 💡 Array-like syntax is supported in CSS queries as an alternative to using +:nth-child()+.
115
+ #
116
+ # ⚠ NOTE that indices are 1-based like +:nth-child+ and not 0-based like Ruby Arrays. For
117
+ # example:
118
+ #
119
+ # # equivalent to 'li:nth-child(2)'
120
+ # node.css('li[2]') # retrieve the second li element in a list
121
+ #
122
+ # ⚠ NOTE that the CSS query string is case-sensitive with regards to your document type. HTML
123
+ # tags will match only lowercase CSS queries, so if you search for "H1" in an HTML document,
124
+ # you'll never find anything. However, "H1" might be found in an XML document, where tags
125
+ # names are case-sensitive (e.g., "H1" is distinct from "h1").
109
126
  def css(*args)
110
127
  rules, handler, ns, _ = extract_params(args)
111
128
 
112
- css_internal self, rules, handler, ns
129
+ css_internal(self, rules, handler, ns)
113
130
  end
114
131
 
115
132
  ##
116
- # call-seq: css *rules, [namespace-bindings, custom-pseudo-class]
133
+ # call-seq:
134
+ # at_css(*rules, [namespace-bindings, custom-pseudo-class])
117
135
  #
118
136
  # Search this object for CSS +rules+, and return only the first
119
137
  # match. +rules+ must be one or more CSS selectors.
@@ -124,7 +142,8 @@ module Nokogiri
124
142
  end
125
143
 
126
144
  ###
127
- # call-seq: xpath *paths, [namespace-bindings, variable-bindings, custom-handler-class]
145
+ # call-seq:
146
+ # xpath(*paths, [namespace-bindings, variable-bindings, custom-handler-class])
128
147
  #
129
148
  # Search this node for XPath +paths+. +paths+ must be one or more XPath
130
149
  # queries.
@@ -140,27 +159,27 @@ module Nokogiri
140
159
  #
141
160
  # node.xpath('.//address[@domestic=$value]', nil, {:value => 'Yes'})
142
161
  #
143
- # Custom XPath functions may also be defined. To define custom
144
- # functions create a class and implement the function you want
145
- # to define. The first argument to the method will be the
146
- # current matching NodeSet. Any other arguments are ones that
147
- # you pass in. Note that this class may appear anywhere in the
148
- # argument list. For example:
162
+ # 💡 Custom XPath functions may also be defined. To define custom functions create a class and
163
+ # implement the function you want to define. The first argument to the method will be the
164
+ # current matching NodeSet. Any other arguments are ones that you pass in. Note that this
165
+ # class may appear anywhere in the argument list. For example:
149
166
  #
150
- # node.xpath('.//title[regex(., "\w+")]', Class.new {
151
- # def regex node_set, regex
167
+ # handler = Class.new {
168
+ # def regex(node_set, regex)
152
169
  # node_set.find_all { |node| node['some_attribute'] =~ /#{regex}/ }
153
170
  # end
154
- # }.new)
171
+ # }.new
172
+ # node.xpath('.//title[regex(., "\w+")]', handler)
155
173
  #
156
174
  def xpath(*args)
157
175
  paths, handler, ns, binds = extract_params(args)
158
176
 
159
- xpath_internal self, paths, handler, ns, binds
177
+ xpath_internal(self, paths, handler, ns, binds)
160
178
  end
161
179
 
162
180
  ##
163
- # call-seq: xpath *paths, [namespace-bindings, variable-bindings, custom-handler-class]
181
+ # call-seq:
182
+ # at_xpath(*paths, [namespace-bindings, variable-bindings, custom-handler-class])
164
183
  #
165
184
  # Search this node for XPath +paths+, and return only the first
166
185
  # match. +paths+ must be one or more XPath queries.
@@ -170,12 +189,21 @@ module Nokogiri
170
189
  xpath(*args).first
171
190
  end
172
191
 
173
- # @!endgroup
192
+ # :call-seq:
193
+ # >(selector) → NodeSet
194
+ #
195
+ # Search this node's immediate children using CSS selector +selector+
196
+ def >(selector) # rubocop:disable Naming/BinaryOperatorParameterName
197
+ ns = (document.root&.namespaces || {})
198
+ xpath(CSS.xpath_for(selector, prefix: "./", ns: ns).first)
199
+ end
200
+
201
+ # :section:
174
202
 
175
203
  private
176
204
 
177
205
  def css_internal(node, rules, handler, ns)
178
- xpath_internal node, css_rules_to_xpath(rules, ns), handler, ns, nil
206
+ xpath_internal(node, css_rules_to_xpath(rules, ns), handler, ns, nil)
179
207
  end
180
208
 
181
209
  def xpath_internal(node, paths, handler, ns, binds)
@@ -198,9 +226,9 @@ module Nokogiri
198
226
  ctx.register_namespaces(ns)
199
227
  path = path.gsub(/xmlns:/, " :") unless Nokogiri.uses_libxml?
200
228
 
201
- binds.each do |key, value|
202
- ctx.register_variable key.to_s, value
203
- end if binds
229
+ binds&.each do |key, value|
230
+ ctx.register_variable(key.to_s, value)
231
+ end
204
232
 
205
233
  ctx.evaluate(path, handler)
206
234
  end
@@ -210,10 +238,13 @@ module Nokogiri
210
238
  end
211
239
 
212
240
  def xpath_query_from_css_rule(rule, ns)
213
- visitor = Nokogiri::CSS::XPathVisitorOptimallyUseBuiltins.new
241
+ visitor = Nokogiri::CSS::XPathVisitor.new(
242
+ builtins: Nokogiri::CSS::XPathVisitor::BuiltinsConfig::OPTIMAL,
243
+ doctype: document.xpath_doctype,
244
+ )
214
245
  self.class::IMPLIED_XPATH_CONTEXTS.map do |implied_xpath_context|
215
- CSS.xpath_for(rule.to_s, {:prefix => implied_xpath_context, :ns => ns,
216
- :visitor => visitor})
246
+ CSS.xpath_for(rule.to_s, { prefix: implied_xpath_context, ns: ns,
247
+ visitor: visitor, })
217
248
  end.join(" | ")
218
249
  end
219
250
 
@@ -230,7 +261,7 @@ module Nokogiri
230
261
  end
231
262
  ns, binds = hashes.reverse
232
263
 
233
- ns ||= document.root ? document.root.namespaces : {}
264
+ ns ||= (document.root&.namespaces || {})
234
265
 
235
266
  [params, handler, ns, binds]
236
267
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Nokogiri
3
4
  module XML
4
5
  ###
@@ -42,9 +43,9 @@ module Nokogiri
42
43
 
43
44
  def to_s
44
45
  message = super.chomp
45
- [location_to_s, level_to_s, message].
46
- compact.join(": ").
47
- force_encoding(message.encoding)
46
+ [location_to_s, level_to_s, message]
47
+ .compact.join(": ")
48
+ .force_encoding(message.encoding)
48
49
  end
49
50
 
50
51
  private
@@ -54,7 +55,6 @@ module Nokogiri
54
55
  when 3 then "FATAL"
55
56
  when 2 then "ERROR"
56
57
  when 1 then "WARNING"
57
- else nil
58
58
  end
59
59
  end
60
60
 
@@ -64,6 +64,7 @@ module Nokogiri
64
64
 
65
65
  def location_to_s
66
66
  return nil if nil_or_zero?(line) && nil_or_zero?(column)
67
+
67
68
  "#{line}:#{column}"
68
69
  end
69
70
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Nokogiri
3
4
  module XML
4
5
  class Text < Nokogiri::XML::CharacterData
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Nokogiri
3
4
  module XML
4
5
  module XPath
5
6
  class SyntaxError < XML::SyntaxError
6
7
  def to_s
7
- [super.chomp, str1].compact.join(': ')
8
+ [super.chomp, str1].compact.join(": ")
8
9
  end
9
10
  end
10
11
  end
@@ -1,9 +1,21 @@
1
1
  # frozen_string_literal: true
2
- require 'nokogiri/xml/xpath/syntax_error'
3
2
 
4
3
  module Nokogiri
5
4
  module XML
6
5
  module XPath
6
+ # The XPath search prefix to search globally, +//+
7
+ GLOBAL_SEARCH_PREFIX = "//"
8
+
9
+ # The XPath search prefix to search direct descendants of the root element, +/+
10
+ ROOT_SEARCH_PREFIX = "/"
11
+
12
+ # The XPath search prefix to search direct descendants of the current element, +./+
13
+ CURRENT_SEARCH_PREFIX = "./"
14
+
15
+ # The XPath search prefix to search anywhere in the current element's subtree, +.//+
16
+ SUBTREE_SEARCH_PREFIX = ".//"
7
17
  end
8
18
  end
9
19
  end
20
+
21
+ require_relative "xpath/syntax_error"
@@ -1,17 +1,16 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Nokogiri
3
4
  module XML
4
5
  class XPathContext
5
-
6
6
  ###
7
7
  # Register namespaces in +namespaces+
8
8
  def register_namespaces(namespaces)
9
9
  namespaces.each do |k, v|
10
- k = k.to_s.gsub(/.*:/,'') # strip off 'xmlns:' or 'xml:'
10
+ k = k.to_s.gsub(/.*:/, "") # strip off 'xmlns:' or 'xml:'
11
11
  register_ns(k, v)
12
12
  end
13
13
  end
14
-
15
14
  end
16
15
  end
17
16
  end
data/lib/nokogiri/xml.rb CHANGED
@@ -1,38 +1,10 @@
1
1
  # frozen_string_literal: true
2
- require 'nokogiri/xml/pp'
3
- require 'nokogiri/xml/parse_options'
4
- require 'nokogiri/xml/sax'
5
- require 'nokogiri/xml/searchable'
6
- require 'nokogiri/xml/node'
7
- require 'nokogiri/xml/attribute_decl'
8
- require 'nokogiri/xml/element_decl'
9
- require 'nokogiri/xml/element_content'
10
- require 'nokogiri/xml/character_data'
11
- require 'nokogiri/xml/namespace'
12
- require 'nokogiri/xml/attr'
13
- require 'nokogiri/xml/dtd'
14
- require 'nokogiri/xml/cdata'
15
- require 'nokogiri/xml/text'
16
- require 'nokogiri/xml/document'
17
- require 'nokogiri/xml/document_fragment'
18
- require 'nokogiri/xml/processing_instruction'
19
- require 'nokogiri/xml/node_set'
20
- require 'nokogiri/xml/syntax_error'
21
- require 'nokogiri/xml/xpath'
22
- require 'nokogiri/xml/xpath_context'
23
- require 'nokogiri/xml/builder'
24
- require 'nokogiri/xml/reader'
25
- require 'nokogiri/xml/notation'
26
- require 'nokogiri/xml/entity_decl'
27
- require 'nokogiri/xml/entity_reference'
28
- require 'nokogiri/xml/schema'
29
- require 'nokogiri/xml/relax_ng'
30
2
 
31
3
  module Nokogiri
32
4
  class << self
33
5
  ###
34
6
  # Parse XML. Convenience method for Nokogiri::XML::Document.parse
35
- def XML thing, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_XML, &block
7
+ def XML(thing, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_XML, &block)
36
8
  Nokogiri::XML::Document.parse(thing, url, encoding, options, &block)
37
9
  end
38
10
  end
@@ -41,36 +13,64 @@ module Nokogiri
41
13
  # Original C14N 1.0 spec canonicalization
42
14
  XML_C14N_1_0 = 0
43
15
  # Exclusive C14N 1.0 spec canonicalization
44
- XML_C14N_EXCLUSIVE_1_0 = 1
16
+ XML_C14N_EXCLUSIVE_1_0 = 1
45
17
  # C14N 1.1 spec canonicalization
46
18
  XML_C14N_1_1 = 2
47
19
  class << self
48
20
  ###
49
21
  # Parse an XML document using the Nokogiri::XML::Reader API. See
50
22
  # Nokogiri::XML::Reader for mor information
51
- def Reader string_or_io, url = nil, encoding = nil, options = ParseOptions::STRICT
52
-
23
+ def Reader(string_or_io, url = nil, encoding = nil, options = ParseOptions::STRICT)
53
24
  options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
54
- # Give the options to the user
55
25
  yield options if block_given?
56
26
 
57
- if string_or_io.respond_to? :read
27
+ if string_or_io.respond_to?(:read)
58
28
  return Reader.from_io(string_or_io, url, encoding, options.to_i)
59
29
  end
30
+
60
31
  Reader.from_memory(string_or_io, url, encoding, options.to_i)
61
32
  end
62
33
 
63
34
  ###
64
35
  # Parse XML. Convenience method for Nokogiri::XML::Document.parse
65
- def parse thing, url = nil, encoding = nil, options = ParseOptions::DEFAULT_XML, &block
36
+ def parse(thing, url = nil, encoding = nil, options = ParseOptions::DEFAULT_XML, &block)
66
37
  Document.parse(thing, url, encoding, options, &block)
67
38
  end
68
39
 
69
40
  ####
70
41
  # Parse a fragment from +string+ in to a NodeSet.
71
- def fragment string
72
- XML::DocumentFragment.parse(string)
42
+ def fragment(string, options = ParseOptions::DEFAULT_XML, &block)
43
+ XML::DocumentFragment.parse(string, options, &block)
73
44
  end
74
45
  end
75
46
  end
76
47
  end
48
+
49
+ require_relative "xml/pp"
50
+ require_relative "xml/parse_options"
51
+ require_relative "xml/sax"
52
+ require_relative "xml/searchable"
53
+ require_relative "xml/node"
54
+ require_relative "xml/attribute_decl"
55
+ require_relative "xml/element_decl"
56
+ require_relative "xml/element_content"
57
+ require_relative "xml/character_data"
58
+ require_relative "xml/namespace"
59
+ require_relative "xml/attr"
60
+ require_relative "xml/dtd"
61
+ require_relative "xml/cdata"
62
+ require_relative "xml/text"
63
+ require_relative "xml/document"
64
+ require_relative "xml/document_fragment"
65
+ require_relative "xml/processing_instruction"
66
+ require_relative "xml/node_set"
67
+ require_relative "xml/syntax_error"
68
+ require_relative "xml/xpath"
69
+ require_relative "xml/xpath_context"
70
+ require_relative "xml/builder"
71
+ require_relative "xml/reader"
72
+ require_relative "xml/notation"
73
+ require_relative "xml/entity_decl"
74
+ require_relative "xml/entity_reference"
75
+ require_relative "xml/schema"
76
+ require_relative "xml/relax_ng"
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Nokogiri
3
4
  module XSLT
4
5
  ###
@@ -18,7 +19,7 @@ module Nokogiri
18
19
  # Apply an XSLT stylesheet to an XML::Document.
19
20
  # +params+ is an array of strings used as XSLT parameters.
20
21
  # returns serialized document
21
- def apply_to document, params = []
22
+ def apply_to(document, params = [])
22
23
  serialize(transform(document, params))
23
24
  end
24
25
  end
data/lib/nokogiri/xslt.rb CHANGED
@@ -1,5 +1,5 @@
1
+ # coding: utf-8
1
2
  # frozen_string_literal: true
2
- require 'nokogiri/xslt/stylesheet'
3
3
 
4
4
  module Nokogiri
5
5
  class << self
@@ -10,7 +10,7 @@ module Nokogiri
10
10
  #
11
11
  # xslt = Nokogiri::XSLT(File.read(ARGV[0]))
12
12
  #
13
- def XSLT stylesheet, modules = {}
13
+ def XSLT(stylesheet, modules = {})
14
14
  XSLT.parse(stylesheet, modules)
15
15
  end
16
16
  end
@@ -22,36 +22,44 @@ module Nokogiri
22
22
  class << self
23
23
  ###
24
24
  # Parse the stylesheet in +string+, register any +modules+
25
- def parse string, modules = {}
25
+ def parse(string, modules = {})
26
26
  modules.each do |url, klass|
27
- XSLT.register url, klass
27
+ XSLT.register(url, klass)
28
28
  end
29
29
 
30
+ doc = XML::Document.parse(string, nil, nil, XML::ParseOptions::DEFAULT_XSLT)
30
31
  if Nokogiri.jruby?
31
- Stylesheet.parse_stylesheet_doc(XML.parse(string), string)
32
+ Stylesheet.parse_stylesheet_doc(doc, string)
32
33
  else
33
- Stylesheet.parse_stylesheet_doc(XML.parse(string))
34
+ Stylesheet.parse_stylesheet_doc(doc)
34
35
  end
35
36
  end
36
37
 
37
- ###
38
- # Quote parameters in +params+ for stylesheet safety
39
- def quote_params params
40
- parray = (params.instance_of?(Hash) ? params.to_a.flatten : params).dup
41
- parray.each_with_index do |v,i|
42
- if i % 2 > 0
43
- parray[i]=
44
- if v =~ /'/
45
- "concat('#{ v.gsub(/'/, %q{', "'", '}) }')"
46
- else
47
- "'#{v}'";
48
- end
38
+ # :call-seq:
39
+ # quote_params(params) Array
40
+ #
41
+ # Quote parameters in +params+ for stylesheet safety.
42
+ # See Nokogiri::XSLT::Stylesheet.transform for example usage.
43
+ #
44
+ # [Parameters]
45
+ # - +params+ (Hash, Array) XSLT parameters (key->value, or tuples of [key, value])
46
+ #
47
+ # [Returns] Array of string parameters, with quotes correctly escaped for use with XSLT::Stylesheet.transform
48
+ #
49
+ def quote_params(params)
50
+ params.flatten.each_slice(2).each_with_object([]) do |kv, quoted_params|
51
+ key, value = kv.map(&:to_s)
52
+ value = if /'/.match?(value)
53
+ "concat('#{value.gsub(/'/, %q{', "'", '})}')"
49
54
  else
50
- parray[i] = v.to_s
55
+ "'#{value}'"
51
56
  end
57
+ quoted_params << key
58
+ quoted_params << value
52
59
  end
53
- parray.flatten
54
60
  end
55
61
  end
56
62
  end
57
63
  end
64
+
65
+ require_relative "xslt/stylesheet"