leptris 1.9.51 → 1.9.52

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: aab0b795d90effa39a4670c8359fc2808267a48e7d93c7c1c314c3dfebb415f0
4
- data.tar.gz: 52bc50c5d171632e1a45b787d22bb9a94763d1f1df885e8c8197867cb4fc6673
3
+ metadata.gz: ce439698a32a7737054564af4f25866e9d49b87a86f30dee916e6d04f53e8249
4
+ data.tar.gz: 947ef61ce70fd53664851fe073d7504b1a2c28a59591e2b7c04ea482bcbed605
5
5
  SHA512:
6
- metadata.gz: 0efb45ab3367594bc1781d5d88a9a9db7f2d14af84b73b844cc9a8f08ad81eed03f6bd70a14d04d21240f8fdd592dc4a725c706f5277c10536ab0189333db6eb
7
- data.tar.gz: 33150488d60668fe10d62c6f00ab4129abb37816d5a940238b97283113f7cf04c4158a2b8d41e6fd8c73610242484a96bd92f35540033c7407d76cefdf1bd9d8
6
+ metadata.gz: c56ca957ac03806e595f8702cf4936b5303bf51761196d9b3bc9fb2aa84fb1023becb48520e59e8ec09defc5e482e8db929ecab787fc8925754ac182eaa7a2b2
7
+ data.tar.gz: 04b5685bb317af87788e52425b8b8f66b2e9b77f1d5488f65354b6631285695be22a746b6536024f4b5172d63765b6ea196d4a2de74f627e86cccf6f92365967
data/CHANGELOG.md CHANGED
@@ -5,6 +5,48 @@ 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.52] - 2026-09-02
9
+
10
+ ### Changed
11
+
12
+ - **Lockstep with libleptris 1.9.43** (1.9.37 → 1.9.43; no new C
13
+ surface — the audit holds at 255/255 attached == exported):
14
+ - 1.9.37: tunnel parameters (§11.7) — `xsl:with-param
15
+ tunnel="yes"` persists for the whole subtree, including the
16
+ built-in unmatched-node path. This work also fixed the
17
+ `shallow-skip`/`text-only-copy` subtree drop (leptris/leptris#705).
18
+ - 1.9.38: regex trio atomizes node arguments (#691); single-item
19
+ atomic `xsl:sequence` serializes (#685 remainder); #705 verified
20
+ against a live Saxon-HE 12.7 oracle — all four reported shapes
21
+ pinned, with the correction that the no-template case emits
22
+ EMPTY for both dispositions (the report's `312` expectation
23
+ contradicted Saxon).
24
+ - 1.9.39: `leptris_element_copy` keeps COMMENT and PI children
25
+ (leptris/leptris#696) — pinned with a C-level spec.
26
+ - 1.9.40: fn: date slice (#691-E) — `xs:date`/`xs:dateTime`/
27
+ `xs:time`/`xs:duration` constructors and component extractors.
28
+ - 1.9.41: `switch` rejected like Saxon (XPST0003 pattern-only);
29
+ the #692 brace guard now runs the compiler first — map
30
+ constructors and `try/catch` raise cleanly in XPath expression
31
+ context instead of returning empty silently.
32
+ - 1.9.42: `xsl:where-populated`, `xsl:on-non-empty`,
33
+ `xsl:next-match` (#690/#685).
34
+ - 1.9.43: `xsl:fork`, `xsl:number @start-at`, composite keys
35
+ (#690/#685).
36
+ - Nine new specs cover the above through the generic
37
+ `XSLT.parse/apply_to` face; the two pending #705 disposition
38
+ specs are un-pending with the Saxon-verified expectations.
39
+
40
+ ### Fixed
41
+
42
+ - **`dup` keeps the serialization round-trip** (leptris/leptris#721,
43
+ filed this round): with #696 fixed upstream, the C copy now
44
+ keeps comment/PI children — but it drops namespace prefixes and
45
+ declarations outright (`leptris_element_namespace` resolves NULL
46
+ after a copy), while the round-trip preserves them byte-for-byte.
47
+ The dup sites' comments now carry the #721 rationale; the revert
48
+ to the C fast path waits on #721.
49
+
8
50
  ## [1.9.51] - 2026-09-01
9
51
 
10
52
  ### Changed
data/README.adoc CHANGED
@@ -9,7 +9,9 @@ A Nokogiri-compatible Ruby binding for
9
9
  https://github.com/leptris/leptris[libleptris], a pure-C99 XML 1.0 parser
10
10
  with full https://www.w3.org/TR/1999/REC-xpath-19991116/[XPath 1.0],
11
11
  XML Namespaces 1.0, SAX, and C14N (1.0 / 1.1 / Exclusive), plus
12
- XSLT 1.0–3.0 transforms (the XPath 3.1 core rides inside them).
12
+ XSLT 1.0–3.0 transforms (the XPath 3.1 core rides inside them) and a
13
+ growing XPath 2/3.1 expression subset available standalone from
14
+ `#xpath` itself.
13
15
 
14
16
  The C DOM is the single source of truth — Ruby objects are thin FFI
15
17
  handles over the C pointers, so every Ruby method maps to one FFI call.
@@ -225,6 +227,30 @@ XPath result type follows XPath 1.0 semantics:
225
227
  `count(...)` → `Float`, `boolean(...)` → `true`/`false`,
226
228
  `string(...)` → `String`, otherwise a `Leptris::XML::NodeSet`.
227
229
 
230
+ Beyond XPath 1.0, the engine accepts a growing XPath 2/3.1
231
+ expression subset standalone — no stylesheet required:
232
+
233
+ [source,ruby]
234
+ ----
235
+ doc.xpath("let $n := count(//book) return $n + 1") # => 3.0
236
+ doc.xpath("for $b in //book return count($b/*)") # sequence
237
+ doc.xpath("if (count(//book) = 2) then 'two' else '?'")
238
+ doc.xpath("count(1 to 4)") # => 4.0
239
+ doc.xpath("//book => count()") # 3.1 arrow
240
+ doc.xpath("//title ! string(.)") # 3.1 simple map
241
+ doc.xpath("'v' || count(//book)") # 3.1 concat
242
+ ----
243
+
244
+ Two caveats: `for … return` sequences come back as opaque result
245
+ nodes — consume them through an aggregate (`count(...)`,
246
+ `string-join(...)`) until the engine materializes readable sequence
247
+ items; and XQuery-only syntax (`order by`, `try/catch`, map
248
+ constructors) raises `XPathError` rather than evaluating silently
249
+ wrong. The remaining grammar gaps — value comparators (`eq`),
250
+ quantifiers, sequence types (`instance of`), `intersect`/`except`,
251
+ string templates — and XQuery itself are
252
+ https://github.com/leptris/leptris/issues/683[tracked upstream].
253
+
228
254
  === Supported CSS selectors
229
255
 
230
256
  Minimal subset (translated to XPath via `Leptris::XML::CssToXPath`):
@@ -339,11 +365,20 @@ result = style.apply_to(doc) # => Document
339
365
  style.serialize(doc) # => String
340
366
  ----
341
367
 
342
- The engine dispatches on the stylesheet's declared version; the 3.0
343
- instruction set (grouping, `xsl:accumulator`, `xsl:analyze-string`,
344
- the XPath 3.1 core) is available inside transforms. Standalone
345
- XPath 2.0/3.1 evaluation entries and XQuery are
346
- https://github.com/leptris/leptris/issues/683[tracked upstream].
368
+ The engine dispatches on the stylesheet's declared version. XSLT
369
+ 1.0 is complete; the 3.0 instruction set has grown through
370
+ libleptris 1.9.36 — grouping, `xsl:accumulator`,
371
+ `xsl:analyze-string`, `xsl:mode/@on-no-match` dispositions,
372
+ `xsl:sequence`, `xsl:perform-sort`, and `fn:format-integer` — with
373
+ the XPath 3.1 core expressions available inside transforms (see
374
+ the subset list under <<Searching: XPath and CSS>>; value
375
+ comparators and sequence types are still out,
376
+ https://github.com/leptris/leptris/issues/683[tracked upstream]).
377
+ Known engine bug: the `shallow-skip` and `text-only-copy`
378
+ dispositions drop unmatched subtrees in the built-in initial
379
+ descent (https://github.com/leptris/leptris/issues/705[#705]) —
380
+ the other four dispositions are spec-correct. XQuery has no
381
+ entry point yet.
347
382
  `Document#save(path, **opts)` :: serialize to a file.
348
383
  `Document#canonicalize(version, inclusive_ns, with_comments:, exclusive:, mode:)` (alias `#c14n`) :: canonical XML.
349
384
  `Element#canonicalize(...)` :: subtree canonicalization.
@@ -510,7 +545,8 @@ Notable differences:
510
545
  past Document disposal will see the error; silence-replace-UAF patterns
511
546
  from Nokogiri do not apply.
512
547
  * No `Nokogiri::HTML` or `Nokogiri::CSS` parser. Leptris is XML-only.
513
- * No XSLT, no RelaxNG / DTD validation, no schema caching.
548
+ * No XQuery, no RelaxNG / DTD validation, no schema caching
549
+ (XSLT 1.0–3.0 is supported — see above).
514
550
  * No built-in JRuby / TruffleRuby support — only CRuby via `ffi`.
515
551
 
516
552
  == Performance
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.36"
11
+ LIBLEPTRIS_VERSION = "1.9.43"
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.51"
4
+ VERSION = "1.9.52"
5
5
  end
@@ -252,10 +252,11 @@ class Leptris::XML::Element < Leptris::XML::Node
252
252
  end
253
253
 
254
254
  # Deep copy in a NEW document, via serialization round-trip:
255
- # leptris_element_copy silently drops COMMENT and PI children
256
- # (leptris/leptris#696, leptris-ruby#115) — the serializer
257
- # preserves every child kind, prefixed names, and namespace
258
- # declarations, and re-parsing rebuilds them all.
255
+ # leptris_element_copy drops namespace prefixes and declarations
256
+ # outright (leptris/leptris#721; its comment/PI child drop was
257
+ # #696, fixed upstream in 1.9.39) — the serializer preserves
258
+ # every child kind, prefixed names, and namespace declarations,
259
+ # and re-parsing rebuilds them all.
259
260
  def dup
260
261
  ensure_alive!
261
262
  Leptris::XML::Document.parse(to_xml).root
@@ -370,10 +370,11 @@ class Leptris::XML::Node
370
370
  end
371
371
 
372
372
  # Deep copy in a NEW document. Rounds through serialization
373
- # rather than leptris_element_copy: the C copy silently drops
374
- # COMMENT and PI children (leptris/leptris#696, leptris-ruby#115)
375
- # — the serializer preserves every child kind, prefixed names,
376
- # and namespace declarations, and re-parsing rebuilds them all.
373
+ # rather than leptris_element_copy: the C copy drops namespace
374
+ # prefixes and declarations outright (leptris/leptris#721; the
375
+ # comment/PI child drop was #696, fixed upstream in 1.9.39) —
376
+ # the serializer preserves every child kind, prefixed names, and
377
+ # namespace declarations, and re-parsing rebuilds them all.
377
378
  def dup
378
379
  ensure_alive!
379
380
  elem_ptr = Leptris::XML::FFI.leptris_node_as_element(@c_ptr)
@@ -98,11 +98,10 @@ module Leptris::XML::Serialization
98
98
  # Element-face indent unit (leptris-ruby#109 residual 2): no
99
99
  # element-level ext-serialize entry exists yet, so the unit path
100
100
  # rounds the subtree through serialization into a fresh document
101
- # (leptris_element_copy drops COMMENT/PI children —
102
- # leptris/leptris#696, leptris-ruby#115) and serializes that
103
- # document without a declaration — identical output to the
104
- # element serializer for the standard layout, with the unit and
105
- # every child kind intact.
101
+ # (leptris_element_copy drops namespaces — leptris/leptris#721)
102
+ # and serializes that document without a declaration — identical
103
+ # output to the element serializer for the standard layout, with
104
+ # the unit and every child kind intact.
106
105
  def self.to_xml_element_unit(element, unit, indent: 0)
107
106
  document = Leptris::XML::Document.parse(element.to_xml)
108
107
  begin
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.51
4
+ version: 1.9.52
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-01 00:00:00.000000000 Z
11
+ date: 2026-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi