leptris 1.2.0 → 1.2.1

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: 28a6d0b01b14207e6a928eead2f38f84bf2dda03b9c7ae4a3c6bcc3163f2760d
4
- data.tar.gz: e23962a817090c8707dc691fe58276f25da7075e1b0b64bb1fa39774cd113d4e
3
+ metadata.gz: e9d9e951ee8e7b15451e02933c6e5e80d6cb78fa970ff4411153ec1358c50ab1
4
+ data.tar.gz: 5aab53987963478c27bb0d9bfe96e804672dcc6b7da1842cc3422f9e0b91c235
5
5
  SHA512:
6
- metadata.gz: 83e9f30fd09ded2f909d651423db46be8a6baca9f39f310e9b8c3632f5fd7cd5627d193cd57c80d6191a2c00145858b87d9454a72df12e96a28fbd928864a663
7
- data.tar.gz: 5991c97a7ea5b8a3462c62492fd70808f4094d2758525ce2ec6ac47a9ffe61bb318c71d1999c95081e5e48ce10cc98d9e671ea8c52400c3a90b01e4f9a5b3ce1
6
+ metadata.gz: 7de27428d6e469b405889481a78bdbe1680d28e4b8c4bd2041ccfb49dd3b9a620359f5d66a4bc4f4573e16c332916348cf4313bedbb1c5d1876cf08cb64b243e
7
+ data.tar.gz: c71f63da347773adfd341782dd10326ff5993c673080e63554013eed453137014f76f2b4a0474b9fa452c5009f573d4d65f01213822016e296735a0a1eea30e3
data/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ All notable changes to Leptris will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.2.1] - 2026-08-23
9
+
10
+ Completes the libleptris 1.2.0 public surface in the binding.
11
+
12
+ ### Added
13
+
14
+ - **Namespace-bound XPath**: `doc.xpath("//p:title", "p" => "urn:p")`
15
+ (Nokogiri parity) — expression prefixes now resolve to caller-supplied
16
+ URIs regardless of the prefixes the document declared, via
17
+ `leptris_xpath_ns_set_new/_add/_free` + `leptris_xpath_eval_ns`. The
18
+ binding set is built per call and freed under `ensure`. Previously
19
+ the trailing namespace hash was silently ignored.
20
+ - `leptris_error_message` / `leptris_last_error` bound; the status seam
21
+ and parse errors now append the library's last-error detail when
22
+ present (best-effort: it is a library-global string).
23
+
8
24
  ## [1.2.0] - 2026-08-23
9
25
 
10
26
  Lockstep with libleptris 1.2.0.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leptris
4
- VERSION = "1.2.0"
4
+ VERSION = "1.2.1"
5
5
  end
@@ -50,7 +50,8 @@ class Leptris::XML::Document
50
50
  if raw.null?
51
51
  status = status_ptr.read_int
52
52
  raise Leptris::XML::ParseError,
53
- "leptris_parse_string failed (status=#{status})"
53
+ "leptris_parse_string failed (status=#{status}): " +
54
+ Leptris::XML::FFI.status_message(status)
54
55
  end
55
56
  wrap(raw)
56
57
  end
@@ -23,6 +23,7 @@ module Leptris
23
23
  typedef :pointer, :leptris_attribute
24
24
  typedef :pointer, :leptris_doctype
25
25
  typedef :pointer, :leptris_xpath_result
26
+ typedef :pointer, :leptris_xpath_ns_set
26
27
  typedef :pointer, :leptris_xpath_var_set
27
28
  typedef :pointer, :leptris_sax_parser
28
29
  typedef :int, :leptris_status
@@ -365,6 +366,18 @@ module Leptris
365
366
  attach_function :leptris_xpath_variable_set_string,
366
367
  [:leptris_xpath_var_set, :string, :string], :leptris_status
367
368
 
369
+ # Namespace-bound XPath (v1.2.0): expression prefixes resolve to
370
+ # caller-supplied URIs regardless of the document's declarations.
371
+ attach_function :leptris_xpath_ns_set_new,
372
+ [], :leptris_xpath_ns_set
373
+ attach_function :leptris_xpath_ns_set_free,
374
+ [:leptris_xpath_ns_set], :void
375
+ attach_function :leptris_xpath_ns_set_add,
376
+ [:leptris_xpath_ns_set, :string, :string], :leptris_status
377
+ attach_function :leptris_xpath_eval_ns,
378
+ [:leptris_document, :leptris_element, :string, :leptris_xpath_ns_set],
379
+ :leptris_xpath_result
380
+
368
381
  attach_function :leptris_sax_parse,
