leptris 1.9.17 → 1.9.19
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 +4 -4
- data/CHANGELOG.md +39 -0
- data/Rakefile +1 -1
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/document.rb +15 -0
- data/lib/leptris/xml/ffi.rb +29 -0
- data/lib/leptris/xml/xslt.rb +85 -0
- data/lib/leptris/xml.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 97ca1201d65e8bb43ac419b09c9e208fd49a1cb88275beb14cb2f2ec0e7965e2
|
|
4
|
+
data.tar.gz: df1b06279ae9426f463c724a6c895a135daedb19880f62ba1c8cda377228af3f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 390e31d59b5fe74f08776d719e5cd608a6cee954184a65edd688d25e92ed019be47b39c65369a5553fe1b1425341570778b3f6a7abf5896ca425935cf1e3e2aa
|
|
7
|
+
data.tar.gz: f72f7460afa8f16d0aa77e313d8d047c8ff1cf98180332c34f59c4034352fa737256cf943b1cecf941caee2ae7beddd1e0f844c1e2bb305332594f496b026d77
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,45 @@ 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.19] - 2026-08-27
|
|
9
|
+
|
|
10
|
+
Lockstep with libleptris 1.9.3 — unblocks the 1.9.18 release
|
|
11
|
+
(v1.9.2 did not compile on musl, upstream #582).
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`Document#comments`**: document-level comments — parsed
|
|
16
|
+
`<!-- ... -->` outside the root, prolog then epilog, in document
|
|
17
|
+
order (upstream #578). UTF-8, version-memoized like the PI list;
|
|
18
|
+
the companion reader to `#processing_instructions`.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Rides the engine's v1.9.3 fixes: dataless PIs parse correctly
|
|
23
|
+
(#577 — `<?pi?>` no longer clobbers its closing `?`), epilog
|
|
24
|
+
comments are kept and serialize after the root (#578), and
|
|
25
|
+
attribute values normalize per XML 1.0 §3.3.3 (#576 — whitespace
|
|
26
|
+
collapsing and entity decoding in attribute values).
|
|
27
|
+
|
|
28
|
+
## [1.9.18] - 2026-08-27
|
|
29
|
+
|
|
30
|
+
Lockstep with libleptris 1.9.2 (covers 1.9.1 — the XSLT engine — and
|
|
31
|
+
1.9.2, the options-struct ABI freeze; the binding's three-field
|
|
32
|
+
SerializeOptions layout is the frozen shape, so no binding change was
|
|
33
|
+
required for the fix).
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- **`Leptris::XML::XSLT` — XSLT 1.0 transforms**: the engine compiles
|
|
38
|
+
a stylesheet ONCE into an immutable instruction forest, then applies
|
|
39
|
+
it to any number of documents. `XSLT.parse(xml)` /
|
|
40
|
+
`XSLT.parse_file(path)` (resolves §2.7 embedded stylesheets);
|
|
41
|
+
`Stylesheet#apply_to(doc)` returns the result as an owning,
|
|
42
|
+
queryable Document; `Stylesheet#serialize(doc)` keeps top-level
|
|
43
|
+
text nodes and result fragments. Bad select expressions are
|
|
44
|
+
rejected at COMPILE time. The custom XPath-function handler seam
|
|
45
|
+
attaches mirror-only until a use case arrives.
|
|
46
|
+
|
|
8
47
|
## [1.9.17] - 2026-08-27
|
|
9
48
|
|
|
10
49
|
### Changed
|
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.
|
|
11
|
+
LIBLEPTRIS_VERSION = "1.9.3"
|
|
12
12
|
|
|
13
13
|
CMAKE_FLAGS = %w[
|
|
14
14
|
-DCMAKE_BUILD_TYPE=Release
|
data/lib/leptris/version.rb
CHANGED
data/lib/leptris/xml/document.rb
CHANGED
|
@@ -311,6 +311,21 @@ class Leptris::XML::Document
|
|
|
311
311
|
@freed.state == :freed || @c_ptr.nil?
|
|
312
312
|
end
|
|
313
313
|
|
|
314
|
+
# Document-level comments — parsed <!-- ... --> outside the
|
|
315
|
+
# root element, prolog then epilog, in document order (the
|
|
316
|
+
# companion reader to #processing_instructions; libleptris
|
|
317
|
+
# 1.9.3, upstream #578). Version-memoized like the PI list.
|
|
318
|
+
def comments
|
|
319
|
+
return @comments if @comments_version == @version
|
|
320
|
+
count = Leptris::XML::FFI.leptris_document_comment_count(@c_ptr)
|
|
321
|
+
result = Array.new(count) do |i|
|
|
322
|
+
Leptris::XML::FFI.leptris_document_comment_content(@c_ptr, i)
|
|
323
|
+
end
|
|
324
|
+
@comments = result
|
|
325
|
+
@comments_version = @version
|
|
326
|
+
result
|
|
327
|
+
end
|
|
328
|
+
|
|
314
329
|
# The thread-global last-failure [line, column] (1-based), or nil
|
|
315
330
|
# when no error is recorded — the position companion to
|
|
316
331
|
# Document#last_error; populated by recover parses.
|
data/lib/leptris/xml/ffi.rb
CHANGED
|
@@ -42,6 +42,7 @@ module Leptris
|
|
|
42
42
|
typedef :pointer, :leptris_xpath_result
|
|
43
43
|
typedef :pointer, :leptris_xpath_ns_set
|
|
44
44
|
typedef :pointer, :leptris_xpath_compiled
|
|
45
|
+
typedef :pointer, :leptris_xslt
|
|
45
46
|
typedef :pointer, :leptris_pull_parser
|
|
46
47
|
typedef :pointer, :leptris_iterparse
|
|
47
48
|
typedef :pointer, :leptris_xpath_var_set
|
|
@@ -124,6 +125,13 @@ module Leptris
|
|
|
124
125
|
[:leptris_document, :size_t], :string
|
|
125
126
|
attach_function :leptris_document_add_pi,
|
|
126
127
|
[:leptris_document, :string, :string], :pointer
|
|
128
|
+
# Document-level comments (libleptris 1.9.3, #578): parsed
|
|
129
|
+
# <!-- ... --> outside the root, prolog then epilog, in
|
|
130
|
+
# document order. Read-only surface (no add_comment yet).
|
|
131
|
+
attach_function :leptris_document_comment_count,
|
|
132
|
+
[:leptris_document], :size_t
|
|
133
|
+
attach_function :leptris_document_comment_content,
|
|
134
|
+
[:leptris_document, :size_t], :string
|
|
127
135
|
# Options-struct parse (v1.6.0): supersedes the flags variants;
|
|
128
136
|
# the flags path remains bound for compatibility.
|
|
129
137
|
attach_function :leptris_parse_string_ex,
|
|
@@ -478,7 +486,11 @@ module Leptris
|
|
|
478
486
|
attach_function :leptris_xpath_compiled_eval_vars,
|
|
479
487
|
[:leptris_xpath_compiled, :leptris_document, :leptris_element,
|
|
480
488
|
:leptris_xpath_var_set], :leptris_xpath_result
|
|
489
|
+
# Source text of a compiled expression (owned by the handle).
|
|
490
|
+
attach_function :leptris_xpath_compiled_text,
|
|
491
|
+
[:leptris_xpath_compiled], :string
|
|
481
492
|
attach_function :leptris_xpath_compiled_free,
|
|
493
|
+
|
|
482
494
|
[:leptris_xpath_compiled], :void
|
|
483
495
|
|
|
484
496
|
attach_function :leptris_sax_parse,
|
|
@@ -539,7 +551,23 @@ module Leptris
|
|
|
539
551
|
[:leptris_element, :pointer, :size_t, :pointer, :pointer], :size_t
|
|
540
552
|
attach_function :leptris_document_save_file,
|
|
541
553
|
[:leptris_document, :string, :pointer], :leptris_status
|
|
554
|
+
# XSLT 1.0 engine (libleptris 1.9.1): compile once, apply many.
|
|
555
|
+
attach_function :leptris_xslt_parse,
|
|
556
|
+
[:string, :size_t], :leptris_xslt
|
|
557
|
+
attach_function :leptris_xslt_parse_file,
|
|
558
|
+
[:string], :leptris_xslt
|
|
559
|
+
attach_function :leptris_xslt_free,
|
|
560
|
+
[:leptris_xslt], :void
|
|
561
|
+
# Result tree is a document (free with document_free); errors
|
|
562
|
+
# surface via document_last_error on NULL.
|
|
563
|
+
attach_function :leptris_xslt_apply,
|
|
564
|
+
[:leptris_xslt, :leptris_document], :leptris_document
|
|
565
|
+
# apply + serialize in one call, keeping top-level text nodes
|
|
566
|
+
# and result fragments the tree API would flatten.
|
|
567
|
+
attach_function :leptris_xslt_apply_string,
|
|
568
|
+
[:leptris_xslt, :leptris_document], :pointer
|
|
542
569
|
attach_function :leptris_c14n_canonicalize,
|
|
570
|
+
|
|
543
571
|
[:leptris_document, :int, :int], :pointer
|
|
544
572
|
attach_function :leptris_c14n_canonicalize_subtree,
|
|
545
573
|
[:leptris_element, :int, :int], :pointer
|
|
@@ -648,6 +676,7 @@ module Leptris
|
|
|
648
676
|
leptris_status_string leptris_last_error
|
|
649
677
|
leptris_document_last_error leptris_document_encoding
|
|
650
678
|
leptris_document_pi_target leptris_document_pi_data
|
|
679
|
+
leptris_document_comment_content
|
|
651
680
|
leptris_element_name leptris_element_text leptris_element_prefix
|
|
652
681
|
leptris_element_namespace
|
|
653
682
|
leptris_element_attribute leptris_element_attribute_ns
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ffi"
|
|
4
|
+
|
|
5
|
+
module Leptris::XML::XSLT
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
def parse(stylesheet_xml)
|
|
9
|
+
Stylesheet.parse(stylesheet_xml)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def parse_file(path)
|
|
13
|
+
Stylesheet.parse_file(path)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# A compiled XSLT 1.0 stylesheet (libleptris 1.9.1): the stylesheet
|
|
17
|
+
# parses ONCE into an immutable instruction forest — patterns to
|
|
18
|
+
# XPath ASTs, selects through the compiled-XPath path — then applies
|
|
19
|
+
# to any number of documents with no re-parsing.
|
|
20
|
+
#
|
|
21
|
+
# style = Leptris::XML::XSLT.parse(<<~XSL)
|
|
22
|
+
# <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
|
23
|
+
# <xsl:template match="/"><out><xsl:value-of select="count(//item)"/></out></xsl:template>
|
|
24
|
+
# </xsl:stylesheet>
|
|
25
|
+
# XSL
|
|
26
|
+
# style.apply_to(doc) # => result Document (queryable tree)
|
|
27
|
+
# style.serialize(doc) # => String (fragments and top-level
|
|
28
|
+
# # text nodes preserved)
|
|
29
|
+
#
|
|
30
|
+
class Stylesheet
|
|
31
|
+
# GC-managed compiled handle.
|
|
32
|
+
class Handle < ::FFI::AutoPointer
|
|
33
|
+
def self.release(ptr)
|
|
34
|
+
Leptris::XML::FFI.leptris_xslt_free(ptr)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Compile a stylesheet. Raises XPathError on a stylesheet syntax
|
|
39
|
+
# error (detail on the thread-global last error).
|
|
40
|
+
def self.parse(stylesheet_xml)
|
|
41
|
+
raw = Leptris::XML::FFI.leptris_xslt_parse(
|
|
42
|
+
stylesheet_xml.to_s, stylesheet_xml.to_s.bytesize)
|
|
43
|
+
if raw.null?
|
|
44
|
+
raise Leptris::XML::XPathError,
|
|
45
|
+
"stylesheet parse failed: #{Leptris::XML::FFI.leptris_last_error}"
|
|
46
|
+
end
|
|
47
|
+
new(Handle.new(raw))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Compile from a file. Resolves §2.7 embedded stylesheets
|
|
51
|
+
# (xml-stylesheet PI with an href="#id" fragment) when the file's
|
|
52
|
+
# root is not itself a stylesheet.
|
|
53
|
+
def self.parse_file(path)
|
|
54
|
+
raw = Leptris::XML::FFI.leptris_xslt_parse_file(path.to_s)
|
|
55
|
+
if raw.null?
|
|
56
|
+
raise Leptris::XML::XPathError,
|
|
57
|
+
"stylesheet parse failed: #{Leptris::XML::FFI.leptris_last_error}"
|
|
58
|
+
end
|
|
59
|
+
new(Handle.new(raw))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def initialize(handle)
|
|
63
|
+
@handle = handle
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Apply to +document+ (not modified) and return the result tree
|
|
67
|
+
# as an owning Document — query it with xpath/css like any other.
|
|
68
|
+
def apply_to(document)
|
|
69
|
+
raw = Leptris::XML::FFI.leptris_xslt_apply(@handle, document.c_ptr)
|
|
70
|
+
if raw.null?
|
|
71
|
+
raise Leptris::XML::XPathError,
|
|
72
|
+
"transform failed: #{document.last_error || Leptris::XML::FFI.leptris_last_error}"
|
|
73
|
+
end
|
|
74
|
+
Leptris::XML::Document.wrap(raw)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Apply and serialize in one call — keeps top-level text nodes and
|
|
78
|
+
# result fragments that the tree API would flatten.
|
|
79
|
+
def serialize(document)
|
|
80
|
+
str_ptr = Leptris::XML::FFI.leptris_xslt_apply_string(
|
|
81
|
+
@handle, document.c_ptr)
|
|
82
|
+
Leptris::XML::FFI.read_owned_string(str_ptr)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
data/lib/leptris/xml.rb
CHANGED
|
@@ -22,6 +22,7 @@ module Leptris
|
|
|
22
22
|
autoload :Serialization, "leptris/xml/serialization"
|
|
23
23
|
autoload :SAX, "leptris/xml/sax"
|
|
24
24
|
autoload :XPath, "leptris/xml/xpath"
|
|
25
|
+
autoload :XSLT, "leptris/xml/xslt"
|
|
25
26
|
autoload :Pull, "leptris/xml/pull"
|
|
26
27
|
autoload :Iterparse, "leptris/xml/iterparse"
|
|
27
28
|
|
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.
|
|
4
|
+
version: 1.9.19
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -103,6 +103,7 @@ files:
|
|
|
103
103
|
- lib/leptris/xml/serialization.rb
|
|
104
104
|
- lib/leptris/xml/text.rb
|
|
105
105
|
- lib/leptris/xml/xpath.rb
|
|
106
|
+
- lib/leptris/xml/xslt.rb
|
|
106
107
|
homepage: https://github.com/leptris/leptris-ruby
|
|
107
108
|
licenses:
|
|
108
109
|
- MIT
|