nokogiri 1.11.4 → 1.13.2

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 (164) 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 +11 -62
  8. data/ext/nokogiri/depend +35 -34
  9. data/ext/nokogiri/extconf.rb +235 -126
  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} +6 -5
  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 +19 -9
  19. data/ext/nokogiri/xml_document.c +49 -49
  20. data/ext/nokogiri/xml_document_fragment.c +0 -2
  21. data/ext/nokogiri/xml_dtd.c +2 -2
  22. data/ext/nokogiri/xml_element_content.c +2 -0
  23. data/ext/nokogiri/xml_encoding_handler.c +31 -12
  24. data/ext/nokogiri/xml_namespace.c +4 -2
  25. data/ext/nokogiri/xml_node.c +759 -439
  26. data/ext/nokogiri/xml_node_set.c +20 -20
  27. data/ext/nokogiri/xml_reader.c +39 -11
  28. data/ext/nokogiri/xml_sax_parser.c +6 -6
  29. data/ext/nokogiri/xml_sax_parser_context.c +2 -0
  30. data/ext/nokogiri/xml_schema.c +2 -0
  31. data/ext/nokogiri/xml_xpath_context.c +109 -84
  32. data/ext/nokogiri/xslt_stylesheet.c +109 -10
  33. data/gumbo-parser/CHANGES.md +63 -0
  34. data/gumbo-parser/Makefile +101 -0
  35. data/gumbo-parser/THANKS +27 -0
  36. data/gumbo-parser/src/Makefile +34 -0
  37. data/gumbo-parser/src/README.md +41 -0
  38. data/gumbo-parser/src/ascii.c +75 -0
  39. data/gumbo-parser/src/ascii.h +115 -0
  40. data/gumbo-parser/src/attribute.c +42 -0
  41. data/gumbo-parser/src/attribute.h +17 -0
  42. data/gumbo-parser/src/char_ref.c +22225 -0
  43. data/gumbo-parser/src/char_ref.h +29 -0
  44. data/gumbo-parser/src/char_ref.rl +2154 -0
  45. data/gumbo-parser/src/error.c +626 -0
  46. data/gumbo-parser/src/error.h +148 -0
  47. data/gumbo-parser/src/foreign_attrs.c +104 -0
  48. data/gumbo-parser/src/foreign_attrs.gperf +27 -0
  49. data/gumbo-parser/src/gumbo.h +943 -0
  50. data/gumbo-parser/src/insertion_mode.h +33 -0
  51. data/gumbo-parser/src/macros.h +91 -0
  52. data/gumbo-parser/src/parser.c +4875 -0
  53. data/gumbo-parser/src/parser.h +41 -0
  54. data/gumbo-parser/src/replacement.h +33 -0
  55. data/gumbo-parser/src/string_buffer.c +103 -0
  56. data/gumbo-parser/src/string_buffer.h +68 -0
  57. data/gumbo-parser/src/string_piece.c +48 -0
  58. data/gumbo-parser/src/svg_attrs.c +174 -0
  59. data/gumbo-parser/src/svg_attrs.gperf +77 -0
  60. data/gumbo-parser/src/svg_tags.c +137 -0
  61. data/gumbo-parser/src/svg_tags.gperf +55 -0
  62. data/gumbo-parser/src/tag.c +222 -0
  63. data/gumbo-parser/src/tag_lookup.c +382 -0
  64. data/gumbo-parser/src/tag_lookup.gperf +169 -0
  65. data/gumbo-parser/src/tag_lookup.h +13 -0
  66. data/gumbo-parser/src/token_buffer.c +79 -0
  67. data/gumbo-parser/src/token_buffer.h +71 -0
  68. data/gumbo-parser/src/token_type.h +17 -0
  69. data/gumbo-parser/src/tokenizer.c +3463 -0
  70. data/gumbo-parser/src/tokenizer.h +112 -0
  71. data/gumbo-parser/src/tokenizer_states.h +339 -0
  72. data/gumbo-parser/src/utf8.c +245 -0
  73. data/gumbo-parser/src/utf8.h +164 -0
  74. data/gumbo-parser/src/util.c +68 -0
  75. data/gumbo-parser/src/util.h +30 -0
  76. data/gumbo-parser/src/vector.c +111 -0
  77. data/gumbo-parser/src/vector.h +45 -0
  78. data/lib/nokogiri/class_resolver.rb +67 -0
  79. data/lib/nokogiri/css/node.rb +9 -8
  80. data/lib/nokogiri/css/parser.rb +361 -342
  81. data/lib/nokogiri/css/parser.y +250 -245
  82. data/lib/nokogiri/css/parser_extras.rb +20 -20
  83. data/lib/nokogiri/css/syntax_error.rb +2 -1
  84. data/lib/nokogiri/css/tokenizer.rb +4 -3
  85. data/lib/nokogiri/css/tokenizer.rex +3 -2
  86. data/lib/nokogiri/css/xpath_visitor.rb +179 -82
  87. data/lib/nokogiri/css.rb +49 -17
  88. data/lib/nokogiri/decorators/slop.rb +8 -7
  89. data/lib/nokogiri/extension.rb +8 -3
  90. data/lib/nokogiri/gumbo.rb +15 -0
  91. data/lib/nokogiri/html.rb +37 -27
  92. data/lib/nokogiri/{html → html4}/builder.rb +3 -2
  93. data/lib/nokogiri/{html → html4}/document.rb +88 -79
  94. data/lib/nokogiri/{html → html4}/document_fragment.rb +13 -9
  95. data/lib/nokogiri/{html → html4}/element_description.rb +2 -1
  96. data/lib/nokogiri/html4/element_description_defaults.rb +578 -0
  97. data/lib/nokogiri/{html → html4}/entity_lookup.rb +3 -2
  98. data/lib/nokogiri/{html → html4}/sax/parser.rb +13 -15
  99. data/lib/nokogiri/html4/sax/parser_context.rb +20 -0
  100. data/lib/nokogiri/{html → html4}/sax/push_parser.rb +11 -11
  101. data/lib/nokogiri/html4.rb +46 -0
  102. data/lib/nokogiri/html5/document.rb +88 -0
  103. data/lib/nokogiri/html5/document_fragment.rb +83 -0
  104. data/lib/nokogiri/html5/node.rb +96 -0
  105. data/lib/nokogiri/html5.rb +477 -0
  106. data/lib/nokogiri/jruby/dependencies.rb +10 -9
  107. data/lib/nokogiri/syntax_error.rb +1 -0
  108. data/lib/nokogiri/version/constant.rb +2 -1
  109. data/lib/nokogiri/version/info.rb +30 -14
  110. data/lib/nokogiri/version.rb +1 -0
  111. data/lib/nokogiri/xml/attr.rb +5 -3
  112. data/lib/nokogiri/xml/attribute_decl.rb +2 -1
  113. data/lib/nokogiri/xml/builder.rb +69 -31
  114. data/lib/nokogiri/xml/cdata.rb +2 -1
  115. data/lib/nokogiri/xml/character_data.rb +1 -0
  116. data/lib/nokogiri/xml/document.rb +178 -96
  117. data/lib/nokogiri/xml/document_fragment.rb +41 -38
  118. data/lib/nokogiri/xml/dtd.rb +3 -2
  119. data/lib/nokogiri/xml/element_content.rb +1 -0
  120. data/lib/nokogiri/xml/element_decl.rb +2 -1
  121. data/lib/nokogiri/xml/entity_decl.rb +3 -2
  122. data/lib/nokogiri/xml/entity_reference.rb +1 -0
  123. data/lib/nokogiri/xml/namespace.rb +2 -0
  124. data/lib/nokogiri/xml/node/save_options.rb +7 -4
  125. data/lib/nokogiri/xml/node.rb +516 -351
  126. data/lib/nokogiri/xml/node_set.rb +46 -54
  127. data/lib/nokogiri/xml/notation.rb +12 -0
  128. data/lib/nokogiri/xml/parse_options.rb +12 -6
  129. data/lib/nokogiri/xml/pp/character_data.rb +8 -6
  130. data/lib/nokogiri/xml/pp/node.rb +24 -26
  131. data/lib/nokogiri/xml/pp.rb +3 -2
  132. data/lib/nokogiri/xml/processing_instruction.rb +2 -1
  133. data/lib/nokogiri/xml/reader.rb +17 -19
  134. data/lib/nokogiri/xml/relax_ng.rb +1 -0
  135. data/lib/nokogiri/xml/sax/document.rb +44 -49
  136. data/lib/nokogiri/xml/sax/parser.rb +36 -34
  137. data/lib/nokogiri/xml/sax/parser_context.rb +7 -3
  138. data/lib/nokogiri/xml/sax/push_parser.rb +5 -5
  139. data/lib/nokogiri/xml/sax.rb +5 -4
  140. data/lib/nokogiri/xml/schema.rb +7 -6
  141. data/lib/nokogiri/xml/searchable.rb +93 -62
  142. data/lib/nokogiri/xml/syntax_error.rb +4 -4
  143. data/lib/nokogiri/xml/text.rb +1 -0
  144. data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
  145. data/lib/nokogiri/xml/xpath.rb +13 -1
  146. data/lib/nokogiri/xml/xpath_context.rb +2 -3
  147. data/lib/nokogiri/xml.rb +36 -37
  148. data/lib/nokogiri/xslt/stylesheet.rb +2 -1
  149. data/lib/nokogiri/xslt.rb +28 -20
  150. data/lib/nokogiri.rb +48 -43
  151. data/lib/xsd/xmlparser/nokogiri.rb +25 -24
  152. data/patches/libxml2/0004-use-glibc-strlen.patch +3 -3
  153. data/patches/libxml2/0006-update-automake-files-for-arm64.patch +2443 -1914
  154. data/patches/libxml2/0008-htmlParseComment-handle-abruptly-closed-comments.patch +61 -0
  155. data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
  156. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +2445 -1919
  157. data/ports/archives/libxml2-2.9.13.tar.xz +0 -0
  158. data/ports/archives/libxslt-1.1.35.tar.xz +0 -0
  159. metadata +198 -83
  160. data/lib/nokogiri/html/element_description_defaults.rb +0 -672
  161. data/lib/nokogiri/html/sax/parser_context.rb +0 -17
  162. data/patches/libxslt/0002-Fix-xml2-config-check-in-configure-script.patch +0 -19
  163. data/ports/archives/libxml2-2.9.12.tar.gz +0 -0
  164. data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Nokogiri
