moxml 0.5.56 → 0.5.57
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/lib/moxml/adapter/leptris.rb +55 -3
- data/lib/moxml/context.rb +5 -2
- data/lib/moxml/version.rb +1 -1
- data/spec/moxml/adapter/leptris_spec.rb +33 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d4db82d82671fd5cc6189294198abf6d019cd9a719dd25eff901227ebd6c411e
|
|
4
|
+
data.tar.gz: 34611277972cb9687a3b1350ee4a9d5d3036c432fb2ed89409492a2bae812821
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 22ee802575e1c85d3f2a03981ed0fce5ed24e23576d005bbf08861e06051026b23276977a8cdedc3340709ea617fcd8a01cade368f74083d4a05728b6dd5f9f0
|
|
7
|
+
data.tar.gz: 43b6109e181270728559005b64e7e8b728a38403b2230f2c868b125def432ceddc5e9e1e468ad6afebcb2a073c9d5e9f69da48acae2499218dbe7c12a81a61aa
|
|
@@ -598,7 +598,21 @@ module Moxml
|
|
|
598
598
|
# entity-marker splitting applies.
|
|
599
599
|
def parse_fragment(xml, _context = nil)
|
|
600
600
|
doc = parse("<m>#{xml}</m>")
|
|
601
|
-
|
|
601
|
+
# Lifetime seam (#245): the fragment's natives live in the
|
|
602
|
+
# parse document's C tree, and the binding Document is the
|
|
603
|
+
# sole owner with a GC finalizer. The parent_node chain
|
|
604
|
+
# (fragment -> synthetic <m> -> Document wrapper) keeps the
|
|
605
|
+
# owning wrappers strongly reachable from every returned
|
|
606
|
+
# node; the wrappers are minted HERE and returned as-is —
|
|
607
|
+
# re-wrapping at the caller would race the context map's
|
|
608
|
+
# weak values and silently drop the chain.
|
|
609
|
+
root_wrapper = doc.root
|
|
610
|
+
root_wrapper.parent_node = doc
|
|
611
|
+
children(root_wrapper.native).map do |child|
|
|
612
|
+
wrapped = Node.wrap(child, doc.context)
|
|
613
|
+
wrapped.parent_node = root_wrapper
|
|
614
|
+
wrapped
|
|
615
|
+
end
|
|
602
616
|
end
|
|
603
617
|
|
|
604
618
|
def iterparse(xml, mode = :top_level, _context = nil, &block)
|
|
@@ -794,6 +808,10 @@ module Moxml
|
|
|
794
808
|
|
|
795
809
|
element = node
|
|
796
810
|
if namespace.nil?
|
|
811
|
+
# Supported un-prefix (#245, relaton migration): rename
|
|
812
|
+
# the node to its local part (name = local) — the
|
|
813
|
+
# serializer re-attaches the old prefix after namespace=
|
|
814
|
+
# nil on prefixed elements until leptris-ruby#244 lands.
|
|
797
815
|
# Nil-clear contract (issue #164): undeclare the default
|
|
798
816
|
# namespace (xmlns="") and drop any name prefix — the
|
|
799
817
|
# element then reports no namespace, matching the other
|
|
@@ -1359,7 +1377,17 @@ module Moxml
|
|
|
1359
1377
|
node.document.add_pi(new_node.target, new_node.content.to_s)
|
|
1360
1378
|
return new_node
|
|
1361
1379
|
end
|
|
1362
|
-
node.add_previous_sibling(new_node)
|
|
1380
|
+
return node.add_previous_sibling(new_node) if node.is_a?(::Leptris::XML::Element)
|
|
1381
|
+
|
|
1382
|
+
# Non-element receivers: raw-FFI anchor (issue #245, same
|
|
1383
|
+
# shape as add_next_sibling).
|
|
1384
|
+
adopt_for_sibling_insert(new_node, node)
|
|
1385
|
+
::Leptris::XML::FFI.check_status(
|
|
1386
|
+
::Leptris::XML::FFI.leptris_element_insert_before(
|
|
1387
|
+
node.c_ptr, new_node.c_ptr
|
|
1388
|
+
),
|
|
1389
|
+
)
|
|
1390
|
+
new_node
|
|
1363
1391
|
end
|
|
1364
1392
|
|
|
1365
1393
|
def add_next_sibling(node, new_node)
|
|
@@ -1367,7 +1395,31 @@ module Moxml
|
|
|
1367
1395
|
node = to_binding(node)
|
|
1368
1396
|
new_node = to_binding(new_node)
|
|
1369
1397
|
end
|
|
1370
|
-
node.add_next_sibling(new_node)
|
|
1398
|
+
return node.add_next_sibling(new_node) if node.is_a?(::Leptris::XML::Element)
|
|
1399
|
+
|
|
1400
|
+
# Non-element receivers (Text/Comment/CDATA): the binding's
|
|
1401
|
+
# method is Element-only, but the C insert anchors on any
|
|
1402
|
+
# node — route through the FFI entry directly, keeping the
|
|
1403
|
+
# binding's namespace-lift adoption for element inserts
|
|
1404
|
+
# (issue #245).
|
|
1405
|
+
adopt_for_sibling_insert(new_node, node)
|
|
1406
|
+
::Leptris::XML::FFI.check_status(
|
|
1407
|
+
::Leptris::XML::FFI.leptris_element_insert_after(
|
|
1408
|
+
node.c_ptr, new_node.c_ptr
|
|
1409
|
+
),
|
|
1410
|
+
)
|
|
1411
|
+
new_node
|
|
1412
|
+
end
|
|
1413
|
+
|
|
1414
|
+
# The binding's add_*_ sibling methods lift an adopted
|
|
1415
|
+
# element's namespace declarations into the target scope;
|
|
1416
|
+
# the raw-FFI path above must preserve that.
|
|
1417
|
+
def adopt_for_sibling_insert(new_node, anchor)
|
|
1418
|
+
return unless new_node.is_a?(::Leptris::XML::Element)
|
|
1419
|
+
return if ::Leptris::XML::Element.skip_adoption_lift?(new_node)
|
|
1420
|
+
|
|
1421
|
+
scope = anchor.parent.is_a?(::Leptris::XML::Element) ? anchor.parent.namespaces : {}
|
|
1422
|
+
::Leptris::XML::Element.lift_namespaces_for_adoption(new_node, scope)
|
|
1371
1423
|
end
|
|
1372
1424
|
|
|
1373
1425
|
def remove(node)
|
data/lib/moxml/context.rb
CHANGED
|
@@ -124,8 +124,11 @@ module Moxml
|
|
|
124
124
|
# are the result either way.
|
|
125
125
|
def parse_fragment(xml)
|
|
126
126
|
adapter = config.adapter
|
|
127
|
-
adapter.parse_fragment(xml, self).map do |
|
|
128
|
-
|
|
127
|
+
adapter.parse_fragment(xml, self).map do |node|
|
|
128
|
+
# Adapters that tie a parent_node lifetime chain (#245)
|
|
129
|
+
# return wrapped nodes — pass them through untouched;
|
|
130
|
+
# re-wrapping would race the weak wrapper map.
|
|
131
|
+
node.is_a?(Moxml::Node) ? node : Moxml::Node.wrap(node, self)
|
|
129
132
|
end
|
|
130
133
|
end
|
|
131
134
|
|
data/lib/moxml/version.rb
CHANGED
|
@@ -672,6 +672,39 @@ RSpec.describe Moxml::Adapter::Leptris do
|
|
|
672
672
|
end
|
|
673
673
|
end
|
|
674
674
|
|
|
675
|
+
describe "adapter seams from the relaton migration (issue #245)" do
|
|
676
|
+
let(:ctx) { Moxml.new(:leptris) }
|
|
677
|
+
|
|
678
|
+
it "keeps parse_fragment nodes' owning document alive" do
|
|
679
|
+
nodes = ctx.parse_fragment("<em>x</em>")
|
|
680
|
+
element = nodes.first
|
|
681
|
+
expect(element.parent_node).not_to be_nil
|
|
682
|
+
GC.start
|
|
683
|
+
GC.start
|
|
684
|
+
expect(element.name).to eq("em")
|
|
685
|
+
expect(element.text).to eq("x")
|
|
686
|
+
document = element.document
|
|
687
|
+
expect(document.children.first.name).to eq("m")
|
|
688
|
+
expect(document.children.first.children.first.name).to eq("em")
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
it "inserts siblings after a text node" do
|
|
692
|
+
doc = ctx.parse("<root><p>a<!--c1-->b</p></root>")
|
|
693
|
+
paragraph = doc.root.children.first
|
|
694
|
+
cursor = paragraph.children.first
|
|
695
|
+
cursor.add_next_sibling(doc.create_text("Z"))
|
|
696
|
+
expect(paragraph.to_xml).to eq("<p>aZ<!--c1-->b</p>")
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
it "inserts siblings before a text node" do
|
|
700
|
+
doc = ctx.parse("<root><p><!--c1-->ab</p></root>")
|
|
701
|
+
paragraph = doc.root.children.first
|
|
702
|
+
cursor = paragraph.children.last
|
|
703
|
+
cursor.add_previous_sibling(doc.create_text("Y"))
|
|
704
|
+
expect(paragraph.to_xml).to eq("<p><!--c1-->Yab</p>")
|
|
705
|
+
end
|
|
706
|
+
end
|
|
707
|
+
|
|
675
708
|
describe "to_binding is defined regardless of the native layer (issue #217)" do
|
|
676
709
|
it "is the identity for binding nodes" do
|
|
677
710
|
ctx = Moxml.new(:leptris)
|
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.
|
|
4
|
+
version: 0.5.57
|
|
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-09-
|
|
11
|
+
date: 2026-09-17 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
|