moxml 0.5.102 → 0.5.104

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: d182614a13bd3934c6d6dc1bb9b137015dc1daa124aeac24df40246ea3109103
4
- data.tar.gz: 51d96b5f964b185772d4378913c5e48e4775c41cf5fd1a3e5cf942576fa33183
3
+ metadata.gz: 3bbf00c0bac03066dd77a5bb5f952ac786a893d51dd0b18365a67500bdad7a15
4
+ data.tar.gz: 79d1609f628fcf8b69044ee5a9c990ae347cf0ff11c8b5e2ed2f812bee80ae0e
5
5
  SHA512:
6
- metadata.gz: f4e9ae7331917e4fb295aa541028cb233d889127e4e32982d24ad1d696df668f52d223b70a1c6f2e96360f72138abf36a2eb055f15b9f48c069cb7b421191cfe
7
- data.tar.gz: '0362854ca321c56e434a0f030232088d200d948dfe231c2d2cf4d2017c3af7316610e3f18ece3ca85a9a9a2c0d98f431c9f3bb465f186fe39ae23b63ea2e9a7b'
6
+ metadata.gz: 756a39e9fc200fc4b1a9880f820489684169c3206739d02bb44aad987bfa9b20140a65ae923b29745609fd47407927be9d369f4ed4a64d4129e0f3168f3aec56
7
+ data.tar.gz: 6efc68d693d8c3b12f90ee4bfed2bf801162b89c7f3a5b0b1fc21eed45183a1ea962d4f2916a30932314208cd5099245a4977a0020b28892a83f4f019b40e03e
data/README.adoc CHANGED
@@ -1283,7 +1283,8 @@ reproduce:
1283
1283
  [source,shell]
1284
1284
  ----
1285
1285
  # One-time setup: install ragel + ruby-ll so the forks' gitignored
1286
- # generated lexer/parser sources can be produced.
1286
+ # generated lexer/parser sources can be produced. ruby-ll must be
1287
+ # installed outside the bundle: vendor:prepare runs it outside Bundler.
1287
1288
  gem install ruby-ll --no-document
1288
1289
  # (Install ragel via your package manager, e.g. apt-get install ragel
1289
1290
  # or brew install ragel.)
data/Rakefile CHANGED
@@ -88,13 +88,17 @@ namespace :vendor do
88
88
  "#{ruby_ll}/lib/ll/parser.rll"],
89
89
  ]
90
90
 
91
- generators.each do |cmd, output, source|
92
- if File.exist?(output) && File.mtime(output) >= File.mtime(source)
93
- next
91
+ # Under bundle exec, ruby-ll resolves to the vendored opal-ruby-ll
92
+ # binstub, which needs the not-yet-compiled libll.
93
+ Bundler.with_unbundled_env do
94
+ generators.each do |cmd, output, source|
95
+ if File.exist?(output) && File.mtime(output) >= File.mtime(source)
96
+ next
97
+ end
98
+
99
+ FileUtils.mkdir_p(File.dirname(output))
100
+ sh cmd
94
101
  end
95
-
96
- FileUtils.mkdir_p(File.dirname(output))
97
- sh cmd
98
102
  end
99
103
  end
100
104
 
@@ -507,7 +507,37 @@ module Moxml
507
507
  raise Moxml::XsltError, "stylesheet compile failed: #{e.message}"
508
508
  end
509
509
 
510
+ # Bindings >= 1.9.290.0 thread top-level xsl:param overrides
511
+ # (leptris#1478); older bindings raise the typed error (the
512
+ # #360 face gap, face-probed so a misrelease degrades instead
513
+ # of NoMethodError-ing — the 1.9.199.0 lesson).
514
+ NATIVE_XSLT_PARAMS =
515
+ NATIVE_READ_LAYER &&
516
+ Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.290.0") &&
517
+ ::Leptris::XML::XSLT::Stylesheet.instance_method(:apply_to)
518
+ .parameters.size > 1
519
+
520
+ # The seam contract passes the libxslt flat quoted array; the
521
+ # binding wants the raw name => value hash (leptris#1478
522
+ # matches nokogiri's quoted-string semantics internally).
523
+ def self.flat_params_to_hash(params)
524
+ return params if params.is_a?(Hash)
525
+ return {} if params.nil? || params.empty?
526
+
527
+ params.each_slice(2).to_h { |name, value| [name, unquote_param(value)] }
528
+ end
529
+
530
+ def self.unquote_param(value)
531
+ str = value.to_s
532
+ str.start_with?("'") && str.end_with?("'") && str.length >= 2 ? str[1..-2] : str
533
+ end
534
+
510
535
  def self.xslt_apply_document(sheet, document_native, params)