3
4
  module XML
4
5
  ###
@@ -196,6 +197,41 @@ module Nokogiri
196
197
  #
197
198
  # Note the "foo:object" tag.
198
199
  #
200
+ # === Namespace inheritance
201
+ #
202
+ # In the Builder context, children will inherit their parent's namespace. This is the same
203
+ # behavior as if the underlying {XML::Document} set +namespace_inheritance+ to +true+:
204
+ #
205
+ # result = Nokogiri::XML::Builder.new do |xml|
206
+ # xml["soapenv"].Envelope("xmlns:soapenv" => "http://schemas.xmlsoap.org/soap/envelope/") do
207
+ # xml.Header
208
+ # end
209
+ # end
210
+ # result.doc.to_xml
211
+ # # => <?xml version="1.0" encoding="utf-8"?>
212
+ # # <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
213
+ # # <soapenv:Header/>
214
+ # # </soapenv:Envelope>
215
+ #
216
+ # Users may turn this behavior off by passing a keyword argument +namespace_inheritance:false+
217
+ # to the initializer:
218
+ #
219
+ # result = Nokogiri::XML::Builder.new(namespace_inheritance: false) do |xml|
220
+ # xml["soapenv"].Envelope("xmlns:soapenv" => "http://schemas.xmlsoap.org/soap/envelope/") do
221
+ # xml.Header
222
+ # xml["soapenv"].Body # users may explicitly opt into the namespace
223
+ # end
224
+ # end
225
+ # result.doc.to_xml
226
+ # # => <?xml version="1.0" encoding="utf-8"?>
227
+ # # <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
228
+ # # <Header/>
229
+ # # <soapenv:Body/>
230
+ # # </soapenv:Envelope>
231
+ #
232
+ # For more information on namespace inheritance, please see {XML::Document#namespace_inheritance}
233
+ #
234
+ #
199
235
  # == Document Types
