leptris 1.9.58 → 1.9.59

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: 159f07010d3dd22a62761daef970c4090a47ee9d7ba6471099380410119dadf2
4
- data.tar.gz: b80e233d06f4d3af6bb14cc1cbf157ce88dfd7c745ffe7c936bc333d77b7e92d
3
+ metadata.gz: e2a400c8a5129b1a0485f8ec239fc11abe6261c5f930e46369ce2481ee5c7ea0
4
+ data.tar.gz: 2fcdb3f77738362d51d5dd65c1bbea8d1a495c21b141e602b6f8e663b2e97b4b
5
5
  SHA512:
6
- metadata.gz: c2a1504b697e82a0eddeb8966597f2e39ba27362fa6ebdff2edf9dae2258f5a6cf5757b7088c144f69309ca5016297cba39513fe3a1a901b709029d82a45e88f
7
- data.tar.gz: 4314c5cf903efe548acaec50494a40578e543f31268ffa9fcdee9e0bd9a069efa152bb8889ad86f6c43b638bd48ad7d554428e9ea9c48b1970301913aa905d66
6
+ metadata.gz: af3f53eef914d192c152054c35d979ae09098684d25aadf1bf3eb50fca7d67736faf05a9f32f48434e8388eb09ebebd4b5ef00f8d7f21e6d563b144faaae045b
7
+ data.tar.gz: f14d0cfaa7696949a7cf50cb1af6b095289ef8877f54c1968f7f0147083066c10059232f3f6b1df691600345e3f04615ce1793fd0f3512c6a886f55d113ed875
data/CHANGELOG.md CHANGED
@@ -5,6 +5,44 @@ 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.59] - 2026-09-04
9
+
10
+ ### Added
11
+
12
+ - **Lockstep with libleptris 1.9.76** (one release, four engine
13
+ fixes — the tracker-clearing round). One new C symbol attached
14
+ (audit 261/261):
15
+ - **`Element#namespace=`** (leptris/leptris#817, closes
16
+ leptris-ruby#132): Nokogiri `node.namespace=` semantics — `nil`
17
+ detaches (prefix clears, `xmlns=""` blocks in-scope defaults),
18
+ a URI rebinds to an in-scope declaration carrying it (adopting
19
+ its prefix; raises when none is in scope — declare first).
20
+ Three specs; README Namespaces entry. The setter rides
21
+ `ensure_writable!`'s version advance so memoization
22
+ invalidates correctly.
23
+ - Upstream also fixed the serializer half: unqualified renames no
24
+ longer resurrect the old prefix.
25
+
26
+ ### Fixed
27
+
28
+ - **#131 closed** (leptris/leptris#815, engine): the intermittent
29
+ unescaped-`<` under parse pressure — a dirty recycled pool page
30
+ left `base.raw` set on ~5-7% of parses and the indenting
31
+ serializer emitted that node's text verbatim. Our exact repro:
32
+ 0/100 on 1.9.76.
33
+ - **`dup` reverts to the C copy again** (leptris/leptris#812, the
34
+ 1.9.74 descendant-declaration regression fixed): byte-for-byte
35
+ namespaced mixed-content copies restored, and the copier is fast
36
+ — ~68 µs flat per 250-record subtree (the round-trip ran ~95 µs),
37
+ and 2.5x Nokogiri on a 100-book subtree (52 vs 131 µs). The
38
+ #130 degradation shape stays flat.
39
+ - **The #790 follow-up fixed** (leptris/leptris#814): the `where`
40
+ clause in function-argument FLWOR now filters correctly (2.0 on
41
+ the shape that returned 3.0) — the last pending spec is un-pending.
42
+ - **HTML parity** (leptris/leptris#813): minimized attributes
43
+ serialize `checked=""`, and the synthesized wrapper omits an
44
+ empty `<head>`. README updated.
45
+
8
46
  ## [1.9.58] - 2026-09-03
9
47
 
10
48
  ### Added
data/README.adoc CHANGED
@@ -122,9 +122,9 @@ doc.at_css("body").inner_html # => "<ul><li>a</li><li>b</li></ul>"
122
122
  Implied end tags (`p`/`li`/`td`/`tr`/...), void elements, raw-text
123
123
  `<script>`/`<style>`, case-insensitive lowercased names,
124
124
  minimized/unquoted attributes, and the HTML named entities all
125
- parse; `html`/`head`/`body` are synthesized (Nokogiri::HTML parity)
126
- but `tbody` is never implied. Malformed markup degrades to text
127
- rather than raising.
125
+ parse; `html`/`body` are synthesized (an empty `head` is not) and
126
+ `tbody` is never implied. Malformed markup degrades to text rather
127
+ than raising.
128
128
 
129
129
  == Reading nodes
130
130
 
@@ -349,6 +349,7 @@ doc.root.name = "catalog"
349
349
  `Element#namespace_definitions` :: only namespaces declared directly on this element.
350
350
  `Element#add_namespace_definition(prefix, href)` (alias `#add_namespace`) :: declare `xmlns:prefix="href"` on this element.
351
351
  `Element#default_namespace=(href)` :: declare/replace `xmlns="href"`.
352
+ `Element#namespace=(uri)` :: Nokogiri `node.namespace=` semantics (libleptris 1.9.76): `nil` detaches — prefix clears, `xmlns=""` blocks in-scope defaults; a URI rebinds to an in-scope declaration carrying it (adopting its prefix; raises when none is in scope — declare first).
352
353
  `Element#remove_namespace_definition(prefix)` :: drop a declaration.
353
354
  `Element#attribute_ns(uri, local)` :: attribute value by expanded name (URI + local); nil URI matches no-namespace attributes only.
354
355
  `Element#has_attribute_ns?(uri, local)` :: presence by expanded name.
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.75"
11
+ LIBLEPTRIS_VERSION = "1.9.76"
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.58"
4
+ VERSION = "1.9.59"
5
5
  end
@@ -251,12 +251,15 @@ class Leptris::XML::Element < Leptris::XML::Node
251
251
  self
252
252
  end
253
253
 
254
- # Deep copy in a NEW document via serialization round-trip
255
- # (leptris/leptris#812: the 1.9.74 copy rewrite drops
256
- # descendant-used declarations; the serializer is byte-exact).
254
+ # Deep copy in a NEW document via the C copy, attached as the
255
+ # fresh document's root (#696 1.9.39, #721 1.9.47, #812 1.9.76 —
256
+ # every child kind and namespace survives, pool-threaded).
257
257
  def dup
258
258
  ensure_alive!
259
- Leptris::XML::Document.parse(to_xml).root
259
+ new_doc = Leptris::XML::Document.create
260
+ copy = Leptris::XML::FFI.leptris_element_copy(@c_ptr, new_doc.c_ptr)
261
+ raise Leptris::XML::Error, "leptris_element_copy failed" if copy.null?
262
+ new_doc.root = Leptris::XML::Node.wrap(copy, new_doc)
260
263
  end
261
264
  alias_method :clone, :dup
262
265
 
@@ -304,6 +307,20 @@ class Leptris::XML::Element < Leptris::XML::Node
304
307
  result
305
308
  end
306
309
 
310
+ # Nokogiri node.namespace= semantics (libleptris 1.9.76, #817):
311
+ # nil (or "") detaches the namespace — the resolved link and the
312
+ # name's prefix clear, and an xmlns="" undeclaration blocks
313
+ # in-scope defaults from capturing the unqualified name. A URI
314
+ # rebinds to an in-scope declaration carrying it (adopting its
315
+ # prefix); a URI with no in-scope declaration raises — declare
316
+ # it first with #add_namespace_definition.
317
+ def namespace=(uri)
318
+ ensure_writable!
319
+ Leptris::XML::FFI.check_status(
320
+ Leptris::XML::FFI.leptris_element_set_namespace(@c_ptr, uri&.to_s))
321
+ uri
322
+ end
323
+
307
324
  def namespace_definitions
308
325
  return @namespace_definitions if memo_hit?(@namespace_definitions_version)
309
326
  ensure_alive!
@@ -451,6 +451,13 @@ attach_function :leptris_parse_string,
451
451
  attach_function :leptris_parse_fragment,
452
452
  [:string, :size_t, :leptris_document, :pointer], :leptris_element
453
453
 
454
+ # Nokogiri node.namespace= parity (libleptris 1.9.76, #817):
455
+ # NULL (or "") detaches — link + prefix clear, xmlns=""
456
+ # undeclaration added; a URI rebinds to an IN-SCOPE
457
+ # declaration carrying it (NOT_FOUND if there is none — this
458
+ # entry does not invent declarations).
459
+ attach_function :leptris_element_set_namespace,
460
+ [:leptris_element, :string], :leptris_status
454
461
  attach_function :leptris_element_namespace,
455
462
  [:leptris_element], :string
456
463
  attach_function :leptris_element_namespace_for_prefix,
@@ -374,17 +374,20 @@ class Leptris::XML::Node
374
374
  result
375
375
  end
376
376
 
377
- # Deep copy in a NEW document. Rounds through serialization: the
378
- # 1.9.74 copy rewrite (#653 perf lane) drops declarations used
379
- # only by descendants — resolution on the copied subtree resolves
380
- # NULL (leptris/leptris#812, an #721 regression) — while the
381
- # serializer preserves every child kind, prefixed name, and
382
- # declaration byte-for-byte.
377
+ # Deep copy in a NEW document via the C copy, attached as the
378
+ # fresh document's root. Both copy gaps are closed for good:
379
+ # comment/PI children in 1.9.39 (#696), namespaces in 1.9.47
380
+ # (#721) with the 1.9.74 descendant-declaration regression fixed
381
+ # in 1.9.76 (#812). Perf: the detached copier is pool-threaded —
382
+ # upstream measures ~2.3x Nokogiri per subtree.
383
383
  def dup
384
384
  ensure_alive!
385
385
  elem_ptr = Leptris::XML::FFI.leptris_node_as_element(@c_ptr)
386
386
  raise Leptris::XML::Error, "dup is only supported for element nodes" if elem_ptr.null?
387
- Leptris::XML::Document.parse(to_xml).root
387
+ new_doc = Leptris::XML::Document.create
388
+ copy = Leptris::XML::FFI.leptris_element_copy(elem_ptr, new_doc.c_ptr)
389
+ raise Leptris::XML::Error, "leptris_element_copy failed" if copy.null?
390
+ new_doc.root = Leptris::XML::Node.wrap(copy, new_doc)
388
391
  end
389
392
  alias_method :clone, :dup
390
393
 
@@ -115,14 +115,17 @@ module Leptris::XML::Serialization
115
115
 
116
116
  # Element-face indent unit (leptris-ruby#109 residual 2): no
117
117
  # element-level ext-serialize entry exists yet, so the unit path
118
- # rounds the subtree through serialization into a fresh document
119
- # (the 1.9.74 C copy drops descendant-used declarations —
120
- # leptris/leptris#812) and serializes that document without a
121
- # declaration — identical output to the element serializer for
122
- # the standard layout, with the unit and every child kind intact.
118
+ # C-copies the subtree into a fresh document (every child kind
119
+ # and namespace survive since 1.9.76 — #696/#721/#812) and
120
+ # serializes that document without a declaration — identical
121
+ # output to the element serializer for the standard layout, with
122
+ # the unit and every child kind intact.
123
123
  def self.to_xml_element_unit(element, unit, indent: 0)
124
- document = Leptris::XML::Document.parse(element.to_xml)
124
+ document = Leptris::XML::Document.create
125
125
  begin
126
+ copy = Leptris::XML::FFI.leptris_element_copy(element.c_ptr, document.c_ptr)
127
+ raise Leptris::XML::Error, "leptris_element_copy failed" if copy.null?
128
+ document.root = Leptris::XML::Node.wrap(copy, document)
126
129
  to_xml_indent_unit(document.c_ptr, unit,
127
130
  indent: indent, no_decl: true)
128
131
  ensure
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.58
4
+ version: 1.9.59
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-03 00:00:00.000000000 Z
11
+ date: 2026-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi