moxml 0.5.5 → 0.5.6
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/.github/workflows/release.yml +3 -1
- data/lib/moxml/adapter/customized_leptris/document_pi.rb +34 -0
- data/lib/moxml/adapter/customized_leptris.rb +3 -1
- data/lib/moxml/adapter/leptris.rb +50 -8
- data/lib/moxml/version.rb +1 -1
- data/spec/moxml/adapter/leptris_spec.rb +48 -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: 7f2b8ff3a745345a5d0462bd246f0ee8b463713fcad2dcf99590813ffd49aa27
|
|
4
|
+
data.tar.gz: 8930bcdaee831095c3a5b576d4f19a36591fd1a3884e0fb1f0aebb1c4c91485f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d7c64568fa5c5a013bee81b37e9329590817c5d0db567c6f8c609de48e6782d75544e10bfe00929d0768e04a10591eef54c3a79e1ed3acfab2aa34dc1a11eb64
|
|
7
|
+
data.tar.gz: 6eebca4d31617a36da0df9f471bafc7085556b7216af8bb6138df0c9e5c2d8982fdfd6bd8ad897a3c88bdc06367c30fef9ccc9418575480ce0b97546a40af38c
|
|
@@ -30,6 +30,8 @@ jobs:
|
|
|
30
30
|
with:
|
|
31
31
|
next_version: ${{ github.event.inputs.next_version }}
|
|
32
32
|
gated: ${{ inputs.gated == true }}
|
|
33
|
+
# No rubygems-api-key: the gem publishes through its configured
|
|
34
|
+
# RubyGems OIDC trusted publisher. pat_token covers the version
|
|
35
|
+
# bump push to main.
|
|
33
36
|
secrets:
|
|
34
|
-
rubygems-api-key: ${{ secrets.LUTAML_CI_RUBYGEMS_API_KEY }}
|
|
35
37
|
pat_token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Moxml
|
|
4
|
+
module Adapter
|
|
5
|
+
module CustomizedLeptris
|
|
6
|
+
# Document-level processing instruction. libleptris stores these
|
|
7
|
+
# outside the element tree (a flat, document-ordered list with no
|
|
8
|
+
# prolog/epilog anchoring — its serializer emits them all before
|
|
9
|
+
# the root), reachable through Document#processing_instructions
|
|
10
|
+
# as [target, data] pairs. This pseudo-native gives the pairs a
|
|
11
|
+
# node identity so the moxml contract can list them as document
|
|
12
|
+
# children.
|
|
13
|
+
class DocumentPI
|
|
14
|
+
attr_accessor :target, :data, :parent_doc
|
|
15
|
+
alias content data
|
|
16
|
+
alias content= data=
|
|
17
|
+
|
|
18
|
+
def initialize(target, data = "", parent_doc = nil)
|
|
19
|
+
@target = target
|
|
20
|
+
@data = data.to_s
|
|
21
|
+
@parent_doc = parent_doc
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_xml
|
|
25
|
+
data.empty? ? "<?#{target}?>" : "<?#{target} #{data}?>"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def ==(other)
|
|
29
|
+
other.is_a?(self.class) && target == other.target && data == other.data
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
module Moxml
|
|
4
4
|
module Adapter
|
|
5
5
|
# Pure-Ruby node kinds that libleptris has no native representation
|
|
6
|
-
# for: XML declarations, programmatic DOCTYPEs,
|
|
6
|
+
# for: XML declarations, programmatic DOCTYPEs, entity references,
|
|
7
|
+
# and document-level processing instructions.
|
|
7
8
|
# The adapter stores them via NativeAttachment and serializes them
|
|
8
9
|
# from #to_xml.
|
|
9
10
|
module CustomizedLeptris
|
|
@@ -11,6 +12,7 @@ module Moxml
|
|
|
11
12
|
autoload :Doctype, "moxml/adapter/customized_leptris/doctype"
|
|
12
13
|
autoload :EntityReference, "moxml/adapter/customized_leptris/entity_reference"
|
|
13
14
|
autoload :TextSegment, "moxml/adapter/customized_leptris/text_segment"
|
|
15
|
+
autoload :DocumentPI, "moxml/adapter/customized_leptris/document_pi"
|
|
14
16
|
end
|
|
15
17
|
end
|
|
16
18
|
end
|
|
@@ -215,7 +215,8 @@ module Moxml
|
|
|
215
215
|
def entity_bearing?(native)
|
|
216
216
|
case native
|
|
217
217
|
when CustomizedLeptris::Declaration, CustomizedLeptris::Doctype,
|
|
218
|
-
CustomizedLeptris::EntityReference, CustomizedLeptris::TextSegment
|
|
218
|
+
CustomizedLeptris::EntityReference, CustomizedLeptris::TextSegment,
|
|
219
|
+
CustomizedLeptris::DocumentPI
|
|
219
220
|
true
|
|
220
221
|
else
|
|
221
222
|
doc = native.document
|
|
@@ -231,7 +232,7 @@ module Moxml
|
|
|
231
232
|
when CustomizedLeptris::EntityReference then :entity_reference
|
|
232
233
|
when ::Leptris::XML::CDATA then :cdata
|
|
233
234
|
when ::Leptris::XML::Comment then :comment
|
|
234
|
-
when ::Leptris::XML::ProcessingInstruction then :processing_instruction
|
|
235
|
+
when ::Leptris::XML::ProcessingInstruction, CustomizedLeptris::DocumentPI then :processing_instruction
|
|
235
236
|
when ::Leptris::XML::Text, CustomizedLeptris::TextSegment then :text
|
|
236
237
|
when ::Leptris::XML::Element then :element
|
|
237
238
|
when ::Leptris::XML::Attr then :attribute
|
|
@@ -241,13 +242,14 @@ module Moxml
|
|
|
241
242
|
|
|
242
243
|
def node_name(node)
|
|
243
244
|
return node.root_name if node.is_a?(::Leptris::XML::DocType)
|
|
245
|
+
return node.target if node.is_a?(CustomizedLeptris::DocumentPI)
|
|
244
246
|
|
|
245
247
|
node.name.to_s.dup.force_encoding("UTF-8")
|
|
246
248
|
end
|
|
247
249
|
|
|
248
250
|
def set_node_name(node, name)
|
|
249
251
|
case node
|
|
250
|
-
when ::Leptris::XML::ProcessingInstruction then node.target = name
|
|
252
|
+
when ::Leptris::XML::ProcessingInstruction, CustomizedLeptris::DocumentPI then node.target = name
|
|
251
253
|
else node.name = name
|
|
252
254
|
end
|
|
253
255
|
end
|
|
@@ -260,6 +262,8 @@ module Moxml
|
|
|
260
262
|
CustomizedLeptris::Doctype.new(node.name, node.external_id, node.system_id)
|
|
261
263
|
when CustomizedLeptris::EntityReference
|
|
262
264
|
CustomizedLeptris::EntityReference.new(node.name)
|
|
265
|
+
when CustomizedLeptris::DocumentPI
|
|
266
|
+
CustomizedLeptris::DocumentPI.new(node.target, node.data, node.parent_doc)
|
|
263
267
|
else
|
|
264
268
|
node.dup
|
|
265
269
|
end
|
|
@@ -271,6 +275,7 @@ module Moxml
|
|
|
271
275
|
assemble_document_children(node)
|
|
272
276
|
when CustomizedLeptris::Declaration, CustomizedLeptris::Doctype,
|
|
273
277
|
CustomizedLeptris::EntityReference, CustomizedLeptris::TextSegment,
|
|
278
|
+
CustomizedLeptris::DocumentPI,
|
|
274
279
|
# Terminal node kinds pay an FFI round trip for an empty
|
|
275
280
|
# list; unfiltered recursions visit every text node.
|
|
276
281
|
::Leptris::XML::Text, ::Leptris::XML::Comment,
|
|
@@ -321,7 +326,8 @@ module Moxml
|
|
|
321
326
|
def parent(node)
|
|
322
327
|
case node
|
|
323
328
|
when ::Leptris::XML::Document then nil
|
|
324
|
-
when CustomizedLeptris::Declaration, CustomizedLeptris::Doctype
|
|
329
|
+
when CustomizedLeptris::Declaration, CustomizedLeptris::Doctype,
|
|
330
|
+
CustomizedLeptris::DocumentPI then node.parent_doc
|
|
325
331
|
when CustomizedLeptris::TextSegment, CustomizedLeptris::EntityReference then node.parent
|
|
326
332
|
else
|
|
327
333
|
# The binding reports the root element as parentless; the
|
|
@@ -447,6 +453,12 @@ module Moxml
|
|
|
447
453
|
attachments.delete(node.parent_doc, :doctype) if node.parent_doc
|
|
448
454
|
when CustomizedLeptris::EntityReference
|
|
449
455
|
marker_text_for(node.parent, node.name)&.unlink
|
|
456
|
+
when CustomizedLeptris::DocumentPI
|
|
457
|
+
raise Moxml::NotImplementedError.new(
|
|
458
|
+
"libleptris has no document-level PI removal",
|
|
459
|
+
adapter: :leptris,
|
|
460
|
+
feature: :remove,
|
|
461
|
+
)
|
|
450
462
|
else
|
|
451
463
|
node.unlink
|
|
452
464
|
end
|
|
@@ -741,7 +753,7 @@ module Moxml
|
|
|
741
753
|
# binding, so a Text branch first would swallow CDATA nodes.
|
|
742
754
|
case node
|
|
743
755
|
when CustomizedLeptris::Declaration, CustomizedLeptris::Doctype,
|
|
744
|
-
CustomizedLeptris::EntityReference
|
|
756
|
+
CustomizedLeptris::EntityReference, CustomizedLeptris::DocumentPI
|
|
745
757
|
return node.to_xml
|
|
746
758
|
when ::Leptris::XML::CDATA
|
|
747
759
|
return XmlEmitter.cdata(node.content)
|
|
@@ -863,9 +875,7 @@ module Moxml
|
|
|
863
875
|
native = native_doctype_xml(doc)
|
|
864
876
|
parts << native if native
|
|
865
877
|
|
|
866
|
-
(doc
|
|
867
|
-
parts << (data.to_s.empty? ? "<?#{target}?>" : "<?#{target} #{data}?>")
|
|
868
|
-
end
|
|
878
|
+
document_pi_nodes(doc).each { |pi| parts << pi.to_xml }
|
|
869
879
|
|
|
870
880
|
parts << raw_serialize(doc.root, options) if doc.root
|
|
871
881
|
|
|
@@ -935,6 +945,21 @@ module Moxml
|
|
|
935
945
|
attachments.get(native, :had_source_declaration) ? true : false
|
|
936
946
|
end
|
|
937
947
|
|
|
948
|
+
# Document-level PI pseudo-nodes, materialized once from the C
|
|
949
|
+
# list and cached per document: children and serialization read
|
|
950
|
+
# the same objects, so wrapper mutations round-trip. Build the
|
|
951
|
+
# cache BEFORE appending a PI with add_pi, or the C-side
|
|
952
|
+
# addition would be double-counted.
|
|
953
|
+
def document_pi_nodes(doc)
|
|
954
|
+
attachments.get(doc, :doc_pi_nodes) || begin
|
|
955
|
+
nodes = doc.processing_instructions.map do |(target, data)|
|
|
956
|
+
CustomizedLeptris::DocumentPI.new(target, data, doc)
|
|
957
|
+
end
|
|
958
|
+
attachments.set(doc, :doc_pi_nodes, nodes)
|
|
959
|
+
nodes
|
|
960
|
+
end
|
|
961
|
+
end
|
|
962
|
+
|
|
938
963
|
def assemble_document_children(doc)
|
|
939
964
|
children = []
|
|
940
965
|
|
|
@@ -944,6 +969,15 @@ module Moxml
|
|
|
944
969
|
doctype_wrapper = attachments.get(doc, :doctype)
|
|
945
970
|
children << doctype_wrapper if doctype_wrapper
|
|
946
971
|
|
|
972
|
+
# Document-level PIs live outside the element tree in
|
|
973
|
+
# libleptris (a flat list; its serializer emits them before
|
|
974
|
+
# the root). Listed after the DOCTYPE to match the order
|
|
975
|
+
# serialize_document emits, so children and serialization
|
|
976
|
+
# agree. Epilog anchoring is not representable in the C
|
|
977
|
+
# model — a known divergence from the Nokogiri-shaped
|
|
978
|
+
# contract the other adapters expose.
|
|
979
|
+
children.concat(document_pi_nodes(doc))
|
|
980
|
+
|
|
947
981
|
children << doc.root if doc.root
|
|
948
982
|
|
|
949
983
|
texts = attachments.get(doc, :document_text)
|
|
@@ -966,7 +1000,15 @@ module Moxml
|
|
|
966
1000
|
when ::Leptris::XML::Element
|
|
967
1001
|
doc.root = child
|
|
968
1002
|
when ::Leptris::XML::ProcessingInstruction
|
|
1003
|
+
document_pi_nodes(doc)
|
|
969
1004
|
doc.add_pi(child.target, child.content.to_s)
|
|
1005
|
+
document_pi_nodes(doc) << CustomizedLeptris::DocumentPI.new(
|
|
1006
|
+
child.target, child.content.to_s, doc
|
|
1007
|
+
)
|
|
1008
|
+
when CustomizedLeptris::DocumentPI
|
|
1009
|
+
document_pi_nodes(doc)
|
|
1010
|
+
doc.add_pi(child.target, child.data)
|
|
1011
|
+
document_pi_nodes(doc) << child
|
|
970
1012
|
when ::Leptris::XML::Text
|
|
971
1013
|
texts = attachments.get(doc, :document_text) || []
|
|
972
1014
|
texts << child
|
data/lib/moxml/version.rb
CHANGED
|
@@ -81,6 +81,54 @@ RSpec.describe Moxml::Adapter::Leptris do
|
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
describe "document-level processing instructions" do
|
|
85
|
+
let(:ctx) { Moxml.new(:leptris) }
|
|
86
|
+
|
|
87
|
+
it "lists document PIs as children with the root" do
|
|
88
|
+
doc = ctx.parse('<?xml version="1.0"?><?pi-prolog before?><root/><?pi-epilog after?>')
|
|
89
|
+
kids = doc.children.to_a
|
|
90
|
+
|
|
91
|
+
expect(kids.map(&:class)).to eq(
|
|
92
|
+
[Moxml::ProcessingInstruction, Moxml::ProcessingInstruction, Moxml::Element],
|
|
93
|
+
)
|
|
94
|
+
expect(kids.select(&:processing_instruction?).map(&:target)).to eq(%w[pi-prolog pi-epilog])
|
|
95
|
+
expect(kids[0].content).to eq("before")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "round-trips mutations and additions through serialization" do
|
|
99
|
+
doc = ctx.parse("<?pi-original x?><root/>")
|
|
100
|
+
pi = doc.children.to_a[0]
|
|
101
|
+
pi.target = "renamed"
|
|
102
|
+
pi.content = "changed"
|
|
103
|
+
expect(doc.to_xml).to include("<?renamed changed?>")
|
|
104
|
+
|
|
105
|
+
doc.add_child(doc.create_processing_instruction("added", "now"))
|
|
106
|
+
expect(doc.to_xml).to include("<?added now?>")
|
|
107
|
+
expect(doc.children.to_a.select(&:processing_instruction?).map(&:target)).to eq(%w[renamed added])
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "serializes children and document output in agreement" do
|
|
111
|
+
# libleptris stores document PIs as one flat pre-root list (no
|
|
112
|
+
# epilog anchoring); children and to_xml must at least agree.
|
|
113
|
+
doc = ctx.parse('<?xml version="1.0"?><?pi-a 1?><root/><?pi-b 2?>')
|
|
114
|
+
from_children = doc.children.to_a.select(&:processing_instruction?)
|
|
115
|
+
.map(&:to_xml).join
|
|
116
|
+
from_document = doc.to_xml.sub(%r{\A<\?xml[^>]*\?>}, "")
|
|
117
|
+
|
|
118
|
+
expect(from_document).to start_with(from_children)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "reports the tracked native for a re-added document PI" do
|
|
122
|
+
doc = ctx.parse("<?pi-src orig?><root/>")
|
|
123
|
+
moved = doc.children.to_a[0]
|
|
124
|
+
target_doc = ctx.parse("<other/>")
|
|
125
|
+
target_doc.add_child(moved)
|
|
126
|
+
|
|
127
|
+
expect(target_doc.to_xml).to include("<?pi-src orig?>")
|
|
128
|
+
expect(target_doc.children.to_a.select(&:processing_instruction?).map(&:target)).to include("pi-src")
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
84
132
|
describe "entity-marker tracking" do
|
|
85
133
|
let(:ctx) { Moxml.new(:leptris) }
|
|
86
134
|
|
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.
|
|
4
|
+
version: 0.5.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -123,6 +123,7 @@ files:
|
|
|
123
123
|
- lib/moxml/adapter/customized_leptris.rb
|
|
124
124
|
- lib/moxml/adapter/customized_leptris/declaration.rb
|
|
125
125
|
- lib/moxml/adapter/customized_leptris/doctype.rb
|
|
126
|
+
- lib/moxml/adapter/customized_leptris/document_pi.rb
|
|
126
127
|
- lib/moxml/adapter/customized_leptris/entity_reference.rb
|
|
127
128
|
- lib/moxml/adapter/customized_leptris/text_segment.rb
|
|
128
129
|
- lib/moxml/adapter/customized_libxml.rb
|