200
236
  #
201
237
  # To create a document type (DTD), access use the Builder#doc method to get
@@ -226,6 +262,10 @@ module Nokogiri
226
262
  # </root>
227
263
  #
228
264
  class Builder
265
+ include Nokogiri::ClassResolver
266
+
267
+ DEFAULT_DOCUMENT_OPTIONS = { namespace_inheritance: true }
268
+
229
269
  # The current Document object being built
230
270
  attr_accessor :doc
231
271
 
@@ -269,24 +309,19 @@ module Nokogiri
269
309
  @doc = root.document
270
310
  @parent = root
271
311
  else
272
- klassname = "::" + (self.class.name.split("::")[0..-2] + ["Document"]).join("::")
273
- klass = begin
274
- Object.const_get(klassname)
275
- rescue NameError
276
- Nokogiri::XML::Document
277
- end
278
- @parent = @doc = klass.new
312
+ @parent = @doc = related_class("Document").new
279
313
  end
280
314
 
281
315
  @context = nil
282
316
  @arity = nil
283
317
  @ns = nil
284
318
 
319
+ options = DEFAULT_DOCUMENT_OPTIONS.merge(options)
285
320
  options.each do |k, v|
286
321
  @doc.send(:"#{k}=", v)
287
322
  end
288
323
 
289
- return unless block_given?
324
+ return unless block
290
325
 
291
326
  @arity = block.arity
292
327
  if @arity <= 0
@@ -302,19 +337,19 @@ module Nokogiri
302
337
  ###
303
338
  # Create a Text Node with content of +string+
304
339
  def text(string)
305
- insert @doc.create_text_node(string)
340
+ insert(@doc.create_text_node(string))
306
341
  end
307
342
 
308
343
  ###
309
344
  # Create a CDATA Node with content of +string+
310
345
  def cdata(string)
311
- insert doc.create_cdata(string)
346
+ insert(doc.create_cdata(string))
312
347
  end
313
348
 
314
349
  ###
