moxml 0.5.54 → 0.5.56

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: ba51d35ca414232eb04fafd976a2f5d24b2f43fff1b0e4c4a69147162da324c7
4
- data.tar.gz: 73df7c7f9da2ff33e4ab2d06f3b56b29b0a09e4784c78eb9907d3ec15f82c234
3
+ metadata.gz: 30ad2e1e2f91d4d31eb467d5a2beee85bc3112585d6383bf37b0a66e6d1bca40
4
+ data.tar.gz: ff7ef79362aa97205ce0b16c7161a9c5d7f25720a3794a967cfb9dbf4afa3a5e
5
5
  SHA512:
6
- metadata.gz: c30f3bef444d6a6da7416e5ee5493c5656a6bbca1f28c9d504c9405b3be54b083eb5bf9a218ed1e0ac1cb94b3551678c028adadf667fcc7b15b50a2e403341ab
7
- data.tar.gz: cef805979f7168ec08ce5dc80624e74a2bef27225233d1389862d84b6d4d9cea56806b50a6231e078a626ba488ce90668e0fd8b40ad6cf11a650a3b154c24041
6
+ metadata.gz: 580fe3a426ebf5d37017fa727527518a76e2221c34543e58c22a08c41d92300e23dbc8bfc391d7f39b09ffd9b78921b1434dc2a51154af4e507e2be409935e08
7
+ data.tar.gz: 15cbb5eb0ca6795715aea82f2b05e017c6d5726c0b6e814713955aa4da0c7e045b21afd9304b7fd1bfdc1cc685f9b45ee743d80f5e06025770218ae383d76060
data/Gemfile CHANGED
@@ -9,7 +9,7 @@ gemspec
9
9
  gem "benchmark"
10
10
  gem "benchmark-ips"
11
11
  gem "get_process_mem"
12
- gem "leptris", "~> 1.9.174.1"
12
+ gem "leptris", "~> 1.9.174"
13
13
  gem "libxml-ruby", ">= 5.0"
14
14
  gem "nokogiri", "~> 1.18"
15
15
  gem "openssl", "~> 3.0"
@@ -141,6 +141,37 @@ module Moxml
141
141
  nil
142
142
  end
143
143
 
144
+ # Prefixed-attribute value fast path: adapters whose engine
145
+ # resolves expanded-name (uri, local) lookups natively answer
146
+ # the value here; others fall back to the resolver's
147
+ # attribute-list match. Capability probe, not a class
148
+ # identity check — Moxml::Adapter::Leptris is only defined
149
+ # once that adapter loads (issue #242).
150
+ def expanded_attr_reads?
151
+ false
152
+ end
153
+
154
+ def expanded_attr_value(_element, _uri, _local)
155
+ nil
156
+ end
157
+
158
+ # Engine-side inclusive C14N delegation: adapters whose
159
+ # engine canonicalizes byte-identically to the Ruby reference
160
+ # answer the String here; others (and unsupported shapes)
161
+ # return nil and the Ruby reference runs. Capability probe —
162
+ # same reasoning as expanded_attr_reads? (issue #242).
163
+ def native_inclusive10(_native)
164
+ nil
165
+ end
166
+
167
+ # Source position {line, col_start, col_end} for a node where
168
+ # the engine exposes it (leptris 1.9.181+ source_position);
169
+ # nil elsewhere and for nodes without a position (created
170
+ # nodes answer zeros upstream — pass those through as-is).
171
+ def source_position(_native)
172
+ nil
173
+ end
174
+
144
175
  # Subtree walk capability: an adapter with a C-side pre-order
145
176
  # traversal (leptris >= 1.9.174.6 visit) walks descendants in
146
177
  # one dispatch; nil keeps the recursive children walk. Self
@@ -103,6 +103,12 @@ module Moxml
103
103
  NN_ADD_CHILD = NN.instance_method(:add_child)
104
104
  end
105
105
 
106
+ # 1.9.181 (lockstep): Node#source_position — {line, col_start,
107
+ # col_end} from the engine's source-position API (upstream
108
+ # #1124); created nodes report zeros.
109
+ NATIVE_SOURCE_POSITION =
110
+ Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.181")
111
+
106
112
  # Entity-reference preservation (leptris-ruby#212 / upstream
107
113
  # #1094): 1.9.177 ships ParseOptions.keep_entity_refs plus
108
114
  # first-class EntityReference nodes — the marker machinery
@@ -463,8 +469,27 @@ module Moxml
463
469
  # engine — the same match rule as the resolver (xmlns
464
470
  # declarations invisible, no-namespace never matches a
465
471
  # prefixed name), without materializing the attribute list.
472
+ def expanded_attr_reads?
473
+ true
474
+ end
475
+
476
+ def native_inclusive10(native)
477
+ return nil unless native_c14n_byte_safe?
478
+
479
+ to_binding(native).canonicalize(
480
+ ::Leptris::XML::FFI::C14N_1_0, nil,
481
+ mode: ::Leptris::XML::FFI::C14N_MODE_CANONICAL
482
+ )
483
+ end
484
+
466
485
  def expanded_attr_value(element, uri, local)
467
- element.attribute_ns(uri, local)
486
+ # Bridge first: identity-mode wrappers hand a NativeNode
487
+ # (no attribute_ns); binding elements pass through as-is.
488
+ # The class-receiver is_a? this method replaced was always
489
+ # false — element.adapter IS the adapter class — so the
490
+ # branch sat dead since identity mode and the binding-only
491
+ # assumption went unnoticed (issue #242).
492
+ to_binding(element).attribute_ns(uri, local)
468
493
  end