536
+ if NATIVE_XSLT_PARAMS
537
+ return sheet.apply_to(document_native,
538
+ params: flat_params_to_hash(params))
539
+ end
540
+
511
541
  assert_xslt_no_params(params)
512
542
  sheet.apply_to(document_native)
513
543
  rescue ::Leptris::XML::XPathError => e
@@ -515,6 +545,11 @@ module Moxml
515
545
  end
516
546
 
517
547
  def self.xslt_apply_string(sheet, document_native, params)
548
+ if NATIVE_XSLT_PARAMS
549
+ return sheet.serialize(document_native,
550
+ params: flat_params_to_hash(params))
551
+ end
552
+
518
553
  assert_xslt_no_params(params)
519
554
  sheet.serialize(document_native)
520
555
  rescue ::Leptris::XML::XPathError => e
@@ -525,8 +560,9 @@ module Moxml
525
560
  return if params.nil? || params.empty?
526
561
 
527
562
  raise Moxml::XsltError,
528
- "XSLT params are not threaded by the leptris engine yet " \
529
- "(leptris-ruby#360); pass an empty params hash"
563
+ "XSLT params are not threaded by this binding " \
564
+ "(leptris-ruby#360); upgrade to leptris >= 1.9.290.0 or " \
565
+ "pass an empty params hash"
530
566
  end
531
567
 
532
568
  def self.native_c14n_byte_safe?
@@ -1972,7 +2008,16 @@ module Moxml
1972
2008
  )
1973
2009
  end
1974
2010
  else
1975
- node.unlink
2011
+ begin
2012
+ node.unlink
2013
+ rescue ::Leptris::XML::Error => e
2014
+ # "Not found" from unlink means the node is already in
2015
+ # no parent list — detached (replace, children=, engine
2016
+ # paths the wrapper layer cannot clear links for).
2017
+ # Nokogiri's unlink is a no-op there; match it instead
2018
+ # of crashing cleanup passes.
2019
+ raise unless e.message.include?("Not found")
2020
+ end
1976
2021
  end
1977
2022
  end
1978
2023
 
@@ -2016,11 +2061,23 @@ module Moxml
2016
2061
  new_node
2017
2062
  end
2018
2063
 
2064
+ NATIVE_APPEND_CHILDREN =
2065
+ NATIVE_READ_LAYER &&
2066
+ Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.290.0")
2067
+
2019
2068
  def replace_children(node, new_children)
2020
2069
  if NATIVE_READ_LAYER
2021
2070
  node = to_binding(node)
2022
2071
  new_children = new_children.map { |child| to_binding(child) }
2023
2072
  end
2073
+ if NATIVE_APPEND_CHILDREN && !new_children.empty?
2074
+ # One crossing to clear, one to append N (leptris-ruby#366's
2075
+ # bulk face; the old path paid an append crossing per child).
2076
+ ::Leptris::XML::FFI.check_status(
2077
+ ::Leptris::XML::FFI.leptris_element_remove_children(node.c_ptr),
2078
+ )
2079
+ return node.append_children(new_children)
2080
+ end
2024
2081
  node.children = new_children
2025
2082
  end
2026
2083
 
data/lib/moxml/node.rb CHANGED
@@ -254,6 +254,11 @@ module Moxml
254
254
  context.bump_children_generation
255
255
  invalidate_parent_children_cache!
256
256
  adapter.remove(@native)
257
+ # The wrapper-side parent link dies with the attach — leaving it
258
+ # stale makes a later #remove's guard trust a parent that no
259
+ # longer exists and push an already-detached node into the
260
+ # engine (leptris: "Not found").
261
+ @parent_node = nil
257
262
  invalidate_children_cache!