315
350
  # Create a Comment Node with content of +string+
316
351
  def comment(string)
317
- insert doc.create_comment(string)
352
+ insert(doc.create_comment(string))
318
353
  end
319
354
 
320
355
  ###
@@ -332,8 +367,8 @@ module Nokogiri
332
367
  return self if @ns
333
368
  end
334
369
 
335
- @ns = { :pending => ns.to_s }
336
- return self
370
+ @ns = { pending: ns.to_s }
371
+ self
337
372
  end
338
373
 
339
374
  ###
@@ -341,7 +376,7 @@ module Nokogiri
341
376
  def to_xml(*args)
342
377
  if Nokogiri.jruby?
343
378
  options = args.first.is_a?(Hash) ? args.shift : {}
344
- if !options[:save_with]
379
+ unless options[:save_with]
345
380
  options[:save_with] = Node::SaveOptions::AS_BUILDER
346
381
  end
347
382
  args.insert(0, options)
@@ -356,18 +391,18 @@ module Nokogiri
356
391
  end
357
392
 
358
393
  def method_missing(method, *args, &block) # :nodoc:
359
- if @context && @context.respond_to?(method)
394
+ if @context&.respond_to?(method)
360
395
  @context.send(method, *args, &block)
361
396
  else
362
- node = @doc.create_element(method.to_s.sub(/[_!]$/, ""), *args) { |n|
397
+ node = @doc.create_element(method.to_s.sub(/[_!]$/, ""), *args) do |n|
363
398
  # Set up the namespace
364
- if @ns.is_a? Nokogiri::XML::Namespace
399
+ if @ns.is_a?(Nokogiri::XML::Namespace)
365
400
  n.namespace = @ns
366
401
  @ns = nil
367
402
  end
368
- }
403
+ end
369
404
 
370
- if @ns.is_a? Hash
405
+ if @ns.is_a?(Hash)
371
406
  node.namespace = node.namespace_definitions.find { |x| x.prefix == @ns[:pending] }
372
407
  if node.namespace.nil?
373
408
  raise ArgumentError, "Namespace #{@ns[:pending]} has not been defined"
@@ -385,16 +420,19 @@ module Nokogiri
385
420
  # Insert +node+ as a child of the current Node
386
421
  def insert(node, &block)
387
422
  node = @parent.add_child(node)
388
- if block_given?
389
- old_parent = @parent
390
- @parent = node
391
- @arity ||= block.arity
392
- if @arity <= 0
393
- instance_eval(&block)
394
- else
395
- block.call(self)
423
+ if block
424
+ begin
425
+ old_parent = @parent
426
+ @parent = node
427
+ @arity ||= block.arity
428
+ if @arity <= 0
429
+ instance_eval(&block)
430
+ else
431
+ yield(self)
432
+ end
433
+ ensure
434
+ @parent = old_parent
396
435
  end
397
- @parent = old_parent
398
436
  end
399
437
  NodeBuilder.new(node, self)
400
438
  end
@@ -417,10 +455,10 @@ module Nokogiri
417
455
  opts = args.last.is_a?(Hash) ? args.pop : {}
418
456
  case method.to_s
419
457
  when /^(.*)!$/
420
- @node["id"] = $1
458
+ @node["id"] = Regexp.last_match(1)
421
459
  @node.content = args.first if args.first
422
460
  when /^(.*)=/
423
- @node[$1] = args.first
461
+ @node[Regexp.last_match(1)] = args.first
424
462
  else
425
463
  @node["class"] =
426
464
  ((@node["class"] || "").split(/\s/) + [method.to_s]).join(" ")
@@ -432,7 +470,7 @@ module Nokogiri
432
470
  @node[k.to_s] = ((@node[k.to_s] || "").split(/\s/) + [v]).join(" ")
433
471
  end
434
472
 
435
- if block_given?
473
+ if block
436
474
  old_parent = @doc_builder.parent
437
475
  @doc_builder.parent = @node
438
476
  value = @doc_builder.instance_eval(&block)
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Nokogiri
3
4
  module XML
4
5
  class CDATA < Nokogiri::XML::Text
5
6
  ###
6
7
  # Get the name of this CDATA node
7
8
  def name
8
- '#cdata-section'
9
+ "#cdata-section"
9
10
  end
10
11
  end
11
12
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Nokogiri
3
4
  module XML
4
5
  class CharacterData < Nokogiri::XML::Node
@@ -1,18 +1,16 @@
1
1
  # coding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pathname'
4
+ require "pathname"
5
5
 
6
6
  module Nokogiri
7
7
  module XML
8
- ##
9
- # Nokogiri::XML::Document is the main entry point for dealing with
10
- # XML documents. The Document is created by parsing an XML document.
11
- # See Nokogiri::XML::Document.parse() for more information on parsing.
8
+ # Nokogiri::XML::Document is the main entry point for dealing with XML documents. The Document
9
+ # is created by parsing an XML document. See Nokogiri::XML::Document.parse for more information
10
+ # on parsing.
12
11
  #
