moxml 0.5.46 → 0.5.48
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/Gemfile +1 -1
- data/lib/moxml/adapter/base.rb +8 -0
- data/lib/moxml/adapter/leptris.rb +80 -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 +14 -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 +91 -45
- 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 +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fbe45e0b5017c94650ed10dde4e726843ad5a820005ac4a1f653d5747ef04f71
|
|
4
|
+
data.tar.gz: 14f003f4f15ff1b9a40429654a7435485cb20ca62e88f6b9dc21e1120e9c85dd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b6bcf2d9d9b6a34bbd56afc5076421c22e107ac33e9a8adc06ebe0329b7cab59e038ace45e0cb2d14debe8ba16c8cd606af49d8994bf59137e51d2679487295d
|
|
7
|
+
data.tar.gz: 22ea33b5bc99974709cc8cbcf670dc39fdce033fcce310353cda9aa15568129a283055a8e8975f211d67a8167fa6f87597db0d81e4935f77864a6d58ccc1a9dd
|
data/Gemfile
CHANGED
data/lib/moxml/adapter/base.rb
CHANGED
|
@@ -133,6 +133,14 @@ 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
|
+
|
|
136
144
|
def same_node?(one, other)
|
|
137
145
|
one == other
|
|
138
146
|
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,28 @@ 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
|
+
|
|
139
179
|
def record_native_doc(root_native, doc)
|
|
140
180
|
@native_doc_roots[root_native] = doc
|
|
141
181
|
end
|
|
@@ -165,7 +205,7 @@ module Moxml
|
|
|
165
205
|
def doc_for(node)
|
|
166
206
|
# The 1.9.163.5 native layer exposes the owning document
|
|
167
207
|
# directly; the root climb serves older bindings.
|
|
168
|
-
return node
|
|
208
|
+
return NN_DOCUMENT.bind_call(node) if NATIVE_MUTATIONS_COHERENT
|
|
169
209
|
|
|
170
210
|
current = node
|
|
171
211
|
current = current.parent while current&.parent
|
|
@@ -201,7 +241,7 @@ module Moxml
|
|
|
201
241
|
::Leptris::XML::FFI::C14N_1_0, nil,
|
|
202
242
|
mode: ::Leptris::XML::FFI::C14N_MODE_CANONICAL
|
|
203
243
|
)
|
|
204
|
-
wrapper = Moxml::Document.new(native_doc, Moxml::Context.new(:leptris))
|
|
244
|
+
wrapper = Moxml::Wrappers::Document.new(native_doc, Moxml::Context.new(:leptris))
|
|
205
245
|
reference = Moxml::C14n::Inclusive10.new.canonicalize(wrapper.root)
|
|
206
246
|
native == reference
|
|
207
247
|
rescue StandardError
|
|
@@ -333,7 +373,14 @@ module Moxml
|
|
|
333
373
|
# document-plus-attachment probe here cost more than the
|
|
334
374
|
# read itself).
|
|
335
375
|
def bare_attr_value(element, name)
|
|
336
|
-
|
|
376
|
+
# Exact-name C read: bare names target no-namespace
|
|
377
|
+
# attributes (the documented contract — a bare "y" never
|
|
378
|
+
# resolves a "p:y" sibling).
|
|
379
|
+
value = if NATIVE_READ_LAYER && element.is_a?(NN)
|
|
380
|
+
NN_ATTRIBUTE.bind_call(element, name.to_s)
|
|
381
|
+
else
|
|
382
|
+
element[name.to_s]
|
|
383
|
+
end
|
|
337
384
|
if !NATIVE_STRINGS_UTF8 && NATIVE_READ_LAYER &&
|
|
338
385
|
element.is_a?(::Leptris::XML::NativeNode) &&
|
|
339
386
|
value.is_a?(String)
|
|
@@ -376,7 +423,7 @@ module Moxml
|
|
|
376
423
|
create_document
|
|
377
424
|
end
|
|
378
425
|
ctx = _context || Context.new(:leptris)
|
|
379
|
-
doc = Document.new(native_doc, ctx)
|
|
426
|
+
doc = Wrappers::Document.new(native_doc, ctx)
|
|
380
427
|
|
|
381
428
|
if options[:noblanks] && !ENGINE_NOBLANKS_SAFE
|
|
382
429
|
# The engine's DROP_WS_TEXT trims boundary whitespace of
|
|
@@ -451,7 +498,7 @@ module Moxml
|
|
|
451
498
|
end
|
|
452
499
|
attachments.set(native_doc, :entity_markers, false)
|
|
453
500
|
bump_serialize_generation
|
|
454
|
-
Document.new(native_doc, _context || Context.new(:leptris))
|
|
501
|
+
Wrappers::Document.new(native_doc, _context || Context.new(:leptris))
|
|
455
502
|
end
|
|
456
503
|
|
|
457
504
|
# nil when no parse flag is requested — the binding treats a
|
|
@@ -711,13 +758,15 @@ module Moxml
|
|
|
711
758
|
end
|
|
712
759
|
|
|
713
760
|
def processing_instruction_target(node)
|
|
761
|
+
return to_binding(node).target if NATIVE_READ_LAYER && node.is_a?(NN)
|
|
762
|
+
|
|
714
763
|
node.target
|
|
715
764
|
end
|
|
716
765
|
|
|
717
766
|
def node_type(node)
|
|
718
767
|
if NATIVE_READ_LAYER &&
|
|
719
768
|
node.is_a?(::Leptris::XML::NativeNode)
|
|
720
|
-
type = node
|
|
769
|
+
type = NN_NODE_TYPE.bind_call(node)
|
|
721
770
|
# The native layer spells PIs :pi; the wrapper contract
|
|
722
771
|
# (node_type_map) says :processing_instruction.
|
|
723
772
|
return :processing_instruction if type == :pi
|
|
@@ -765,11 +814,12 @@ module Moxml
|
|
|
765
814
|
|
|
766
815
|
if NATIVE_READ_LAYER && node.is_a?(::Leptris::XML::NativeNode)
|
|
767
816
|
# PIs expose no name through the native layer.
|
|
768
|
-
return to_binding(node).target.to_s if node
|
|
817
|
+
return to_binding(node).target.to_s if NN_NODE_TYPE.bind_call(node) == :pi
|
|
769
818
|
|
|
770
|
-
|
|
819
|
+
name = NN_NAME.bind_call(node)
|
|
820
|
+
return name if NATIVE_STRINGS_UTF8
|
|
771
821
|
|
|
772
|
-
|
|
822
|
+
name.dup.force_encoding(Encoding::UTF_8)
|
|
773
823
|
end
|
|
774
824
|
|
|
775
825
|
node.name.to_s.dup.force_encoding("UTF-8")
|
|
@@ -808,7 +858,7 @@ module Moxml
|
|
|
808
858
|
# the wrapper's memo supplies the flag, so deriving it
|
|
809
859
|
# here costs no C parent climb per call.
|
|
810
860
|
natives = if NATIVE_BULK_FIXED
|
|
811
|
-
node.
|
|
861
|
+
NN_CHILDREN.bind_call(node).to_a
|
|
812
862
|
else
|
|
813
863
|
bulk_native_children(node)
|
|
814
864
|
end
|
|
@@ -864,7 +914,7 @@ module Moxml
|
|
|
864
914
|
|
|
865
915
|
def parent(node)
|
|
866
916
|
if NATIVE_READ_LAYER && node.is_a?(::Leptris::XML::NativeNode)
|
|
867
|
-
parent = node
|
|
917
|
+
parent = NN_PARENT.bind_call(node)
|
|
868
918
|
return parent if parent
|
|
869
919
|
|
|
870
920
|
doc = doc_for(node)
|
|
@@ -987,7 +1037,7 @@ module Moxml
|
|
|
987
1037
|
end
|
|
988
1038
|
|
|
989
1039
|
def next_sibling(node)
|
|
990
|
-
return node
|
|
1040
|
+
return NN_NEXT_SIBLING.bind_call(node) if NATIVE_READ_LAYER &&
|
|
991
1041
|
node.is_a?(::Leptris::XML::NativeNode)
|
|
992
1042
|
|
|
993
1043
|
node.next_sibling if node.is_a?(::Leptris::XML::Node)
|
|
@@ -1114,6 +1164,12 @@ module Moxml
|
|
|
1114
1164
|
bump_serialize_generation
|
|
1115
1165
|
return child
|
|
1116
1166
|
end
|
|
1167
|
+
if NATIVE_MUTATIONS_COHERENT && parent.is_a?(NN) && child.is_a?(NN)
|
|
1168
|
+
doc = NN_DOCUMENT.bind_call(parent)
|
|
1169
|
+
child = doc.create_text_node(child) if child.is_a?(String)
|
|
1170
|
+
return NN_ADD_CHILD.bind_call(parent, child)
|
|
1171
|
+
end
|
|
1172
|
+
|
|
1117
1173
|
child = parent.document.create_text_node(child) if child.is_a?(String)
|
|
1118
1174
|
parent.add_child(child)
|
|
1119
1175
|
end
|
|
@@ -1200,9 +1256,10 @@ module Moxml
|
|
|
1200
1256
|
|
|
1201
1257
|
def text_content(node)
|
|
1202
1258
|
if NATIVE_READ_LAYER && node.is_a?(::Leptris::XML::NativeNode)
|
|
1203
|
-
|
|
1259
|
+
content = NN_CONTENT.bind_call(node)
|
|
1260
|
+
return content if NATIVE_STRINGS_UTF8
|
|
1204
1261
|
|
|
1205
|
-
|
|
1262
|
+
content.dup.force_encoding(Encoding::UTF_8)
|
|
1206
1263
|
end
|
|
1207
1264
|
|
|
1208
1265
|
# Frequency-ordered: elements dominate reads; they paid
|
|
@@ -1246,26 +1303,35 @@ module Moxml
|
|
|
1246
1303
|
end
|
|
1247
1304
|
|
|
1248
1305
|
def cdata_content(node)
|
|
1306
|
+
return NN_CONTENT.bind_call(node) if NATIVE_READ_LAYER && node.is_a?(NN)
|
|
1307
|
+
|
|
1249
1308
|
node.content
|
|
1250
1309
|
end
|
|
1251
1310
|
|
|
1252
1311
|
def set_cdata_content(node, content)
|
|
1312
|
+
node = to_binding(node) if NATIVE_READ_LAYER
|
|
1253
1313
|
node.content = content.to_s
|
|
1254
1314
|
end
|
|
1255
1315
|
|
|
1256
1316
|
def comment_content(node)
|
|
1317
|
+
return NN_CONTENT.bind_call(node) if NATIVE_READ_LAYER && node.is_a?(NN)
|
|
1318
|
+
|
|
1257
1319
|
node.content
|
|
1258
1320
|
end
|
|
1259
1321
|
|
|
1260
1322
|
def set_comment_content(node, content)
|
|
1323
|
+
node = to_binding(node) if NATIVE_READ_LAYER
|
|
1261
1324
|
node.content = content.to_s
|
|
1262
1325
|
end
|
|
1263
1326
|
|
|
1264
1327
|
def processing_instruction_content(node)
|
|
1328
|
+
return NN_CONTENT.bind_call(node) if NATIVE_READ_LAYER && node.is_a?(NN)
|
|
1329
|
+
|
|
1265
1330
|
node.content
|
|
1266
1331
|
end
|
|
1267
1332
|
|
|
1268
1333
|
def set_processing_instruction_content(node, content)
|
|
1334
|
+
node = to_binding(node) if NATIVE_READ_LAYER
|
|
1269
1335
|
node.data = content.to_s
|
|
1270
1336
|
end
|
|
1271
1337
|
|
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
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Moxml
|
|
4
|
-
|
|
4
|
+
# Instance behavior for Moxml::Element, extracted so the leptris
|
|
5
|
+
# adapter can extend natives with it in place (issue #230); the
|
|
6
|
+
# class remains the consumer-facing contract.
|
|
7
|
+
module ElementBehavior
|
|
5
8
|
def name
|
|
6
9
|
# The adapter read is an FFI call plus (on several adapters) a
|
|
7
10
|
# defensive string copy; names only change through name= and
|
|
@@ -117,7 +120,7 @@ module Moxml
|
|
|
117
120
|
# mint, so the first name/value/attribute? access skips the
|
|
118
121
|
# context hop and the adapter's type probe.
|
|
119
122
|
@attributes ||= adapter.attributes(@native).map do |attr|
|
|
120
|
-
a = Attribute.new(attr, context, adapter, :attribute)
|
|
123
|
+
a = Wrappers::Attribute.new(attr, context, adapter, :attribute)
|
|
121
124
|
a.parent_node = self
|
|
122
125
|
a
|
|
123
126
|
end
|
|
@@ -179,7 +182,7 @@ module Moxml
|
|
|
179
182
|
# it's NOT the same as namespaces.first
|
|
180
183
|
def namespace
|
|
181
184
|
ns = adapter.namespace(@native)
|
|
182
|
-
ns && Namespace.new(ns, context)
|
|
185
|
+
ns && Wrappers::Namespace.new(ns, context)
|
|
183
186
|
end
|
|
184
187
|
|
|
185
188
|
# add the prefix to the element name
|
|
@@ -213,7 +216,7 @@ module Moxml
|
|
|
213
216
|
return @namespace_definitions unless @namespace_definitions.nil?
|
|
214
217
|
|
|
215
218
|
@namespace_definitions = adapter.namespace_definitions(@native).map do |ns|
|
|
216
|
-
Namespace.new(ns, context)
|
|
219
|
+
Wrappers::Namespace.new(ns, context)
|
|
217
220
|
end
|
|
218
221
|
end
|
|
219
222
|
|
|
@@ -222,7 +225,7 @@ module Moxml
|
|
|
222
225
|
# scope. The shape materialize records carry (issue #138).
|
|
223
226
|
def declared_namespaces
|
|
224
227
|
adapter.namespace_definitions(@native).map do |ns|
|
|
225
|
-
wrapper = Namespace.new(ns, context)
|
|
228
|
+
wrapper = Wrappers::Namespace.new(ns, context)
|
|
226
229
|
[wrapper.prefix, wrapper.uri]
|
|
227
230
|
end
|
|
228
231
|
end
|
|
@@ -233,7 +236,7 @@ module Moxml
|
|
|
233
236
|
generation = context.namespace_scope_generation
|
|
234
237
|
if @in_scope_namespaces.nil? || @in_scope_generation != generation
|
|
235
238
|
@in_scope_namespaces = adapter.in_scope_namespaces(@native).map do |ns|
|
|
236
|
-
Namespace.new(ns, context)
|
|
239
|
+
Wrappers::Namespace.new(ns, context)
|
|
237
240
|
end
|
|
238
241
|
@in_scope_generation = generation
|
|
239
242
|
end
|
|
@@ -359,4 +362,9 @@ module Moxml
|
|
|
359
362
|
context.bump_namespace_scope_generation
|
|
360
363
|
end
|
|
361
364
|
end
|
|
365
|
+
|
|
366
|
+
module Element
|
|
367
|
+
include Node
|
|
368
|
+
include ElementBehavior
|
|
369
|
+
end
|
|
362
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
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Moxml
|
|
4
|
-
|
|
4
|
+
# Instance behavior for Moxml::Node, extracted so the leptris
|
|
5
|
+
# adapter can extend natives with it in place (issue #230); the
|
|
6
|
+
# class remains the consumer-facing contract and the wrap factory.
|
|
7
|
+
module NodeBehavior
|
|
5
8
|
include XmlUtils
|
|
6
9
|
include Enumerable
|
|
7
10
|
|
|
@@ -17,15 +20,22 @@ module Moxml
|
|
|
17
20
|
# otherwise pay the context hop and the type probe again on its
|
|
18
21
|
# first access.
|
|
19
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)
|
|
20
31
|
@context = context
|
|
21
32
|
@native = native
|
|
22
33
|
@parent_node = nil
|
|
23
34
|
@adapter = adapter
|
|
24
35
|
@node_type_cached = node_type
|
|
36
|
+
self
|
|
25
37
|
end
|
|
26
38
|
|
|
27
|
-
# Update native reference after identity-changing operations
|
|
28
|
-
# (e.g., LibXML doc.root= creates a new Ruby wrapper)
|
|
29
39
|
def refresh_native!(new_native)
|
|
30
40
|
unless new_native.equal?(@native)
|
|
31
41
|
context.unregister_wrapper(@native)
|
|
@@ -45,7 +55,7 @@ module Moxml
|
|
|
45
55
|
end
|
|
46
56
|
|
|
47
57
|
def document
|
|
48
|
-
|
|
58
|
+
Moxml::Node.wrap(adapter.document(@native), context)
|
|
49
59
|
end
|
|
50
60
|
|
|
51
61
|
def parent
|
|
@@ -252,7 +262,7 @@ module Moxml
|
|
|
252
262
|
return nil unless element?
|
|
253
263
|
|
|
254
264
|
ns = adapter.namespace(@native)
|
|
255
|
-
ns && Namespace.new(ns, context)
|
|
265
|
+
ns && Wrappers::Namespace.new(ns, context)
|
|
256
266
|
end
|
|
257
267
|
|
|
258
268
|
# Returns all namespace definitions on this node
|
|
@@ -261,7 +271,7 @@ module Moxml
|
|
|
261
271
|
return [] unless element?
|
|
262
272
|
|
|
263
273
|
adapter.namespace_definitions(@native).map do |ns|
|
|
264
|
-
Namespace.new(ns, context)
|
|
274
|
+
Wrappers::Namespace.new(ns, context)
|
|
265
275
|
end
|
|
266
276
|
end
|
|
267
277
|
|
|
@@ -411,7 +421,7 @@ module Moxml
|
|
|
411
421
|
# Native equality goes through the adapter: engines with a
|
|
412
422
|
# native read layer hand out two wrapper classes over one C
|
|
413
423
|
# node, and raw native == is false across that seam.
|
|
414
|
-
|
|
424
|
+
other.is_a?(Moxml::Node) &&
|
|
415
425
|
adapter.same_node?(@native, other.native)
|
|
416
426
|
end
|
|
417
427
|
|
|
@@ -441,37 +451,6 @@ module Moxml
|
|
|
441
451
|
nil
|
|
442
452
|
end
|
|
443
453
|
|
|
444
|
-
# Registry mapping node type symbols to wrapper classes.
|
|
445
|
-
# Built lazily to avoid load-order issues with subclasses.
|
|
446
|
-
def self.node_type_map
|
|
447
|
-
@node_type_map ||= {
|
|
448
|
-
element: Element,
|
|
449
|
-
text: Text,
|
|
450
|
-
cdata: Cdata,
|
|
451
|
-
comment: Comment,
|
|
452
|
-
processing_instruction: ProcessingInstruction,
|
|
453
|
-
document: Document,
|
|
454
|
-
declaration: Declaration,
|
|
455
|
-
doctype: Doctype,
|
|
456
|
-
attribute: Attribute,
|
|
457
|
-
entity_reference: EntityReference,
|
|
458
|
-
}.freeze
|
|
459
|
-
end
|
|
460
|
-
|
|
461
|
-
def self.wrap(node, context)
|
|
462
|
-
return nil if node.nil?
|
|
463
|
-
|
|
464
|
-
cached = context.wrapper_for(node)
|
|
465
|
-
return cached if cached
|
|
466
|
-
|
|
467
|
-
adapter = adapter(context)
|
|
468
|
-
type = adapter.node_type(node)
|
|
469
|
-
klass = node_type_map[type] || self
|
|
470
|
-
|
|
471
|
-
klass.new(node, context, adapter, type)
|
|
472
|
-
.tap { |wrapper| context.register_wrapper(node, wrapper) }
|
|
473
|
-
end
|
|
474
|
-
|
|
475
454
|
# Internal: Set the parent node for cache invalidation tracking.
|
|
476
455
|
# Called by NodeSet, Document, Element when establishing parent-child
|
|
477
456
|
# relationships. Public to allow cross-class usage within Moxml internals.
|
|
@@ -485,12 +464,6 @@ module Moxml
|
|
|
485
464
|
|
|
486
465
|
protected
|
|
487
466
|
|
|
488
|
-
def self.adapter(context)
|
|
489
|
-
context.config.adapter
|
|
490
|
-
end
|
|
491
|
-
|
|
492
|
-
# Invalidate cached children. Called by mutation methods
|
|
493
|
-
# and by Element attribute/namespace caches.
|
|
494
467
|
def invalidate_children_cache!
|
|
495
468
|
@children = nil
|
|
496
469
|
end
|
|
@@ -520,7 +493,7 @@ module Moxml
|
|
|
520
493
|
|
|
521
494
|
def prepare_node(node)
|
|
522
495
|
case node
|
|
523
|
-
when String then
|
|
496
|
+
when String then Moxml::Node.wrap(adapter.create_text(node), context)
|
|
524
497
|
when Node then node
|
|
525
498
|
else
|
|
526
499
|
raise Moxml::DocumentStructureError.new(
|
|
@@ -545,4 +518,77 @@ module Moxml
|
|
|
545
518
|
xml.gsub(/\r?\n/, line_ending)
|
|
546
519
|
end
|
|
547
520
|
end
|
|
521
|
+
|
|
522
|
+
module Node
|
|
523
|
+
include NodeBehavior
|
|
524
|
+
|
|
525
|
+
# Instantiation shells per type — the contract constants
|
|
526
|
+
# (Element, Text, ...) are modules since issue #230, so wrappers
|
|
527
|
+
# mint through Wrappers::*.
|
|
528
|
+
def self.node_type_map
|
|
529
|
+
@node_type_map ||= {
|
|
530
|
+
element: Wrappers::Element,
|
|
531
|
+
text: Wrappers::Text,
|
|
532
|
+
cdata: Wrappers::Cdata,
|
|
533
|
+
comment: Wrappers::Comment,
|
|
534
|
+
processing_instruction: Wrappers::ProcessingInstruction,
|
|
535
|
+
document: Wrappers::Document,
|
|
536
|
+
declaration: Wrappers::Declaration,
|
|
537
|
+
doctype: Wrappers::Doctype,
|
|
538
|
+
attribute: Wrappers::Attribute,
|
|
539
|
+
entity_reference: Wrappers::EntityReference,
|
|
540
|
+
}.freeze
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
# The contract module for a type — what an in-place extended
|
|
544
|
+
# native carries instead of a wrapper shell.
|
|
545
|
+
def self.contract_module(type)
|
|
546
|
+
contract_modules[type]
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
def self.contract_modules
|
|
550
|
+
@contract_modules ||= {
|
|
551
|
+
element: Element,
|
|
552
|
+
text: Text,
|
|
553
|
+
cdata: Cdata,
|
|
554
|
+
comment: Comment,
|
|
555
|
+
processing_instruction: ProcessingInstruction,
|
|
556
|
+
document: Document,
|
|
557
|
+
declaration: Declaration,
|
|
558
|
+
doctype: Doctype,
|
|
559
|
+
attribute: Attribute,
|
|
560
|
+
entity_reference: EntityReference,
|
|
561
|
+
}.freeze
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def self.wrap(node, context)
|
|
565
|
+
return nil if node.nil?
|
|
566
|
+
|
|
567
|
+
cached = context.wrapper_for(node)
|
|
568
|
+
return cached if cached
|
|
569
|
+
|
|
570
|
+
adapter = adapter(context)
|
|
571
|
+
type = adapter.node_type(node)
|
|
572
|
+
|
|
573
|
+
# Extend-in-place (issue #230): adapters whose natives can
|
|
574
|
+
# carry the contract modules directly (leptris TypedData) mint
|
|
575
|
+
# the native itself as the wrapper — @native is self.
|
|
576
|
+
if (extended = adapter.wrap_native(node, type, context))
|
|
577
|
+
extended.prime_contract(node, context, adapter, type)
|
|
578
|
+
context.register_wrapper(node, extended)
|
|
579
|
+
return extended
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
klass = node_type_map[type] || Wrappers::Node
|
|
583
|
+
klass.new(node, context, adapter, type)
|
|
584
|
+
.tap { |wrapper| context.register_wrapper(node, wrapper) }
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
def self.adapter(context)
|
|
588
|
+
context.config.adapter
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
# Invalidate cached children. Called by mutation methods
|
|
592
|
+
# and by Element attribute/namespace caches.
|
|
593
|
+
end
|
|
548
594
|
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,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.48
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -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
|