258
263
  # The detached subtree left its declaring ancestors behind
259
264
  invalidate_namespace_cache!
@@ -269,6 +274,9 @@ module Moxml
269
274
  node = prepare_node(node)
270
275
  invalidate_parent_children_cache!
271
276
  adapter.replace(@native, node.native)
277
+ # Self is detached by the replace — drop the stale parent link
278
+ # (see #remove).
279
+ @parent_node = nil
272
280
  invalidate_children_cache!
273
281
  self
274
282
  end
data/lib/moxml/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Moxml
4
- VERSION = "0.5.102"
4
+ VERSION = "0.5.104"
5
5
  end
@@ -383,4 +383,17 @@ RSpec.describe "Nokogiri-compatible node sugar" do
383
383
  expect(doc.root.inner_xml).to eq("<a>x</a><b/>")
384
384
  end
385
385
  end
386
+
387
+ describe "Node#remove after replace with a parent link" do
388
+ it "is a no-op, not an engine error (stale wrapper parent link)" do
389
+ doc = Moxml.parse("<r><term><p>a</p><note>n</note></term></r>")
390
+ # children walks are parent-aware: the wrapper carries @parent_node
391
+ p_node = doc.at("//term").children.find { |c| c.name == "p" }
392
+ t = doc.create_element("definition")
393
+ p_node.replace(t)
394
+ expect { t << p_node.remove }.not_to raise_error
395
+ expect(doc.at("//term/definition/p")).not_to be_nil
396
+ expect(doc.at("//term/definition/p").text).to eq("a")
397
+ end
398
+ end
386
399
  end
@@ -4,8 +4,9 @@ require "spec_helper"
4
4
 
5
5
  # The Moxml::XSLT contract: compile once, apply many. Only engines
6
6
  # with an XSLT processor implement it (nokogiri/libxslt; leptris
7
- # covering XSLT 1.0-3.0). leptris does not thread top-level params
8
- # yet (leptris-ruby#360) — non-empty params raise Moxml::XsltError.
7
+ # covering XSLT 1.0-3.0). Bindings >= 1.9.290.0 thread top-level
8
+ # params (leptris#1478); older bindings raise Moxml::XsltError
9
+ # citing leptris-ruby#360.
9
10
  SHEET_COUNT = <<~XSL
10
11
  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
11
12
  <xsl:template match="/"><out><xsl:value-of select="count(//i)"/></out></xsl:template>
@@ -77,10 +78,22 @@ RSpec.describe "Moxml::XSLT" do
77
78
  expect(sheet.apply_to_string(doc)).to include("plain text result")
78
79
  end
79
80
 
80
- it "raises XsltError on non-empty params (leptris-ruby#360)" do
81
- sheet = ctx.xslt(SHEET_COUNT)
82
- expect { sheet.apply_to(doc, params: { "n" => "7" }) }
83
- .to raise_error(Moxml::XsltError, /params.*#360/)
81
+ if Gem::Version.new(Leptris::VERSION) >= Gem::Version.new("1.9.290.0")
82
+ it "threads top-level params (leptris#1478)" do
83
+ sheet = ctx.xslt(<<~XSL)
84
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
85
+ <xsl:param name="n" select="'0'"/>
86
+ <xsl:template match="/"><out><xsl:value-of select="$n"/></out></xsl:template>
87
+ </xsl:stylesheet>
88
+ XSL
89
+ expect(sheet.apply_to_string(doc, params: { "n" => "7" })).to include("7")
90
+ end
91
+ else
92
+ it "raises XsltError on non-empty params (leptris-ruby#360)" do
93
+ sheet = ctx.xslt(SHEET_COUNT)
94
+ expect { sheet.apply_to(doc, params: { "n" => "7" }) }
95
+ .to raise_error(Moxml::XsltError, /params.*#360/)
96
+ end
84
97
  end
85
98
 
86
99
  it "reports support" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moxml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.102
4
+ version: 0.5.104
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-02 00:00:00.000000000 Z
11
+ date: 2026-10-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  Moxml is a unified XML manipulation library that provides a common API