13
12
  # For searching a Document, see Nokogiri::XML::Searchable#css and
14
13
  # Nokogiri::XML::Searchable#xpath
15
- #
16
14
  class Document < Nokogiri::XML::Node
17
15
  # See http://www.w3.org/TR/REC-xml-names/#ns-decl for more details. Note that we're not
18
16
  # attempting to handle unicode characters partly because libxml2 doesn't handle unicode
@@ -47,109 +45,178 @@ module Nokogiri
47
45
  #
48
46
  # Nokogiri.XML() is a convenience method which will call this method.
49
47
  #
50
- def self.parse string_or_io, url = nil, encoding = nil, options = ParseOptions::DEFAULT_XML
48
+ def self.parse(string_or_io, url = nil, encoding = nil, options = ParseOptions::DEFAULT_XML)
51
49
  options = Nokogiri::XML::ParseOptions.new(options) if Integer === options
52
-
53
50
  yield options if block_given?
54
51
 
55
52
  url ||= string_or_io.respond_to?(:path) ? string_or_io.path : nil
56
53
 
57
54
  if empty_doc?(string_or_io)
58
55
  if options.strict?
59
- raise Nokogiri::XML::SyntaxError.new("Empty document")
56
+ raise Nokogiri::XML::SyntaxError, "Empty document"
60
57
  else
61
58
  return encoding ? new.tap { |i| i.encoding = encoding } : new
62
59
  end
63
60
  end
64
61
 
65
62
  doc = if string_or_io.respond_to?(:read)
66
- if string_or_io.is_a?(Pathname)
67
- # resolve the Pathname to the file and open it as an IO object, see #2110
68
- string_or_io = string_or_io.expand_path.open
69
- url ||= string_or_io.path
70
- end
63
+ if string_or_io.is_a?(Pathname)
64
+ # resolve the Pathname to the file and open it as an IO object, see #2110
65
+ string_or_io = string_or_io.expand_path.open
66
+ url ||= string_or_io.path
67
+ end
71
68
 
72
- read_io(string_or_io, url, encoding, options.to_i)
73
- else
74
- # read_memory pukes on empty docs
75
- read_memory(string_or_io, url, encoding, options.to_i)
76
- end
69
+ read_io(string_or_io, url, encoding, options.to_i)
70
+ else
71
+ # read_memory pukes on empty docs
72
+ read_memory(string_or_io, url, encoding, options.to_i)
73
+ end
77
74
 
78
75
  # do xinclude processing
79
76
  doc.do_xinclude(options) if options.xinclude?
80
77
 
81
- return doc
78
+ doc
82
79
  end
83
80
 
84
81
  ##
85
- # @!method wrap(java_document)
86
- # @!scope class
82
+ # :singleton-method: wrap
83
+ # :call-seq: wrap(java_document) → Nokogiri::XML::Document
84
+ #
85
+ # ⚠ This method is only available when running JRuby.
87
86
  #
88
- # Create a {Document} using an existing Java DOM document object.
87
+ # Create a Document using an existing Java DOM document object.
89
88
  #
90
- # The returned {Document} shares the same underlying data structure as the Java object, so
89
+ # The returned Document shares the same underlying data structure as the Java object, so
91
90
  # changes in one are reflected in the other.
92
91
  #
93
- # @param java_document [Java::OrgW3cDom::Document]
94
- # @return [Nokogiri::XML::Document]
95
- # @note This method is only available when running JRuby.
96
- # @note The class +Java::OrgW3cDom::Document+ is also accessible as +org.w3c.dom.Document+.
97
- # @see #to_java
92
+ # [Parameters]
93
+ # - `java_document` (Java::OrgW3cDom::Document)
94
+ # (The class `Java::OrgW3cDom::Document` is also accessible as `org.w3c.dom.Document`.)
95
+ #
96
+ # [Returns] Nokogiri::XML::Document
97
+ #
98
+ # See also \#to_java
98
99
 
99
- ##
100
- # @!method to_java()
100
+ # :method: to_java
101
+ # :call-seq: to_java() → Java::OrgW3cDom::Document
102
+ #
103
+ # ⚠ This method is only available when running JRuby.
101
104
  #
102
- # Returns the underlying Java DOM document object for the {Document}.
105
+ # Returns the underlying Java DOM document object for this document.
103
106
  #
104
- # The returned Java object shares the same underlying data structure as the {Document}, so
107
+ # The returned Java object shares the same underlying data structure as this document, so
105
108
  # changes in one are reflected in the other.
106
109
  #
