moxml 0.5.47 → 0.5.49
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/base.rb +16 -0
- data/lib/moxml/adapter/leptris.rb +100 -14
- data/lib/moxml/adapter/libxml.rb +1 -1
- data/lib/moxml/adapter/nokogiri.rb +2 -2
- data/lib/moxml/adapter/oga.rb +1 -1
- data/lib/moxml/adapter/ox.rb +1 -1
- data/lib/moxml/adapter/rexml.rb +1 -1
- data/lib/moxml/attribute.rb +4 -2
- data/lib/moxml/cdata.rb +3 -1
- data/lib/moxml/comment.rb +3 -1
- data/lib/moxml/context.rb +1 -1
- data/lib/moxml/declaration.rb +3 -1
- data/lib/moxml/doctype.rb +3 -1
- data/lib/moxml/document.rb +11 -9
- data/lib/moxml/element.rb +7 -6
- data/lib/moxml/entity/restorer.rb +2 -2
- data/lib/moxml/entity_reference.rb +3 -1
- data/lib/moxml/namespace.rb +3 -1
- data/lib/moxml/node.rb +62 -9
- data/lib/moxml/processing_instruction.rb +3 -1
- data/lib/moxml/text.rb +3 -1
- data/lib/moxml/version.rb +1 -1
- data/lib/moxml/wrappers.rb +47 -0
- data/lib/moxml.rb +1 -0
- data/spec/integration/contract_parity_spec.rb +2 -3
- data/spec/integration/shared_examples/entity_reference_whitespace.rb +4 -4
- data/spec/moxml/adapter/leptris_spec.rb +17 -12
- data/spec/moxml/adapter/libxml_internals_spec.rb +3 -3
- data/spec/moxml/node_set_spec.rb +1 -1
- data/spec/moxml/node_spec.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1e7f648665fbf11423b43ed957f111cabe57a732b2037d6e7d6d718beae4e0c3
|
|
4
|
+
data.tar.gz: ec4ac686e3c83b794944c02a3f6b92aa964c9e984fb5752b49dbeb08812e0f61
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ad7b15e82e237a726680c1eed20c0942abbcc74aca205a58681c745548e5a5c9c5048034079b88b1c8f91eddeb742d0eebbd5cc45daca057f852d25da48eb331
|
|
7
|
+
data.tar.gz: 834577776b64caa59e9b363a8a936db9684a20ed7793a6698adbfe0d6633a0770e17f5d24b063352c3931bea1289ac53ceb0bd8c9f7b71ad3fe2f2007ef59a5f
|
data/lib/moxml/adapter/base.rb
CHANGED
|
@@ -133,6 +133,22 @@ module Moxml
|
|
|
133
133
|
# Protocol-level native equality; engines with more than one
|
|
134
134
|
# wrapper class over one C node override (leptris native
|
|
135
135
|
# read layer). Shared adapter examples compare through this.
|
|
136
|
+
# Extend-in-place capability (#230): an adapter whose native
|
|
137
|
+
# objects can carry the contract modules directly returns the
|
|
138
|
+
# extended native here (its @native is itself); the default
|
|
139
|
+
# mints a wrapper shell.
|
|
140
|
+
def wrap_native(_node, _type, _context)
|
|
141
|
+
nil
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Subtree walk capability: an adapter with a C-side pre-order
|
|
145
|
+
# traversal (leptris >= 1.9.174.6 visit) walks descendants in
|
|
146
|
+
# one dispatch; nil keeps the recursive children walk. Self
|
|
147
|
+
# is not yielded (each_node semantics).
|
|
148
|
+
def walk_descendants(_native, _context)
|
|
149
|
+
nil
|
|
150
|
+
end
|
|
151
|
+
|
|
136
152
|
def same_node?(one, other)
|
|
137
153
|
one == other
|
|
138
154
|
end
|
|
@@ -85,6 +85,24 @@ module Moxml
|
|
|
85
85
|
defined?(::Leptris::XML::NativeNode) &&
|
|
86
86
|
Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.163.5")
|
|
87
87
|
|
|
88
|
+
# Identity mode (#230 stage 2): the contract modules extended
|
|
89
|
+
# onto natives shadow the C surface (Element#[] over
|
|
90
|
+
# NativeNode#[]), so the adapter's native fast paths speak to
|
|
91
|
+
# the native layer through these bound entries — bind_call is
|
|
92
|
+
# the same C dispatch without the shadow lookup.
|
|
93
|
+
if NATIVE_READ_LAYER
|
|
94
|
+
NN = ::Leptris::XML::NativeNode
|
|
95
|
+
NN_ATTRIBUTE = NN.instance_method(:attribute)
|
|
96
|
+
NN_NAME = NN.instance_method(:name)
|
|
97
|
+
NN_PARENT = NN.instance_method(:parent)
|
|
98
|
+
NN_NEXT_SIBLING = NN.instance_method(:next_sibling)
|
|
99
|
+
NN_CONTENT = NN.instance_method(:content)
|
|
100
|
+
NN_CHILDREN = NN.instance_method(:children)
|
|
101
|
+
NN_NODE_TYPE = NN.instance_method(:node_type)
|
|
102
|
+
NN_DOCUMENT = NN.instance_method(:document)
|
|
103
|
+
NN_ADD_CHILD = NN.instance_method(:add_child)
|
|
104
|
+
end
|
|
105
|
+
|
|
88
106
|
# 1.9.163.2 moved the native bulk children into C
|
|
89
107
|
# (Native.bulk_children) and fixed the 512 truncation
|
|
90
108
|
# (leptris-ruby#202). The 162.6-163.1 window carries the
|
|
@@ -136,6 +154,48 @@ module Moxml
|
|
|
136
154
|
@native_doc_roots = ObjectSpace::WeakMap.new
|
|
137
155
|
|
|
138
156
|
class << self
|
|
157
|
+
# Extend-in-place mint (#230 stage 2): a TypedData native
|
|
158
|
+
# carries the contract modules on itself — the wrapper layer's
|
|
159
|
+
# 3-4 Ruby frames collapse to the module call over the C
|
|
160
|
+
# method. @native is self; every adapter method that accepts
|
|
161
|
+
# a native already handles NativeNode receivers.
|
|
162
|
+
# Extend-in-place mint (#230 stage 2): disabled by
|
|
163
|
+
# measurement. Extending TypedData natives with the
|
|
164
|
+
# contract modules works correctly (full battery + lm
|
|
165
|
+
# 5422/0 under identity mode) but each extend allocates a
|
|
166
|
+
# singleton plus per-module iclasses — the consumer
|
|
167
|
+
# pipeline regressed 4017us -> 16350us with 6x the
|
|
168
|
+
# allocations on a 900-node walk. The per-read frame
|
|
169
|
+
# savings (~50ns) cannot repay that mint cost. Revisit
|
|
170
|
+
# when the binding grows klass-injection
|
|
171
|
+
# (NativeNode.from(doc, ptr, klass:) minting the
|
|
172
|
+
# contract-carrying subclass in C) — asked upstream in the
|
|
173
|
+
# #230 thread. Wrappers mint through the Wrappers:: shells
|
|
174
|
+
# meanwhile.
|
|
175
|
+
def wrap_native(_node, _type, _context)
|
|
176
|
+
nil
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
NATIVE_C_WALK =
|
|
180
|
+
defined?(::Leptris::XML::NativeNode) &&
|
|
181
|
+
Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.174.6")
|
|
182
|
+
|
|
183
|
+
# One C visit walk (TODO.perf/27: post-order/abort state in
|
|
184
|
+
# the C callback, rb_yield direct — no FFI closure per
|
|
185
|
+
# node) instead of per-level children walks. Pre-order via
|
|
186
|
+
# entering; depth 0 is the receiver and stays unyielded.
|
|
187
|
+
def walk_descendants(native, context)
|
|
188
|
+
return nil unless NATIVE_C_WALK
|
|
189
|
+
|
|
190
|
+
root = to_binding(native)
|
|
191
|
+
return nil unless root.is_a?(::Leptris::XML::Element) ||
|
|
192
|
+
root.is_a?(::Leptris::XML::Document)
|
|
193
|
+
|
|
194
|
+
root.visit do |node, entering, depth|
|
|
195
|
+
yield Moxml::Node.wrap(node, context) if entering && depth.positive?
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
139
199
|
def record_native_doc(root_native, doc)
|
|
140
200
|
@native_doc_roots[root_native] = doc
|
|
141
201
|
end
|
|
@@ -165,7 +225,7 @@ module Moxml
|
|
|
165
225
|
def doc_for(node)
|
|
166
226
|
# The 1.9.163.5 native layer exposes the owning document
|
|
167
227
|
# directly; the root climb serves older bindings.
|
|
168
|
-
return node
|
|
228
|
+
return NN_DOCUMENT.bind_call(node) if NATIVE_MUTATIONS_COHERENT
|
|
169
229
|
|
|
170
230
|
current = node
|
|
171
231
|
current = current.parent while current&.parent
|
|
@@ -201,7 +261,7 @@ module Moxml
|
|
|
201
261
|
::Leptris::XML::FFI::C14N_1_0, nil,
|
|
202
262
|
mode: ::Leptris::XML::FFI::C14N_MODE_CANONICAL
|
|
203
263
|
)
|
|
204
|
-
wrapper = Moxml::Document.new(native_doc, Moxml::Context.new(:leptris))
|
|
264
|
+
wrapper = Moxml::Wrappers::Document.new(native_doc, Moxml::Context.new(:leptris))
|
|
205
265
|
reference = Moxml::C14n::Inclusive10.new.canonicalize(wrapper.root)
|
|
206
266
|
native == reference
|
|
207
267
|
rescue StandardError
|
|
@@ -333,7 +393,14 @@ module Moxml
|
|
|
333
393
|
# document-plus-attachment probe here cost more than the
|
|
334
394
|
# read itself).
|
|
335
395
|
def bare_attr_value(element, name)
|
|
336
|
-
|
|
396
|
+
# Exact-name C read: bare names target no-namespace
|
|
397
|
+
# attributes (the documented contract — a bare "y" never
|
|
398
|
+
# resolves a "p:y" sibling).
|
|
399
|
+
value = if NATIVE_READ_LAYER && element.is_a?(NN)
|
|
400
|
+
NN_ATTRIBUTE.bind_call(element, name.to_s)
|
|
401
|
+
else
|
|
402
|
+
element[name.to_s]
|
|
403
|
+
end
|
|
337
404
|
if !NATIVE_STRINGS_UTF8 && NATIVE_READ_LAYER &&
|
|
338
405
|
element.is_a?(::Leptris::XML::NativeNode) &&
|
|
339
406
|
value.is_a?(String)
|
|
@@ -376,7 +443,7 @@ module Moxml
|
|
|
376
443
|
create_document
|
|
377
444
|
end
|
|
378
445
|
ctx = _context || Context.new(:leptris)
|
|
379
|
-
doc = Document.new(native_doc, ctx)
|
|
446
|
+
doc = Wrappers::Document.new(native_doc, ctx)
|
|
380
447
|
|
|
381
448
|
if options[:noblanks] && !ENGINE_NOBLANKS_SAFE
|
|
382
449
|
# The engine's DROP_WS_TEXT trims boundary whitespace of
|
|
@@ -451,7 +518,7 @@ module Moxml
|
|
|
451
518
|
end
|
|
452
519
|
attachments.set(native_doc, :entity_markers, false)
|
|
453
520
|
bump_serialize_generation
|
|
454
|
-
Document.new(native_doc, _context || Context.new(:leptris))
|
|
521
|
+
Wrappers::Document.new(native_doc, _context || Context.new(:leptris))
|
|
455
522
|
end
|
|
456
523
|
|
|
457
524
|
# nil when no parse flag is requested — the binding treats a
|
|
@@ -711,13 +778,15 @@ module Moxml
|
|
|
711
778
|
end
|
|
712
779
|
|
|
713
780
|
def processing_instruction_target(node)
|
|
781
|
+
return to_binding(node).target if NATIVE_READ_LAYER && node.is_a?(NN)
|
|
782
|
+
|
|
714
783
|
node.target
|
|
715
784
|
end
|
|
716
785
|
|
|
717
786
|
def node_type(node)
|
|
718
787
|
if NATIVE_READ_LAYER &&
|
|
719
788
|
node.is_a?(::Leptris::XML::NativeNode)
|
|
720
|
-
type = node
|
|
789
|
+
type = NN_NODE_TYPE.bind_call(node)
|
|
721
790
|
# The native layer spells PIs :pi; the wrapper contract
|
|
722
791
|
# (node_type_map) says :processing_instruction.
|
|
723
792
|
return :processing_instruction if type == :pi
|
|
@@ -765,11 +834,12 @@ module Moxml
|
|
|
765
834
|
|
|
766
835
|
if NATIVE_READ_LAYER && node.is_a?(::Leptris::XML::NativeNode)
|
|
767
836
|
# PIs expose no name through the native layer.
|
|
768
|
-
return to_binding(node).target.to_s if node
|
|
837
|
+
return to_binding(node).target.to_s if NN_NODE_TYPE.bind_call(node) == :pi
|
|
769
838
|
|
|
770
|
-
|
|
839
|
+
name = NN_NAME.bind_call(node)
|
|
840
|
+
return name if NATIVE_STRINGS_UTF8
|
|
771
841
|
|
|
772
|
-
|
|
842
|
+
name.dup.force_encoding(Encoding::UTF_8)
|
|
773
843
|
end
|
|
774
844
|
|
|
775
845
|
node.name.to_s.dup.force_encoding("UTF-8")
|
|
@@ -808,7 +878,7 @@ module Moxml
|
|
|
808
878
|
# the wrapper's memo supplies the flag, so deriving it
|
|
809
879
|
# here costs no C parent climb per call.
|
|
810
880
|
natives = if NATIVE_BULK_FIXED
|
|
811
|
-
node.
|
|
881
|
+
NN_CHILDREN.bind_call(node).to_a
|
|
812
882
|
else
|
|
813
883
|
bulk_native_children(node)
|
|
814
884
|
end
|
|
@@ -864,7 +934,7 @@ module Moxml
|
|
|
864
934
|
|
|
865
935
|
def parent(node)
|
|
866
936
|
if NATIVE_READ_LAYER && node.is_a?(::Leptris::XML::NativeNode)
|
|
867
|
-
parent = node
|
|
937
|
+
parent = NN_PARENT.bind_call(node)
|
|
868
938
|
return parent if parent
|
|
869
939
|
|
|
870
940
|
doc = doc_for(node)
|
|
@@ -987,7 +1057,7 @@ module Moxml
|
|
|
987
1057
|
end
|
|
988
1058
|
|
|
989
1059
|
def next_sibling(node)
|
|
990
|
-
return node
|
|
1060
|
+
return NN_NEXT_SIBLING.bind_call(node) if NATIVE_READ_LAYER &&
|
|
991
1061
|
node.is_a?(::Leptris::XML::NativeNode)
|
|
992
1062
|
|
|
993
1063
|
node.next_sibling if node.is_a?(::Leptris::XML::Node)
|
|
@@ -1114,6 +1184,12 @@ module Moxml
|
|
|
1114
1184
|
bump_serialize_generation
|
|
1115
1185
|
return child
|
|
1116
1186
|
end
|
|
1187
|
+
if NATIVE_MUTATIONS_COHERENT && parent.is_a?(NN) && child.is_a?(NN)
|
|
1188
|
+
doc = NN_DOCUMENT.bind_call(parent)
|
|
1189
|
+
child = doc.create_text_node(child) if child.is_a?(String)
|
|
1190
|
+
return NN_ADD_CHILD.bind_call(parent, child)
|
|
1191
|
+
end
|
|
1192
|
+
|
|
1117
1193
|
child = parent.document.create_text_node(child) if child.is_a?(String)
|
|
1118
1194
|
parent.add_child(child)
|
|
1119
1195
|
end
|
|
@@ -1200,9 +1276,10 @@ module Moxml
|
|
|
1200
1276
|
|
|
1201
1277
|
def text_content(node)
|
|
1202
1278
|
if NATIVE_READ_LAYER && node.is_a?(::Leptris::XML::NativeNode)
|
|
1203
|
-
|
|
1279
|
+
content = NN_CONTENT.bind_call(node)
|
|
1280
|
+
return content if NATIVE_STRINGS_UTF8
|
|
1204
1281
|
|
|
1205
|
-
|
|
1282
|
+
content.dup.force_encoding(Encoding::UTF_8)
|
|
1206
1283
|
end
|
|
1207
1284
|
|
|
1208
1285
|
# Frequency-ordered: elements dominate reads; they paid
|
|
@@ -1246,26 +1323,35 @@ module Moxml
|
|
|
1246
1323
|
end
|
|
1247
1324
|
|
|
1248
1325
|
def cdata_content(node)
|
|
1326
|
+
return NN_CONTENT.bind_call(node) if NATIVE_READ_LAYER && node.is_a?(NN)
|
|
1327
|
+
|
|
1249
1328
|
node.content
|
|
1250
1329
|
end
|
|
1251
1330
|
|
|
1252
1331
|
def set_cdata_content(node, content)
|
|
1332
|
+
node = to_binding(node) if NATIVE_READ_LAYER
|
|
1253
1333
|
node.content = content.to_s
|
|
1254
1334
|
end
|
|
1255
1335
|
|
|
1256
1336
|
def comment_content(node)
|
|
1337
|
+
return NN_CONTENT.bind_call(node) if NATIVE_READ_LAYER && node.is_a?(NN)
|
|
1338
|
+
|
|
1257
1339
|
node.content
|
|
1258
1340
|
end
|
|
1259
1341
|
|
|
1260
1342
|
def set_comment_content(node, content)
|
|
1343
|
+
node = to_binding(node) if NATIVE_READ_LAYER
|
|
1261
1344
|
node.content = content.to_s
|
|
1262
1345
|
end
|
|
1263
1346
|
|
|
1264
1347
|
def processing_instruction_content(node)
|
|
1348
|
+
return NN_CONTENT.bind_call(node) if NATIVE_READ_LAYER && node.is_a?(NN)
|
|
1349
|
+
|
|
1265
1350
|
node.content
|
|
1266
1351
|
end
|
|
1267
1352
|
|
|
1268
1353
|
def set_processing_instruction_content(node, content)
|
|
1354
|
+
node = to_binding(node) if NATIVE_READ_LAYER
|
|
1269
1355
|
node.data = content.to_s
|
|
1270
1356
|
end
|
|
1271
1357
|
|
data/lib/moxml/adapter/libxml.rb
CHANGED
|
@@ -152,7 +152,7 @@ module Moxml
|
|
|
152
152
|
# any new parse-time logic only has to be added to this one
|
|
153
153
|
# path; the restoration walk is just one of potentially several
|
|
154
154
|
# post-processing steps and doesn't fork the construction.
|
|
155
|
-
doc = Document.new(native_doc, ctx)
|
|
155
|
+
doc = Wrappers::Document.new(native_doc, ctx)
|
|
156
156
|
Entity::Restorer.new(doc).run if ctx.config.restore_entities
|
|
157
157
|
doc
|
|
158
158
|
end
|
|
@@ -80,7 +80,7 @@ module Moxml
|
|
|
80
80
|
# Use provided context if available, otherwise create new one
|
|
81
81
|
ctx = _context || Context.new(:nokogiri)
|
|
82
82
|
attachments.set(native_doc, :entity_markers, entity_markers)
|
|
83
|
-
Document.new(native_doc, ctx)
|
|
83
|
+
Wrappers::Document.new(native_doc, ctx)
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
# Tolerant HTML parsing through libxml2's HTML mode: implied
|
|
@@ -90,7 +90,7 @@ module Moxml
|
|
|
90
90
|
def parse_html(html, _options = {}, _context = nil)
|
|
91
91
|
html_string = html.is_a?(IO) || html.is_a?(StringIO) ? html.read : html.to_s
|
|
92
92
|
native_doc = ::Nokogiri::HTML(html_string)
|
|
93
|
-
Document.new(native_doc, _context || Context.new(:nokogiri))
|
|
93
|
+
Wrappers::Document.new(native_doc, _context || Context.new(:nokogiri))
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
# Nokogiri parses with `config.recover` unless strict, so
|
data/lib/moxml/adapter/oga.rb
CHANGED
data/lib/moxml/adapter/ox.rb
CHANGED
data/lib/moxml/adapter/rexml.rb
CHANGED
data/lib/moxml/attribute.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Moxml
|
|
4
|
-
|
|
4
|
+
module Attribute
|
|
5
|
+
include Node
|
|
6
|
+
|
|
5
7
|
# Immutable between name= writes (which clear it via
|
|
6
8
|
# clear_native_memo!), unlike element names that can change via
|
|
7
9
|
# native adoption; the memo removes an adapter read per access.
|
|
@@ -64,7 +66,7 @@ module Moxml
|
|
|
64
66
|
|
|
65
67
|
def namespace
|
|
66
68
|
ns = adapter.namespace(@native)
|
|
67
|
-
ns && Namespace.new(ns, context)
|
|
69
|
+
ns && Wrappers::Namespace.new(ns, context)
|
|
68
70
|
end
|
|
69
71
|
|
|
70
72
|
def namespace=(ns)
|
data/lib/moxml/cdata.rb
CHANGED
data/lib/moxml/comment.rb
CHANGED
data/lib/moxml/context.rb
CHANGED
data/lib/moxml/declaration.rb
CHANGED
data/lib/moxml/doctype.rb
CHANGED
|
@@ -13,7 +13,9 @@ module Moxml
|
|
|
13
13
|
# Most adapters do not currently implement these methods. If you need DOCTYPE
|
|
14
14
|
# information, consider using adapter-specific methods or parsing the serialized
|
|
15
15
|
# XML manually.
|
|
16
|
-
|
|
16
|
+
module Doctype
|
|
17
|
+
include Node
|
|
18
|
+
|
|
17
19
|
# Returns the DOCTYPE name (root element name)
|
|
18
20
|
#
|
|
19
21
|
# @return [String, nil] the DOCTYPE name
|
data/lib/moxml/document.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Moxml
|
|
4
|
-
|
|
4
|
+
module Document
|
|
5
|
+
include Node
|
|
6
|
+
|
|
5
7
|
attr_accessor :has_xml_declaration
|
|
6
8
|
|
|
7
9
|
def initialize(native, context, adapter = nil, node_type = nil)
|
|
@@ -61,30 +63,30 @@ module Moxml
|
|
|
61
63
|
end
|
|
62
64
|
|
|
63
65
|
def create_element(name)
|
|
64
|
-
Element.new(adapter.create_element(name, owner_doc: @native), context)
|
|
66
|
+
Wrappers::Element.new(adapter.create_element(name, owner_doc: @native), context)
|
|
65
67
|
end
|
|
66
68
|
|
|
67
69
|
def create_text(content)
|
|
68
|
-
Text.new(adapter.create_text(content, owner_doc: @native), context)
|
|
70
|
+
Wrappers::Text.new(adapter.create_text(content, owner_doc: @native), context)
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
def create_cdata(content)
|
|
72
|
-
Cdata.new(adapter.create_cdata(content, owner_doc: @native), context)
|
|
74
|
+
Wrappers::Cdata.new(adapter.create_cdata(content, owner_doc: @native), context)
|
|
73
75
|
end
|
|
74
76
|
|
|
75
77
|
def create_comment(content)
|
|
76
|
-
Comment.new(adapter.create_comment(content, owner_doc: @native), context)
|
|
78
|
+
Wrappers::Comment.new(adapter.create_comment(content, owner_doc: @native), context)
|
|
77
79
|
end
|
|
78
80
|
|
|
79
81
|
def create_doctype(name, external_id, system_id)
|
|
80
|
-
Doctype.new(
|
|
82
|
+
Wrappers::Doctype.new(
|
|
81
83
|
adapter.create_doctype(name, external_id, system_id),
|
|
82
84
|
context,
|
|
83
85
|
)
|
|
84
86
|
end
|
|
85
87
|
|
|
86
88
|
def create_processing_instruction(target, content)
|
|
87
|
-
ProcessingInstruction.new(
|
|
89
|
+
Wrappers::ProcessingInstruction.new(
|
|
88
90
|
adapter.create_processing_instruction(target, content),
|
|
89
91
|
context,
|
|
90
92
|
)
|
|
@@ -93,11 +95,11 @@ module Moxml
|
|
|
93
95
|
def create_declaration(version = "1.0", encoding = "UTF-8",
|
|
94
96
|
standalone = nil)
|
|
95
97
|
decl = adapter.create_declaration(version, encoding, standalone)
|
|
96
|
-
Declaration.new(decl, context)
|
|
98
|
+
Wrappers::Declaration.new(decl, context)
|
|
97
99
|
end
|
|
98
100
|
|
|
99
101
|
def create_entity_reference(name)
|
|
100
|
-
EntityReference.new(adapter.create_entity_reference(name), context)
|
|
102
|
+
Wrappers::EntityReference.new(adapter.create_entity_reference(name), context)
|
|
101
103
|
end
|
|
102
104
|
|
|
103
105
|
def add_child(node)
|
data/lib/moxml/element.rb
CHANGED
|
@@ -120,7 +120,7 @@ module Moxml
|
|
|
120
120
|
# mint, so the first name/value/attribute? access skips the
|
|
121
121
|
# context hop and the adapter's type probe.
|
|
122
122
|
@attributes ||= adapter.attributes(@native).map do |attr|
|
|
123
|
-
a = Attribute.new(attr, context, adapter, :attribute)
|
|
123
|
+
a = Wrappers::Attribute.new(attr, context, adapter, :attribute)
|
|
124
124
|
a.parent_node = self
|
|
125
125
|
a
|
|
126
126
|
end
|
|
@@ -182,7 +182,7 @@ module Moxml
|
|
|
182
182
|
# it's NOT the same as namespaces.first
|
|
183
183
|
def namespace
|
|
184
184
|
ns = adapter.namespace(@native)
|
|
185
|
-
ns && Namespace.new(ns, context)
|
|
185
|
+
ns && Wrappers::Namespace.new(ns, context)
|
|
186
186
|
end
|
|
187
187
|
|
|
188
188
|
# add the prefix to the element name
|
|
@@ -216,7 +216,7 @@ module Moxml
|
|
|
216
216
|
return @namespace_definitions unless @namespace_definitions.nil?
|
|
217
217
|
|
|
218
218
|
@namespace_definitions = adapter.namespace_definitions(@native).map do |ns|
|
|
219
|
-
Namespace.new(ns, context)
|
|
219
|
+
Wrappers::Namespace.new(ns, context)
|
|
220
220
|
end
|
|
221
221
|
end
|
|
222
222
|
|
|
@@ -225,7 +225,7 @@ module Moxml
|
|
|
225
225
|
# scope. The shape materialize records carry (issue #138).
|
|
226
226
|
def declared_namespaces
|
|
227
227
|
adapter.namespace_definitions(@native).map do |ns|
|
|
228
|
-
wrapper = Namespace.new(ns, context)
|
|
228
|
+
wrapper = Wrappers::Namespace.new(ns, context)
|
|
229
229
|
[wrapper.prefix, wrapper.uri]
|
|
230
230
|
end
|
|
231
231
|
end
|
|
@@ -236,7 +236,7 @@ module Moxml
|
|
|
236
236
|
generation = context.namespace_scope_generation
|
|
237
237
|
if @in_scope_namespaces.nil? || @in_scope_generation != generation
|
|
238
238
|
@in_scope_namespaces = adapter.in_scope_namespaces(@native).map do |ns|
|
|
239
|
-
Namespace.new(ns, context)
|
|
239
|
+
Wrappers::Namespace.new(ns, context)
|
|
240
240
|
end
|
|
241
241
|
@in_scope_generation = generation
|
|
242
242
|
end
|
|
@@ -363,7 +363,8 @@ module Moxml
|
|
|
363
363
|
end
|
|
364
364
|
end
|
|
365
365
|
|
|
366
|
-
|
|
366
|
+
module Element
|
|
367
|
+
include Node
|
|
367
368
|
include ElementBehavior
|
|
368
369
|
end
|
|
369
370
|
end
|
|
@@ -78,12 +78,12 @@ module Moxml
|
|
|
78
78
|
def append_chunk(parent, type, payload)
|
|
79
79
|
case type
|
|
80
80
|
when :text
|
|
81
|
-
parent.add_child(::Moxml::Text.new(
|
|
81
|
+
parent.add_child(::Moxml::Wrappers::Text.new(
|
|
82
82
|
@adapter.create_native_text(payload), @ctx
|
|
83
83
|
))
|
|
84
84
|
when :eref
|
|
85
85
|
parent.add_child(
|
|
86
|
-
::Moxml::EntityReference.new(
|
|
86
|
+
::Moxml::Wrappers::EntityReference.new(
|
|
87
87
|
@adapter.create_native_entity_reference(payload),
|
|
88
88
|
@ctx,
|
|
89
89
|
),
|
data/lib/moxml/namespace.rb
CHANGED
data/lib/moxml/node.rb
CHANGED
|
@@ -20,15 +20,22 @@ module Moxml
|
|
|
20
20
|
# otherwise pay the context hop and the type probe again on its
|
|
21
21
|
# first access.
|
|
22
22
|
def initialize(native, context, adapter = nil, node_type = nil)
|
|
23
|
+
prime_contract(native, context, adapter, node_type)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Update native reference after identity-changing operations
|
|
27
|
+
# (e.g., LibXML doc.root= creates a new Ruby wrapper)
|
|
28
|
+
# Contract priming shared by the constructor and the extend-in-place
|
|
29
|
+
# mint (#230): an extended native IS its own @native.
|
|
30
|
+
def prime_contract(native, context, adapter = nil, node_type = nil)
|
|
23
31
|
@context = context
|
|
24
32
|
@native = native
|
|
25
33
|
@parent_node = nil
|
|
26
34
|
@adapter = adapter
|
|
27
35
|
@node_type_cached = node_type
|
|
36
|
+
self
|
|
28
37
|
end
|
|
29
38
|
|
|
30
|
-
# Update native reference after identity-changing operations
|
|
31
|
-
# (e.g., LibXML doc.root= creates a new Ruby wrapper)
|
|
32
39
|
def refresh_native!(new_native)
|
|
33
40
|
unless new_native.equal?(@native)
|
|
34
41
|
context.unregister_wrapper(@native)
|
|
@@ -48,7 +55,7 @@ module Moxml
|
|
|
48
55
|
end
|
|
49
56
|
|
|
50
57
|
def document
|
|
51
|
-
|
|
58
|
+
Moxml::Node.wrap(adapter.document(@native), context)
|
|
52
59
|
end
|
|
53
60
|
|
|
54
61
|
def parent
|
|
@@ -255,7 +262,7 @@ module Moxml
|
|
|
255
262
|
return nil unless element?
|
|
256
263
|
|
|
257
264
|
ns = adapter.namespace(@native)
|
|
258
|
-
ns && Namespace.new(ns, context)
|
|
265
|
+
ns && Wrappers::Namespace.new(ns, context)
|
|
259
266
|
end
|
|
260
267
|
|
|
261
268
|
# Returns all namespace definitions on this node
|
|
@@ -264,13 +271,26 @@ module Moxml
|
|
|
264
271
|
return [] unless element?
|
|
265
272
|
|
|
266
273
|
adapter.namespace_definitions(@native).map do |ns|
|
|
267
|
-
Namespace.new(ns, context)
|
|
274
|
+
Wrappers::Namespace.new(ns, context)
|
|
268
275
|
end
|
|
269
276
|
end
|
|
270
277
|
|
|
271
278
|
# Recursively yield all descendant nodes
|
|
272
279
|
# Used by XPath descendant-or-self and descendant axes
|
|
273
280
|
def each_node(&block)
|
|
281
|
+
unless block
|
|
282
|
+
# Eager materialization: the leptris C-side walk rb_yields
|
|
283
|
+
# from the C callback and segfaults across fiber-suspended
|
|
284
|
+
# enumerator frames, so the no-block form never enters it.
|
|
285
|
+
nodes = []
|
|
286
|
+
each_node { |node| nodes << node }
|
|
287
|
+
return nodes.each
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# Adapters with a C-side subtree walk take it in one
|
|
291
|
+
# dispatch; the recursive children walk stays the fallback.
|
|
292
|
+
return if adapter.walk_descendants(@native, context, &block)
|
|
293
|
+
|
|
274
294
|
children.each do |child|
|
|
275
295
|
yield child
|
|
276
296
|
child.each_node(&block)
|
|
@@ -414,7 +434,7 @@ module Moxml
|
|
|
414
434
|
# Native equality goes through the adapter: engines with a
|
|
415
435
|
# native read layer hand out two wrapper classes over one C
|
|
416
436
|
# node, and raw native == is false across that seam.
|
|
417
|
-
|
|
437
|
+
other.is_a?(Moxml::Node) &&
|
|
418
438
|
adapter.same_node?(@native, other.native)
|
|
419
439
|
end
|
|
420
440
|
|
|
@@ -486,7 +506,7 @@ module Moxml
|
|
|
486
506
|
|
|
487
507
|
def prepare_node(node)
|
|
488
508
|
case node
|
|
489
|
-
when String then
|
|
509
|
+
when String then Moxml::Node.wrap(adapter.create_text(node), context)
|
|
490
510
|
when Node then node
|
|
491
511
|
else
|
|
492
512
|
raise Moxml::DocumentStructureError.new(
|
|
@@ -512,11 +532,35 @@ module Moxml
|
|
|
512
532
|
end
|
|
513
533
|
end
|
|
514
534
|
|
|
515
|
-
|
|
535
|
+
module Node
|
|
516
536
|
include NodeBehavior
|
|
517
537
|
|
|
538
|
+
# Instantiation shells per type — the contract constants
|
|
539
|
+
# (Element, Text, ...) are modules since issue #230, so wrappers
|
|
540
|
+
# mint through Wrappers::*.
|
|
518
541
|
def self.node_type_map
|
|
519
542
|
@node_type_map ||= {
|
|
543
|
+
element: Wrappers::Element,
|
|
544
|
+
text: Wrappers::Text,
|
|
545
|
+
cdata: Wrappers::Cdata,
|
|
546
|
+
comment: Wrappers::Comment,
|
|
547
|
+
processing_instruction: Wrappers::ProcessingInstruction,
|
|
548
|
+
document: Wrappers::Document,
|
|
549
|
+
declaration: Wrappers::Declaration,
|
|
550
|
+
doctype: Wrappers::Doctype,
|
|
551
|
+
attribute: Wrappers::Attribute,
|
|
552
|
+
entity_reference: Wrappers::EntityReference,
|
|
553
|
+
}.freeze
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
# The contract module for a type — what an in-place extended
|
|
557
|
+
# native carries instead of a wrapper shell.
|
|
558
|
+
def self.contract_module(type)
|
|
559
|
+
contract_modules[type]
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
def self.contract_modules
|
|
563
|
+
@contract_modules ||= {
|
|
520
564
|
element: Element,
|
|
521
565
|
text: Text,
|
|
522
566
|
cdata: Cdata,
|
|
@@ -538,8 +582,17 @@ module Moxml
|
|
|
538
582
|
|
|
539
583
|
adapter = adapter(context)
|
|
540
584
|
type = adapter.node_type(node)
|
|
541
|
-
klass = node_type_map[type] || self
|
|
542
585
|
|
|
586
|
+
# Extend-in-place (issue #230): adapters whose natives can
|
|
587
|
+
# carry the contract modules directly (leptris TypedData) mint
|
|
588
|
+
# the native itself as the wrapper — @native is self.
|
|
589
|
+
if (extended = adapter.wrap_native(node, type, context))
|
|
590
|
+
extended.prime_contract(node, context, adapter, type)
|
|
591
|
+
context.register_wrapper(node, extended)
|
|
592
|
+
return extended
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
klass = node_type_map[type] || Wrappers::Node
|
|
543
596
|
klass.new(node, context, adapter, type)
|
|
544
597
|
.tap { |wrapper| context.register_wrapper(node, wrapper) }
|
|
545
598
|
end
|
data/lib/moxml/text.rb
CHANGED
data/lib/moxml/version.rb
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Moxml
|
|
4
|
+
# Instantiation shells (issue #230): the node-type constants are
|
|
5
|
+
# contract MODULES so leptris TypedData natives can carry them in
|
|
6
|
+
# place — wrappers are minted through these shells for native
|
|
7
|
+
# objects that cannot take the modules in place (binding-layer
|
|
8
|
+
# natives on every adapter, and all natives on non-leptris ones).
|
|
9
|
+
module Wrappers
|
|
10
|
+
Node = Class.new do
|
|
11
|
+
include Moxml::Node
|
|
12
|
+
end
|
|
13
|
+
Element = Class.new(Node) do
|
|
14
|
+
include Moxml::Element
|
|
15
|
+
end
|
|
16
|
+
Text = Class.new(Node) do
|
|
17
|
+
include Moxml::Text
|
|
18
|
+
end
|
|
19
|
+
Cdata = Class.new(Node) do
|
|
20
|
+
include Moxml::Cdata
|
|
21
|
+
end
|
|
22
|
+
Comment = Class.new(Node) do
|
|
23
|
+
include Moxml::Comment
|
|
24
|
+
end
|
|
25
|
+
ProcessingInstruction = Class.new(Node) do
|
|
26
|
+
include Moxml::ProcessingInstruction
|
|
27
|
+
end
|
|
28
|
+
Document = Class.new(Node) do
|
|
29
|
+
include Moxml::Document
|
|
30
|
+
end
|
|
31
|
+
Declaration = Class.new(Node) do
|
|
32
|
+
include Moxml::Declaration
|
|
33
|
+
end
|
|
34
|
+
Doctype = Class.new(Node) do
|
|
35
|
+
include Moxml::Doctype
|
|
36
|
+
end
|
|
37
|
+
Attribute = Class.new(Node) do
|
|
38
|
+
include Moxml::Attribute
|
|
39
|
+
end
|
|
40
|
+
EntityReference = Class.new(Node) do
|
|
41
|
+
include Moxml::EntityReference
|
|
42
|
+
end
|
|
43
|
+
Namespace = Class.new(Node) do
|
|
44
|
+
include Moxml::Namespace
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/moxml.rb
CHANGED
|
@@ -67,6 +67,7 @@ module Moxml
|
|
|
67
67
|
autoload :Config, "moxml/config"
|
|
68
68
|
autoload :Context, "moxml/context"
|
|
69
69
|
autoload :Node, "moxml/node"
|
|
70
|
+
autoload :Wrappers, "moxml/wrappers"
|
|
70
71
|
autoload :NodeSet, "moxml/node_set"
|
|
71
72
|
autoload :LazyNodeSet, "moxml/lazy_node_set"
|
|
72
73
|
autoload :Document, "moxml/document"
|
|
@@ -22,9 +22,8 @@
|
|
|
22
22
|
describe "fragment parsing (issue #188)" do
|
|
23
23
|
it "returns the fragment's top-level nodes uniformly" do
|
|
24
24
|
nodes = ctx.parse_fragment(%(<a x="1">t1</a><b/>tail))
|
|
25
|
-
expect(nodes.map(&:
|
|
26
|
-
|
|
27
|
-
)
|
|
25
|
+
expect(nodes.map(&:element?)).to eq([true, true, false])
|
|
26
|
+
expect(nodes.map(&:text?)).to eq([false, false, true])
|
|
28
27
|
expect(nodes[0]["x"]).to eq("1")
|
|
29
28
|
expect(nodes[0].text).to eq("t1")
|
|
30
29
|
expect(nodes[2].content).to eq("tail")
|
|
@@ -76,12 +76,12 @@ RSpec.shared_examples "Entity Reference Whitespace Preservation" do
|
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
children = doc.root.children
|
|
79
|
-
types = children.map(&:
|
|
79
|
+
types = children.map(&:entity_reference?)
|
|
80
80
|
|
|
81
81
|
expect(types).to eq([
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
true,
|
|
83
|
+
false,
|
|
84
|
+
true,
|
|
85
85
|
])
|
|
86
86
|
expect(children[1].content).to eq(" ")
|
|
87
87
|
end
|
|
@@ -93,10 +93,14 @@ RSpec.describe Moxml::Adapter::Leptris do
|
|
|
93
93
|
doc = ctx.parse('<?xml version="1.0"?><?pi-prolog before?><root/><?pi-epilog after?><!-- tail -->')
|
|
94
94
|
kids = doc.children.to_a
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
shape = kids.map do |k|
|
|
97
|
+
if k.processing_instruction?
|
|
98
|
+
:pi
|
|
99
|
+
else
|
|
100
|
+
k.element? ? :element : :comment
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
expect(shape).to eq(%i[pi element pi comment])
|
|
100
104
|
expect(kids.select(&:processing_instruction?).map(&:target)).to eq(%w[pi-prolog pi-epilog])
|
|
101
105
|
expect(kids[0].content).to eq("before")
|
|
102
106
|
expect(doc.to_xml.index("pi-epilog")).to be > doc.to_xml.index("</root>")
|
|
@@ -606,14 +610,15 @@ RSpec.describe Moxml::Adapter::Leptris do
|
|
|
606
610
|
it "skips the marker split for entity-free documents" do
|
|
607
611
|
doc = ctx.parse("<root>\n <a>text</a>\n <b/>\n</root>")
|
|
608
612
|
kids = doc.root.children.to_a
|
|
609
|
-
|
|
613
|
+
shape = kids.map { |k| k.text? ? :text : :element }
|
|
614
|
+
expect(shape).to eq(%i[text element text element text])
|
|
610
615
|
expect(described_class.entity_bearing?(doc.root.native)).to be(false)
|
|
611
616
|
end
|
|
612
617
|
|
|
613
618
|
it "splits markers when the source carries entities" do
|
|
614
619
|
doc = ctx.parse("<root><a>pre post</a></root>")
|
|
615
620
|
kids = doc.at_xpath("//a").children.to_a
|
|
616
|
-
expect(kids.map(
|
|
621
|
+
expect(kids.map { |k| k.is_a?(Moxml::EntityReference) }).to include(true)
|
|
617
622
|
expect(described_class.entity_bearing?(doc.root.native)).to be(true)
|
|
618
623
|
end
|
|
619
624
|
|
|
@@ -631,7 +636,7 @@ RSpec.describe Moxml::Adapter::Leptris do
|
|
|
631
636
|
er = doc.create_entity_reference("nbsp")
|
|
632
637
|
doc.at_xpath("//a").add_child(er)
|
|
633
638
|
expect(described_class.entity_bearing?(doc.root.native)).to be(true)
|
|
634
|
-
expect(doc.at_xpath("//a").children.to_a.map(
|
|
639
|
+
expect(doc.at_xpath("//a").children.to_a.map { |k| k.is_a?(Moxml::EntityReference) }).to include(true)
|
|
635
640
|
end
|
|
636
641
|
end
|
|
637
642
|
|
|
@@ -702,11 +707,11 @@ RSpec.describe Moxml::Adapter::Leptris do
|
|
|
702
707
|
expect(decl.digest).to be_nil
|
|
703
708
|
end
|
|
704
709
|
# comments and PIs hash in C
|
|
705
|
-
kinds = doc.root.children.map { |n| [n.
|
|
706
|
-
comment = kinds.find { |
|
|
707
|
-
pi = kinds.find { |
|
|
708
|
-
expect(comment[
|
|
709
|
-
expect(pi[
|
|
710
|
+
kinds = doc.root.children.map { |n| [n.is_a?(Moxml::Comment), n.is_a?(Moxml::ProcessingInstruction), n.digest] }
|
|
711
|
+
comment = kinds.find { |c, _, _| c }
|
|
712
|
+
pi = kinds.find { |_, p, _| p }
|
|
713
|
+
expect(comment[2]).to be_a(Integer)
|
|
714
|
+
expect(pi[2]).to be_a(Integer)
|
|
710
715
|
end
|
|
711
716
|
end
|
|
712
717
|
end
|
|
@@ -113,7 +113,7 @@ RSpec.describe Moxml::Adapter::Libxml do
|
|
|
113
113
|
doc = context.parse("<root><a/><b/></root>")
|
|
114
114
|
a = doc.root.children.first
|
|
115
115
|
b = doc.root.children.last
|
|
116
|
-
eref = Moxml::EntityReference.new(
|
|
116
|
+
eref = Moxml::Wrappers::EntityReference.new(
|
|
117
117
|
adapter.create_native_entity_reference("amp"), context
|
|
118
118
|
)
|
|
119
119
|
a.add_child(eref)
|
|
@@ -125,7 +125,7 @@ RSpec.describe Moxml::Adapter::Libxml do
|
|
|
125
125
|
it "returns [refs, sequence] when both are registered for the element" do
|
|
126
126
|
doc = context.parse("<root><a>text</a></root>")
|
|
127
127
|
a = doc.root.children.first
|
|
128
|
-
eref = Moxml::EntityReference.new(
|
|
128
|
+
eref = Moxml::Wrappers::EntityReference.new(
|
|
129
129
|
adapter.create_native_entity_reference("amp"), context
|
|
130
130
|
)
|
|
131
131
|
a.add_child(eref)
|
|
@@ -144,7 +144,7 @@ RSpec.describe Moxml::Adapter::Libxml do
|
|
|
144
144
|
it "preserves normal child indentation when entity refs are present" do
|
|
145
145
|
doc = context.parse("<root><a><b/></a></root>")
|
|
146
146
|
a = doc.root.children.first
|
|
147
|
-
eref = Moxml::EntityReference.new(
|
|
147
|
+
eref = Moxml::Wrappers::EntityReference.new(
|
|
148
148
|
adapter.create_native_entity_reference("amp"), context
|
|
149
149
|
)
|
|
150
150
|
a.add_child(eref)
|
data/spec/moxml/node_set_spec.rb
CHANGED
|
@@ -45,7 +45,7 @@ RSpec.describe Moxml::NodeSet do
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
it "wraps through the Enumerable surface" do
|
|
48
|
-
expect(doc.root.children.map(
|
|
48
|
+
expect(doc.root.children.map { |c| c.is_a?(Moxml::Element) }.uniq).to eq([true])
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
end
|
data/spec/moxml/node_spec.rb
CHANGED
|
@@ -84,7 +84,7 @@ RSpec.describe Moxml::Node do
|
|
|
84
84
|
|
|
85
85
|
describe "#content" do
|
|
86
86
|
it "returns empty string on base Node" do
|
|
87
|
-
expect(
|
|
87
|
+
expect(Moxml::Wrappers::Node.new(nil, context).content).to eq("")
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
it "returns text on Element" 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.
|
|
4
|
+
version: 0.5.49
|
|
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-16 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
|
|
@@ -271,6 +271,7 @@ files:
|
|
|
271
271
|
- lib/moxml/signature/verifier.rb
|
|
272
272
|
- lib/moxml/text.rb
|
|
273
273
|
- lib/moxml/version.rb
|
|
274
|
+
- lib/moxml/wrappers.rb
|
|
274
275
|
- lib/moxml/xml_emitter.rb
|
|
275
276
|
- lib/moxml/xml_utils.rb
|
|
276
277
|
- lib/moxml/xml_utils/encoder.rb
|