469
494
 
470
495
  # Fast bare-name read: the binding call plus marker
@@ -1219,6 +1244,12 @@ module Moxml
1219
1244
  r
1220
1245
  end
1221
1246
 
1247
+ def source_position(node)
1248
+ return nil unless NATIVE_SOURCE_POSITION
1249
+
1250
+ to_binding(node).source_position
1251
+ end
1252
+
1222
1253
  def line_number(node)
1223
1254
  if NATIVE_MUTATIONS_COHERENT &&
1224
1255
  node.is_a?(::Leptris::XML::NativeNode)
@@ -42,9 +42,7 @@ module Moxml
42
42
  return nil if uri.nil?
43
43
 
44
44
  adapter = element.adapter
45
- if adapter.is_a?(Moxml::Adapter::Leptris)
46
- return adapter.expanded_attr_value(element.native, uri, local)
47
- end
45
+ return adapter.expanded_attr_value(element.native, uri, local) if adapter.expanded_attr_reads?
48
46
 
49
47
  attr = resolve(element, name)
50
48
  attr&.value
data/lib/moxml/c14n.rb CHANGED
@@ -62,14 +62,7 @@ module Moxml
62
62
  return nil if with_comments || !inclusive_namespaces.empty?
63
63
  return nil unless algorithm_shape_inclusive10?(node_or_xml)
64
64
 
65
- adapter = node_or_xml.context.config.adapter
66
- return nil unless adapter == Moxml::Adapter::Leptris &&
67
- Moxml::Adapter::Leptris.native_c14n_byte_safe?
68
-
69
- Moxml::Adapter::Leptris.to_binding(node_or_xml.native).canonicalize(
70
- ::Leptris::XML::FFI::C14N_1_0, nil,
71
- mode: ::Leptris::XML::FFI::C14N_MODE_CANONICAL
72
- )
65
+ node_or_xml.context.config.adapter.native_inclusive10(node_or_xml.native)
73
66
  end
74
67
 
75
68
  def self.algorithm_shape_inclusive10?(node_or_xml)
data/lib/moxml/node.rb CHANGED
@@ -402,6 +402,14 @@ module Moxml
402
402
  adapter.line_number(@native)
403
403
  end
404
404
 
405
+ # {line, col_start, col_end} where the engine exposes source
406
+ # positions (leptris 1.9.181+); nil elsewhere. Created nodes
407
+ # answer zeros upstream — distinguishable from nil by callers
408
+ # that care.
409
+ def source_position
410
+ adapter.source_position(@native)
411
+ end
412
+
405
413
  # Content-defined Merkle digest of this subtree (issue #173,
406
414
  # companion to leptris#869): a u64 Integer where the backend
407
415
  # computes one, nil everywhere else. Consumers gate on nil and
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.54"
4
+ VERSION = "0.5.56"
5
5
  end
@@ -694,6 +694,25 @@ RSpec.describe Moxml::Adapter::Leptris do
694
694
  end
695
695
  end
696
696
 
697
+ describe "source_position (leptris 1.9.181+, upstream #1124)" do
698
+ let(:ctx) { Moxml.new(:leptris) }
699
+
700
+ it "answers engine source positions for parsed nodes" do
701
+ skip "requires leptris 1.9.181" unless described_class::NATIVE_SOURCE_POSITION
702
+
703
+ doc = ctx.parse("<root>\n <child>text</child>\n</root>")
704
+ expect(doc.root.source_position).to include(line: 1)
705
+ expect(doc.root.source_position).to be_a(Hash)
706
+ end
707
+
708
+ it "answers nil below the gate and on other adapters" do
709
+ expect(Moxml::Adapter::Base.source_position(nil)).to be_nil
710
+ expect(Moxml::Adapter::Nokogiri.source_position(nil)).to be_nil
711
+ noko = Moxml.new(:nokogiri).parse("<root><a/></root>")
712
+ expect(noko.root.children.first.source_position).to be_nil
713
+ end
714
+ end
715
+
697
716
  describe "subtree digest (issue #173, leptris#869)" do
698
717
  let(:ctx) { Moxml.new(:leptris) }
699
718
 
@@ -105,4 +105,22 @@ RSpec.describe Moxml::AttributeResolver do
105
105
  )).to be(false)
106
106
  end
107
107
  end
108
+
109
+ describe ".resolve_value capability dispatch (issue #242)" do
110
+ it "answers prefixed values through the adapter capability, not class identity" do
111
+ doc = Moxml.new(:nokogiri).parse(
112
+ '<w:f xmlns:w="urn:w"><w:n w:val="Arial"/></w:f>',
113
+ )
114
+ node = doc.root.children.first
115
+
116
+ expect(Moxml::Adapter::Base.expanded_attr_reads?).to be(false)
117
+ expect(Moxml::Adapter::Nokogiri.expanded_attr_reads?).to be(false)
118
+ expect(node["w:val"]).to eq("Arial")
119
+ end
120
+
121
+ it "keeps native c14n delegation behind the adapter protocol" do
122
+ expect(Moxml::Adapter::Base.native_inclusive10(nil)).to be_nil
123
+ expect(Moxml::Adapter::Nokogiri.native_inclusive10(nil)).to be_nil
124
+ end
125
+ end
108
126
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moxml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.54
4
+ version: 0.5.56
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.