107
- # @return [Java::OrgW3cDom::Document]
108
- # @note This method is only available when running JRuby.
109
- # @note The class +Java::OrgW3cDom::Document+ is also accessible as +org.w3c.dom.Document+.
110
- # @see .wrap
111
-
110
+ # [Returns]
111
+ # Java::OrgW3cDom::Document
112
+ # (The class `Java::OrgW3cDom::Document` is also accessible as `org.w3c.dom.Document`.)
113
+ #
114
+ # See also Document.wrap
112
115
 
113
- # A list of Nokogiri::XML::SyntaxError found when parsing a document
116
+ # The errors found while parsing a document.
117
+ #
118
+ # [Returns] Array<Nokogiri::XML::SyntaxError>
114
119
  attr_accessor :errors
115
120
 
116
- def initialize *args # :nodoc:
121
+ # When `true`, reparented elements without a namespace will inherit their new parent's
122
+ # namespace (if one exists). Defaults to `false`.
123
+ #
124
+ # [Returns] Boolean
125
+ #
126
+ # *Example:* Default behavior of namespace inheritance
127
+ #
128
+ # xml = <<~EOF
129
+ # <root xmlns:foo="http://nokogiri.org/default_ns/test/foo">
130
+ # <foo:parent>
131
+ # </foo:parent>
132
+ # </root>
133
+ # EOF
134
+ # doc = Nokogiri::XML(xml)
135
+ # parent = doc.at_xpath("//foo:parent", "foo" => "http://nokogiri.org/default_ns/test/foo")
136
+ # parent.add_child("<child></child>")
137
+ # doc.to_xml
138
+ # # => <?xml version="1.0"?>
139
+ # # <root xmlns:foo="http://nokogiri.org/default_ns/test/foo">
140
+ # # <foo:parent>
141
+ # # <child/>
142
+ # # </foo:parent>
143
+ # # </root>
144
+ #
145
+ # *Example:* Setting namespace inheritance to `true`
146
+ #
147
+ # xml = <<~EOF
148
+ # <root xmlns:foo="http://nokogiri.org/default_ns/test/foo">
149
+ # <foo:parent>
150
+ # </foo:parent>
151
+ # </root>
152
+ # EOF
153
+ # doc = Nokogiri::XML(xml)
154
+ # doc.namespace_inheritance = true
155
+ # parent = doc.at_xpath("//foo:parent", "foo" => "http://nokogiri.org/default_ns/test/foo")
156
+ # parent.add_child("<child></child>")
157
+ # doc.to_xml
158
+ # # => <?xml version="1.0"?>
159
+ # # <root xmlns:foo="http://nokogiri.org/default_ns/test/foo">
160
+ # # <foo:parent>
161
+ # # <foo:child/>
162
+ # # </foo:parent>
163
+ # # </root>
164
+ #
165
+ # Since v1.12.4
166
+ attr_accessor :namespace_inheritance
167
+
168
+ def initialize(*args) # :nodoc:
117
169
  @errors = []
118
170
  @decorators = nil
171
+ @namespace_inheritance = false
119
172
  end
120
173
 
121
- ##
122
- # Create a new +Element+ with +name+ sharing GC lifecycle with the document, optionally
123
- # setting contents or attributes.
174
+ # :call-seq:
175
+ # create_element(name, *contents_or_attrs, &block) Nokogiri::XML::Element
176
+ #
177
+ # Create a new Element with `name` belonging to this document, optionally setting contents or
178
+ # attributes.
179
+ #
180
+ # This method is _not_ the most user-friendly option if your intention is to add a node to the
181
+ # document tree. Prefer one of the Nokogiri::XML::Node methods like Node#add_child,
182
+ # Node#add_next_sibling, Node#replace, etc. which will both create an element (or subtree) and
183
+ # place it in the document tree.
124
184
  #
125
185
  # Arguments may be passed to initialize the element:
126
- # - a +Hash+ argument will be used to set attributes
127
- # - a non-Hash object that responds to +#to_s+ will be used to set the new node's contents
186
+ #
187
+ # - a Hash argument will be used to set attributes
188
+ # - a non-Hash object that responds to \#to_s will be used to set the new node's contents
128
189
  #
129
190
  # A block may be passed to mutate the node.
130
191
  #
131
- # @param name [String]
132
- # @param contents_or_attrs [#to_s,Hash]
133
- # @yieldparam node [Nokogiri::XML::Element]
134
- # @return [Nokogiri::XML::Element]
192
+ # [Parameters]
193
+ # - `name` (String)
194
+ # - `contents_or_attrs` (\#to_s, Hash)
195
+ # [Yields] `node` (Nokogiri::XML::Element)
196
+ # [Returns] Nokogiri::XML::Element
197
+ #
198
+ # *Example:* An empty element without attributes
135
199
  #
136
- # @example An empty element without attributes
137
200
  # doc.create_element("div")
138
201
  # # => <div></div>
139
202
  #
