leptris 1.9.43 → 1.9.44

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a87e2a5aa4eddbbaf1140aa87d33fcd3e0dccfb7ea505cbcaf917dbd3bf715fd
4
- data.tar.gz: '09b6e2b0d46ed3235945f3ad3355fbf46d515ddfc0b3bce2ac75468a80d0af5d'
3
+ metadata.gz: 9895934a1c086857555795905c15ab4f74ef053804e489674192bc7f4cc70bf3
4
+ data.tar.gz: b1bf31ac8c0ef5f718d78d4ae0654218cd3c212adf33e75628326949644032d1
5
5
  SHA512:
6
- metadata.gz: 267bbe8cac5597fa0e40736f087fffc739c9f3c1fb3063fbe652b25bb9e0a958424b283a5933a963c919d20db6128f35dcd2c98b94439613eeed3edcd17877f0
7
- data.tar.gz: 93075be6a11e7fe9cdebfd812c617fe274ef9f93d67cce33d0c83b6e173b9f1fe6515aaff73907155fd09bae9d4867b8e6e35710551764b5554ea8c1214eefe7
6
+ metadata.gz: 536c0b5a7ddb425395b077f5a6a0b40ebc893c6037ba71277a1b6eaa70b9769e977b03b9ed0f81ccf6d9a70e11c4f4095b8ab3e473268f2cb38306ea897d28e4
7
+ data.tar.gz: d34c001bf6840c12d3e44a0253166938523f57c0e935a6dfa4560cea575b02af043d25caf0a491a77810726b168c64e556c63b825355eb3ff23ffbbf010848c5
data/CHANGELOG.md CHANGED
@@ -5,6 +5,35 @@ All notable changes to Leptris will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.9.44] - 2026-08-31
9
+
10
+ ### Added
11
+
12
+ - **libleptris 1.9.19–1.9.22 lockstep** (audit 255/255, three new
13
+ symbols): the #653 hold is lifted — the reported parse
14
+ "regression" was an ill-formed fixture (stray `</y>`) plus a
15
+ stale-build bisect artifact; forced-clean rebuilds show 1.9.18
16
+ and 1.9.21+ identical on every well-formed shape (verified and
17
+ withdrawn on the issue).
18
+ - **`Node#visit`** (upstream #645a, `leptris_node_visit`): one C
19
+ call over the subtree — elements yield `(node, true/false,
20
+ depth)` enter/leave pairs, other kinds once, depth from the
21
+ receiver; the document node walks the document chain. No
22
+ NodeSet, pointer array, or children memo per level — the leanest
23
+ full-subtree iteration the binding offers (#645a's walk lever;
24
+ consumers can now beat the children-recursion allocation floor).
25
+ - **Indent unit with Nokogiri semantics (leptris-ruby#109,
26
+ upstream #633)**: `to_xml(indent: 2, indent_text: "\t")` — the
27
+ unit string replaces the default spaces, repeated `indent`
28
+ times per depth level, standard layout otherwise
29
+ (byte-identical to Nokogiri's output modulo their trailing
30
+ newline, which moxml normalizes). `indent_text: true` keeps the
31
+ display form; `false` the default. Wired through the sized
32
+ ext-serialize entry (PR #107's substance — the audit requires it
33
+ attached with the lockstep, so it rides here; the engine emits
34
+ one unit copy per level and the binding multiplies unit x indent
35
+ to reach Nokogiri's repeat count).
36
+
8
37
  ## [1.9.43] - 2026-08-31
9
38
 
10
39
  ### Fixed
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ RSpec::Core::RakeTask.new(:spec)
8
8
  # Pin for `rake compile` and the platform-gem builds. Keep in lockstep
9
9
  # with .github/workflows/build.yml (which calls `rake compile`) and the
10
10
  # CHANGELOG when libleptris releases.
11
- LIBLEPTRIS_VERSION = "1.9.18"
11
+ LIBLEPTRIS_VERSION = "1.9.22"
12
12
 
13
13
  CMAKE_FLAGS = %w[
14
14
  -DCMAKE_BUILD_TYPE=Release
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leptris
4
- VERSION = "1.9.43"
4
+ VERSION = "1.9.44"
5
5
  end
@@ -266,13 +266,21 @@ class Leptris::XML::Document
266
266
  end
267
267
  alias_method :internal_subset, :doctype
268
268
 
269
- # indent_text: true selects the display form (libleptris 1.9.9,
270
- # #129): text and mixed content indent too — the output is
271
- # display-oriented and not round-trip-guaranteed.
269
+ # indent_text selects the ext-serializer knob (libleptris 1.9.22):
270
+ # a STRING is the indent unit with Nokogiri's semantics — the unit
271
+ # replaces the default spaces, one copy per depth level, standard
272
+ # layout (requires indent > 0); true selects the display form
273
+ # (1.9.9 #129 — text and mixed content indent too; output is
274
+ # display-oriented and not round-trip-guaranteed).
272
275
  def to_xml(indent: 0, no_decl: false, encoding: nil, indent_text: false)
273
276
  raise Leptris::XML::UseAfterFreeError if @freed.state == :freed
274
277
  return "" if @c_ptr.nil?
275
- if indent_text
278
+ case indent_text
279
+ when String
280
+ return Leptris::XML::Serialization.to_xml_indent_unit(
281
+ @c_ptr, indent_text, indent: indent, no_decl: no_decl,
282
+ encoding: encoding)
283
+ when true
276
284
  return Leptris::XML::Serialization.to_xml_display(
277
285
  @c_ptr, indent: indent, no_decl: no_decl, encoding: encoding)
278
286
  end
@@ -72,10 +72,13 @@ module Leptris
72
72
  :encoding, :pointer
73
73
  end
74
74
 
75
- # LeptrisSerializeExtOptions (1.9.9, #129): display-form
76
- # serialization knobs beyond the ABI-frozen options struct.
75
+ # LeptrisSerializeExtOptions (1.9.9 #129 display form; 1.9.22
76
+ # #633/#109 indent unit): knobs beyond the ABI-frozen options
77
+ # struct. MAY grow — always pass its size through the sized
78
+ # entry.
77
79
  class SerializeExtStruct < ::FFI::Struct
78
- layout :indent_text, :int
80
+ layout :indent_text, :int,
81
+ :indent_unit, :pointer
79
82
  end
80
83
 
81
84
  # Mirrors LeptrisParseOptions (libleptris >= 1.9.0 carries the
@@ -154,6 +157,12 @@ module Leptris
154
157
  # 1.9.7, upstream #580; the libxml2 model).
155
158
  attach_function :leptris_document_node,
156
159
  [:leptris_document], :leptris_node_ref
160
+ # Wrap-free subtree visitation (1.9.20, upstream #645a):
161
+ # enter/leave pairs for elements, depth from the walk's root,
162
+ # one C call — no NodeSet/Array churn per level. The document
163
+ # node walks the document child chain.
164
+ attach_function :leptris_node_visit,
165
+ [:leptris_node_ref, :pointer, :pointer], :void
157
166
  # Document-level PIs (v1.6.0): not tree nodes — enumerate via
158
167
  # these accessors only.
159
168
  attach_function :leptris_document_pi_count,
@@ -646,6 +655,11 @@ module Leptris
646
655
  # read_owned_string (the seam frees it).
647
656
  attach_function :leptris_document_serialize_ext,
648
657
  [:leptris_document, :pointer, :pointer], :pointer
658
+ # Sized variant (1.9.19, upstream #644 — leptris-ruby PR #107):
659
+ # passing our ext-struct size keeps the engine from reading
660
+ # past this binding's allocation (the MSVC segfault).
661
+ attach_function :leptris_document_serialize_ext_sized,
662
+ [:leptris_document, :pointer, :pointer, :size_t], :pointer
649
663
  attach_function :leptris_document_serialize_into,
650
664
  [:leptris_document, :pointer, :size_t, :pointer, :pointer], :size_t
651
665
  attach_function :leptris_document_get_dtd,
@@ -273,6 +273,31 @@ class Leptris::XML::Node
273
273
  end
274
274
  alias_method :remove, :unlink
275
275
 
276
+ # Visits the subtree with ONE C call (leptris_node_visit,
277
+ # libleptris 1.9.20 — upstream #645a): elements yield twice —
278
+ # (node, true, depth) before their children, (node, false, depth)
279
+ # after the subtree completes — every other kind once with
280
+ # entering=true; depth counts element levels from the receiver.
281
+ # No NodeSet, pointer array, or children memo per level: the
282
+ # leanest full-subtree iteration the binding offers (a document
283
+ # receiver walks the document child chain). The walk is read-only
284
+ # — mutate only between visits.
285
+ #
286
+ # root.visit { |node, entering, depth| ... }
287
+ def visit(&block)
288
+ return enum_for(:visit) unless block
289
+ ensure_alive!
290
+ document = @document
291
+ visitor = ::FFI::Function.new(
292
+ :void, [:pointer, :pointer, :int, :int], blocking: true) do |_, node_ptr, entering, depth|
293
+ block.call(
294
+ Leptris::XML::Node.wrap(node_ptr, document),
295
+ entering == 1, depth)
296
+ end
297
+ Leptris::XML::FFI.leptris_node_visit(@c_ptr, visitor, nil)
298
+ self
299
+ end
300
+
276
301
  # Walks the subtree in post-order DFS (matches Nokogiri's
277
302
  # semantics): the receiver, its descendants, nothing else.
278
303
  #
@@ -47,8 +47,28 @@ module Leptris::XML::Serialization
47
47
  def self.to_xml_display(c_ptr, indent: 0, no_decl: false, encoding: nil)
48
48
  opts, encoding_anchor = build_options(
49
49
  indent: indent, no_decl: no_decl, encoding: encoding)
50
- str_ptr = Leptris::XML::FFI.leptris_document_serialize_ext(
51
- c_ptr, opts.pointer, INDENT_TEXT_EXT.pointer)
50
+ str_ptr = Leptris::XML::FFI.leptris_document_serialize_ext_sized(
51
+ c_ptr, opts.pointer, INDENT_TEXT_EXT.pointer, INDENT_TEXT_EXT.size)
52
+ Leptris::XML::FFI.read_owned_string(str_ptr)
53
+ end
54
+
55
+ # Indent-unit serialization (libleptris 1.9.22, #633 —
56
+ # leptris-ruby#109): Nokogiri's indent_text semantics — the unit
57
+ # string replaces the default spaces, repeated `indent` times per
58
+ # depth level, standard layout otherwise. The engine emits ONE
59
+ # copy of the unit string per level (options->indent is ignored
60
+ # when a unit is set), so the binding multiplies unit x indent to
61
+ # reach Nokogiri's repeat count.
62
+ def self.to_xml_indent_unit(c_ptr, unit, indent: 0, no_decl: false,
63
+ encoding: nil)
64
+ opts, encoding_anchor = build_options(
65
+ indent: indent, no_decl: no_decl, encoding: encoding)
66
+ ext = Leptris::XML::FFI::SerializeExtStruct.new
67
+ unit_anchor = ::FFI::MemoryPointer.from_string(
68
+ indent.positive? ? unit.to_s * indent : unit.to_s)
69
+ ext[:indent_unit] = unit_anchor
70
+ str_ptr = Leptris::XML::FFI.leptris_document_serialize_ext_sized(
71
+ c_ptr, opts.pointer, ext.pointer, ext.size)
52
72
  Leptris::XML::FFI.read_owned_string(str_ptr)
53
73
  end
54
74
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.43
4
+ version: 1.9.44
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.