369
382
  [:string, :size_t, :pointer, :pointer], :int
370
383
  attach_function :leptris_sax_parser_create,
@@ -419,6 +432,8 @@ module Leptris
419
432
  attach_function :leptris_document_set_allocators,
420
433
  [:leptris_document, :pointer, :pointer], :leptris_status
421
434
  attach_function :leptris_status_string, [:leptris_status], :string
435
+ attach_function :leptris_error_message, [:leptris_status], :string
436
+ attach_function :leptris_last_error, [], :string
422
437
 
423
438
  LEPTRIS_OK = 0
424
439
  LEPTRIS_ERROR_MEMORY = -1
@@ -467,13 +482,22 @@ module Leptris
467
482
  ptr.read_string.tap { leptris_free_string(ptr) }
468
483
  end
469
484
 
470
- # Single status seam: turns a C status code into a Ruby error.
485
+ # Single status seam: turns a C status code into a Ruby error,
486
+ # appending the library's last-error detail when present. The
487
+ # detail is a library-global string, so it can only be treated
488
+ # as best-effort context.
471
489
  def self.check_status(status)
472
490
  unless status == LEPTRIS_OK
473
- raise Leptris::XML::Error, leptris_status_string(status)
491
+ raise Leptris::XML::Error, status_message(status)
474
492
  end
475
493
  status
476
494
  end
495
+
496
+ def self.status_message(status)
497
+ base = leptris_status_string(status).to_s
498
+ detail = leptris_last_error.to_s
499
+ detail.empty? ? base : "#{base} (#{detail})"
500
+ end
477
501
  end
478
502
  end
479
503
  end
@@ -2,14 +2,19 @@
2
2
 
3
3
  module Leptris::XML::Searchable
4
4
  def xpath(*paths)
5
- handler, _ns, _vars = parse_search_args(paths)
5
+ handler, ns, _vars = parse_search_args(paths)
6
6
  raise ArgumentError, "custom XPath handlers not supported" if handler
7
7
  expr = paths.join(" | ")
8
8
 
9
9
  doc_ptr = is_a?(Leptris::XML::Document) ? c_ptr : document.c_ptr
10
10
  context_ptr = is_a?(Leptris::XML::Document) ? nil : c_ptr
11
11
 
12
- result_ptr = Leptris::XML::FFI.leptris_xpath_eval(doc_ptr, context_ptr, expr)
12
+ result_ptr =
13
+ if ns && !ns.empty?
14
+ xpath_eval_with_namespaces(doc_ptr, context_ptr, expr, ns)
15
+ else
16
+ Leptris::XML::FFI.leptris_xpath_eval(doc_ptr, context_ptr, expr)
17
+ end
13
18
  if result_ptr.null?
14
19
  raise Leptris::XML::XPathError,
15
20
  Leptris::XML::FFI.leptris_status_string(Leptris::XML::FFI::LEPTRIS_ERROR_XPATH)
@@ -50,6 +55,22 @@ module Leptris::XML::Searchable
50
55
 
51
56
  protected
52
57
 
58
+ # Builds a caller-owned namespace binding set, evaluates via
59
+ # leptris_xpath_eval_ns, and frees the set regardless of outcome.
60
+ def xpath_eval_with_namespaces(doc_ptr, context_ptr, expr, ns)
61
+ set = Leptris::XML::FFI.leptris_xpath_ns_set_new
62
+ begin
63
+ ns.each do |prefix, uri|
64
+ Leptris::XML::FFI.check_status(
65
+ Leptris::XML::FFI.leptris_xpath_ns_set_add(
66
+ set, prefix.to_s, uri.to_s))
67
+ end
68
+ Leptris::XML::FFI.leptris_xpath_eval_ns(doc_ptr, context_ptr, expr, set)
69
+ ensure
70
+ Leptris::XML::FFI.leptris_xpath_ns_set_free(set)
71
+ end
72
+ end
73
+
53
74
  def parse_search_args(args)
54
75
  handler = args.find { |a| !a.is_a?(String) && !a.is_a?(Hash) && !a.is_a?(Symbol) }
55
76
  args = args - [handler] if handler
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.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.