140
- # @example An element with contents
203
+ # *Example:* An element with contents
204
+ #
141
205
  # doc.create_element("div", "contents")
142
206
  # # => <div>contents</div>
143
207
  #
144
- # @example An element with attributes
208
+ # *Example:* An element with attributes
209
+ #
145
210
  # doc.create_element("div", {"class" => "container"})
146
211
  # # => <div class='container'></div>
147
212
  #
148
- # @example An element with contents and attributes
213
+ # *Example:* An element with contents and attributes
214
+ #
149
215
  # doc.create_element("div", "contents", {"class" => "container"})
150
216
  # # => <div class='container'>contents</div>
151
217
  #
152
- # @example Passing a block to mutate the element
218
+ # *Example:* Passing a block to mutate the element
219
+ #
153
220
  # doc.create_element("div") { |node| node["class"] = "blue" if before_noon? }
154
221
  #
155
222
  def create_element(name, *contents_or_attrs, &block)
@@ -170,30 +237,30 @@ module Nokogiri
170
237
  elm.content = arg
171
238
  end
172
239
  end
173
- if ns = elm.namespace_definitions.find { |n| n.prefix.nil? || (n.prefix == '') }
240
+ if (ns = elm.namespace_definitions.find { |n| n.prefix.nil? || (n.prefix == "") })
174
241
  elm.namespace = ns
175
242
  end
176
243
  elm
177
244
  end
178
245
 
179
246
  # Create a Text Node with +string+
180
- def create_text_node string, &block
181
- Nokogiri::XML::Text.new string.to_s, self, &block
247
+ def create_text_node(string, &block)
248
+ Nokogiri::XML::Text.new(string.to_s, self, &block)
182
249
  end
183
250
 
184
251
  # Create a CDATA Node containing +string+
185
- def create_cdata string, &block
186
- Nokogiri::XML::CDATA.new self, string.to_s, &block
252
+ def create_cdata(string, &block)
253
+ Nokogiri::XML::CDATA.new(self, string.to_s, &block)
187
254
  end
188
255
 
189
256
  # Create a Comment Node containing +string+
190
- def create_comment string, &block
191
- Nokogiri::XML::Comment.new self, string.to_s, &block
257
+ def create_comment(string, &block)
258
+ Nokogiri::XML::Comment.new(self, string.to_s, &block)
192
259
  end
193
260
 
194
261
  # The name of this document. Always returns "document"
195
262
  def name
196
- 'document'
263
+ "document"
197
264
  end
198
265
 
199
266
  # A reference to +self+
@@ -201,46 +268,51 @@ module Nokogiri
201
268
  self
202
269
  end
203
270
 
204
- ##
205
- # Recursively get all namespaces from this node and its subtree and
206
- # return them as a hash.
271
+ # :call-seq:
272
+ # collect_namespaces() Hash<String(Namespace#prefix) String(Namespace#href)>
207
273
  #
208
- # For example, given this document:
274
+ # Recursively get all namespaces from this node and its subtree and return them as a
275
+ # hash.
209
276
  #
210
- # <root xmlns:foo="bar">
277
+ # ⚠ This method will not handle duplicate namespace prefixes, since the return value is a hash.
278
+ #
279
+ # Note that this method does an xpath lookup for nodes with namespaces, and as a result the
280
+ # order (and which duplicate prefix "wins") may be dependent on the implementation of the
281
+ # underlying XML library.
282
+ #
283
+ # *Example:* Basic usage
284
+ #
285
+ # Given this document:
286
+ #
287
+ # <root xmlns="default" xmlns:foo="bar">
211
288
  # <bar xmlns:hello="world" />
212
289
  # </root>
213
290
  #
214
291
  # This method will return:
215
292
  #
216
- # { 'xmlns:foo' => 'bar', 'xmlns:hello' => 'world' }
293
+ # {"xmlns:foo"=>"bar", "xmlns"=>"default", "xmlns:hello"=>"world"}
294
+ #
295
+ # *Example:* Duplicate prefixes
217
296
  #
218
- # WARNING: this method will clobber duplicate names in the keys.
219
- # For example, given this document:
297
+ # Given this document:
220
298
  #
221
299
  # <root xmlns:foo="bar">
222
300
  # <bar xmlns:foo="baz" />
223
301
  # </root>
224
302
  #
225
- # The hash returned will look like this: { 'xmlns:foo' => 'bar' }
303
+ # The hash returned will be something like:
226
304
  #
227
- # Non-prefixed default namespaces (as in "xmlns=") are not included
228
- # in the hash.
229
- #
230
- # Note that this method does an xpath lookup for nodes with
231
- # namespaces, and as a result the order may be dependent on the
232
- # implementation of the underlying XML library.
305
+ # {"xmlns:foo" => "baz"}
233
306
  #
234
307
  def collect_namespaces
235
- xpath("//namespace::*").inject({}) do |hash, ns|
236
- hash[["xmlns",ns.prefix].compact.join(":")] = ns.href if ns.prefix != "xml"
237
- hash
308
+ xpath("//namespace::*").each_with_object({}) do |ns, hash|
309
+ hash[["xmlns", ns.prefix].compact.join(":")] = ns.href if ns.prefix != "xml"
238
310
  end
239
311
  end
240
312
 
241
313
  # Get the list of decorators given +key+
242
- def decorators key
243
- @decorators ||= Hash.new
314
+ def decorators(key)
315
+ @decorators ||= {}
244
316
  @decorators[key] ||= []
245
317
  end
246
318
 
@@ -249,7 +321,7 @@ module Nokogiri
249
321
  # the document or +nil+ when there is no DTD.
250
322
  def validate
251
323
  return nil unless internal_subset
252
- internal_subset.validate self
324
+ internal_subset.validate(self)
253
325
  end
254
326
 
255
327
  ##
@@ -269,7 +341,7 @@ module Nokogiri
269
341
  # ... which does absolutely nothing.
270
342
  #
271
343
  def slop!
272
- unless decorators(XML::Node).include? Nokogiri::Decorators::Slop
344
+ unless decorators(XML::Node).include?(Nokogiri::Decorators::Slop)
273
345
  decorators(XML::Node) << Nokogiri::Decorators::Slop
274
346
  decorate!
275
347
  end
@@ -279,16 +351,16 @@ module Nokogiri
279
351
 
280
352
  ##
281
353
  # Apply any decorators to +node+
282
- def decorate node
354
+ def decorate(node)
283
355
  return unless @decorators
284
- @decorators.each { |klass,list|
356
+ @decorators.each do |klass, list|
285
357
  next unless node.is_a?(klass)
286
358
  list.each { |moodule| node.extend(moodule) }
287
- }
359
+ end
288
360
  end
289
361
 
290
- alias :to_xml :serialize
291
- alias :clone :dup
362
+ alias_method :to_xml, :serialize
363
+ alias_method :clone, :dup
292
364
 
293
365
  # Get the hash of namespaces on the root Nokogiri::XML::Node
294
366
  def namespaces
@@ -298,16 +370,16 @@ module Nokogiri
298
370
  ##
299
371
  # Create a Nokogiri::XML::DocumentFragment from +tags+
300
372
  # Returns an empty fragment if +tags+ is nil.
301
- def fragment tags = nil
302
- DocumentFragment.new(self, tags, self.root)
373
+ def fragment(tags = nil)
374
+ DocumentFragment.new(self, tags, root)
303
375
  end
304
376
 
305
377
  undef_method :swap, :parent, :namespace, :default_namespace=
306
378
  undef_method :add_namespace_definition, :attributes
307
379
  undef_method :namespace_definitions, :line, :add_namespace
308
380
 
309
- def add_child node_or_tags
310
- raise "A document may not have multiple root nodes." if (root && root.name != 'nokogiri_text_wrapper') && !(node_or_tags.comment? || node_or_tags.processing_instruction?)
381
+ def add_child(node_or_tags)
382
+ raise "A document may not have multiple root nodes." if (root && root.name != "nokogiri_text_wrapper") && !(node_or_tags.comment? || node_or_tags.processing_instruction?)
311
383
  node_or_tags = coerce(node_or_tags)
312
384
  if node_or_tags.is_a?(XML::NodeSet)
313
385
  raise "A document may not have multiple root nodes." if node_or_tags.size > 1
@@ -316,17 +388,27 @@ module Nokogiri
316
388
  super
317
389
  end
318
390
  end
319
- alias :<< :add_child
391
+ alias_method :<<, :add_child
392
+
393
+ # :call-seq:
394
+ # xpath_doctype() → Nokogiri::CSS::XPathVisitor::DoctypeConfig
395
+ #
396
+ # [Returns] The document type which determines CSS-to-XPath translation.
397
+ #
398
+ # See XPathVisitor for more information.
399
+ def xpath_doctype
400
+ Nokogiri::CSS::XPathVisitor::DoctypeConfig::XML
401
+ end
320
402
 
321
403
  private
322
404
 
323
- def self.empty_doc? string_or_io
405
+ def self.empty_doc?(string_or_io)
324
406
  string_or_io.nil? ||
325
407
  (string_or_io.respond_to?(:empty?) && string_or_io.empty?) ||
326
408
  (string_or_io.respond_to?(:eof?) && string_or_io.eof?)
327
409
  end
328
410
 
329
- IMPLIED_XPATH_CONTEXTS = [ '//'.freeze ].freeze # :nodoc:
411
+ IMPLIED_XPATH_CONTEXTS = ["//"].freeze # :nodoc:
330
412
 
331
413
  def inspect_attributes
332
414
  [:name, :children]