moxml 0.5.145 → 0.5.146
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 +99 -0
- data/lib/moxml/adapter/rexml.rb +5 -0
- data/lib/moxml/version.rb +1 -1
- data/lib/moxml/xpath/compiler.rb +14 -1
- data/spec/consistency/xpath_idioms_spec.rb +31 -0
- data/spec/moxml/adapter/leptris_contract_reads_spec.rb +133 -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: b529948a14e67202c6ad6fc9acbe6c06c033ba022f93ada6bc9e4001554ea583
|
|
4
|
+
data.tar.gz: 68a76e1a69397aef0d0356e3ddd7bc200737a41333a70d6688cfca34d44e4c27
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3775a27419325f8c764d6d686c547e88f75bdc073cbe354bdd97d2e0516e68a4f83896d4cd840c25be26f7d6aafdca24a596d3c6aa2893e8596ed95d646c16fa
|
|
7
|
+
data.tar.gz: 84c2f0abec2a55d990cdc921f9abac0c9206def8190d609fd298256dd035d586334dedc04bb97af496a98fe9053b2fa3b65f716a11e22e94516f2f8b91837e1b
|
|
@@ -463,25 +463,72 @@ module Moxml
|
|
|
463
463
|
# instances). The hot bare reads super into the C methods
|
|
464
464
|
# (exact-name = the bare-name contract).
|
|
465
465
|
module Identity
|
|
466
|
+
# The C faces are captured before the contract modules
|
|
467
|
+
# shadow them — alias copies bind at this point, so the
|
|
468
|
+
# overrides below plain-dispatch the native reads
|
|
469
|
+
# (leptris-ruby#463 completed the surface: every contract
|
|
470
|
+
# face is a C method at 50-84ns).
|
|
466
471
|
ELEMENT = Class.new(::Leptris::XML::NativeNode) do
|
|
472
|
+
alias_method :native_name, :name
|
|
467
473
|
include ::Moxml::Node
|
|
468
474
|
include ::Moxml::Element
|
|
475
|
+
|
|
476
|
+
# Memo form kept: a warm read is an ivar hit (~30ns
|
|
477
|
+
# vs the C call's 84ns); the cold read drops the
|
|
478
|
+
# adapter round-trip and its PI-check bind_call.
|
|
479
|
+
def name
|
|
480
|
+
@name ||= native_name
|
|
481
|
+
end
|
|
469
482
|
end
|
|
470
483
|
TEXT = Class.new(::Leptris::XML::NativeNode) do
|
|
484
|
+
alias_method :native_content, :content
|
|
471
485
|
include ::Moxml::Node
|
|
472
486
|
include ::Moxml::Text
|
|
487
|
+
|
|
488
|
+
# Text#content's memo + entity restore are the
|
|
489
|
+
# contract; the backing read drops the adapter
|
|
490
|
+
# round-trip (dispatch + is_a? + bind_call) for the
|
|
491
|
+
# C face.
|
|
492
|
+
def raw_content
|
|
493
|
+
native_content
|
|
494
|
+
end
|
|
473
495
|
end
|
|
474
496
|
CDATA = Class.new(::Leptris::XML::NativeNode) do
|
|
497
|
+
alias_method :native_content, :content
|
|
475
498
|
include ::Moxml::Node
|
|
476
499
|
include ::Moxml::Cdata
|
|
500
|
+
|
|
501
|
+
def content
|
|
502
|
+
native_content
|
|
503
|
+
end
|
|
477
504
|
end
|
|
478
505
|
COMMENT = Class.new(::Leptris::XML::NativeNode) do
|
|
506
|
+
alias_method :native_content, :content
|
|
479
507
|
include ::Moxml::Node
|
|
480
508
|
include ::Moxml::Comment
|
|
509
|
+
|
|
510
|
+
# The nil bridge stays for floor-admitted bindings
|
|
511
|
+
# where the native face answers nil for comment-kind
|
|
512
|
+
# (leptris-ruby#313).
|
|
513
|
+
def content
|
|
514
|
+
content = native_content
|
|
515
|
+
return ::Moxml::Adapter::Leptris.to_binding(self).content if content.nil?
|
|
516
|
+
|
|
517
|
+
content
|
|
518
|
+
end
|
|
481
519
|
end
|
|
482
520
|
PROCESSING_INSTRUCTION = Class.new(::Leptris::XML::NativeNode) do
|
|
521
|
+
alias_method :native_content, :content
|
|
483
522
|
include ::Moxml::Node
|
|
484
523
|
include ::Moxml::ProcessingInstruction
|
|
524
|
+
|
|
525
|
+
# Same nil bridge as Comment (leptris-ruby#344).
|
|
526
|
+
def content
|
|
527
|
+
content = native_content
|
|
528
|
+
return ::Moxml::Adapter::Leptris.to_binding(self).content if content.nil?
|
|
529
|
+
|
|
530
|
+
content
|
|
531
|
+
end
|
|
485
532
|
end
|
|
486
533
|
|
|
487
534
|
TYPES = {
|
|
@@ -537,6 +584,46 @@ module Moxml
|
|
|
537
584
|
end
|
|
538
585
|
ELEMENT.include(Reads)
|
|
539
586
|
TEXT.include(Reads)
|
|
587
|
+
|
|
588
|
+
# leptris-ruby#503: name_read joins attr_read/text_read as
|
|
589
|
+
# the unshadowed contract faces. With them, the hot reads
|
|
590
|
+
# plain-dispatch the C faces (one Ruby frame over the
|
|
591
|
+
# ~45ns native call) instead of the adapter bind_call
|
|
592
|
+
# crossing. Face-probed — older bindings keep the
|
|
593
|
+
# adapter paths. The memos ride the existing
|
|
594
|
+
# invalidation: name= and clear_native_memo! clear
|
|
595
|
+
# @name, content= clears @content.
|
|
596
|
+
if NN.method_defined?(:name_read)
|
|
597
|
+
module ContractReads
|
|
598
|
+
def name
|
|
599
|
+
@name ||= name_read
|
|
600
|
+
end
|
|
601
|
+
end
|
|
602
|
+
ELEMENT.include(ContractReads)
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
if NN.method_defined?(:text_read)
|
|
606
|
+
module TextContractReads
|
|
607
|
+
# The stamp fast path is inlined (same ivar protocol
|
|
608
|
+
# as Reads#doc_entity_bearing?, which stays the
|
|
609
|
+
# single writer on recompute) — the two frames it
|
|
610
|
+
# saves are ~20% of the cold read.
|
|
611
|
+
def content
|
|
612
|
+
value = @content
|
|
613
|
+
return value if value
|
|
614
|
+
|
|
615
|
+
value = text_read
|
|
616
|
+
stamp = @doc_entity_stamp
|
|
617
|
+
if stamp && (stamp >> 1) == ::Moxml::Adapter::Leptris.serialize_generation
|
|
618
|
+
value = ::Moxml::Adapter::Leptris.restore_entities(value) if stamp.allbits?(1)
|
|
619
|
+
elsif doc_entity_bearing?
|
|
620
|
+
value = ::Moxml::Adapter::Leptris.restore_entities(value)
|
|
621
|
+
end
|
|
622
|
+
@content = value
|
|
623
|
+
end
|
|
624
|
+
end
|
|
625
|
+
TEXT.include(TextContractReads)
|
|
626
|
+
end
|
|
540
627
|
end
|
|
541
628
|
|
|
542
629
|
# leptris-ruby#246 klass-propagating reads: the read
|
|
@@ -2842,6 +2929,7 @@ module Moxml
|
|
|
2842
2929
|
PARENT_AXIS_CACHE = XPath::Cache.new(100)
|
|
2843
2930
|
|
|
2844
2931
|
def xpath(node, expression, namespaces = {})
|
|
2932
|
+
namespaces = normalize_xpath_namespaces(namespaces)
|
|
2845
2933
|
node = to_binding(node) if NATIVE_READ_LAYER
|
|
2846
2934
|
native = native_xpath(node, expression, namespaces)
|
|
2847
2935
|
return native unless native.nil?
|
|
@@ -2873,6 +2961,7 @@ module Moxml
|
|
|
2873
2961
|
end
|
|
2874
2962
|
|
|
2875
2963
|
def at_xpath(node, expression, namespaces = {})
|
|
2964
|
+
namespaces = normalize_xpath_namespaces(namespaces)
|
|
2876
2965
|
native = native_xpath(node, expression, namespaces, first_only: true)
|
|
2877
2966
|
return native unless native.nil?
|
|
2878
2967
|
|
|
@@ -2880,6 +2969,16 @@ module Moxml
|
|
|
2880
2969
|
result.is_a?(Array) ? result.first : result
|
|
2881
2970
|
end
|
|
2882
2971
|
|
|
2972
|
+
# Bindings arrive in both spellings (symbol keys are the
|
|
2973
|
+
# common Nokogiri idiom); every seam below — the "xmlns"
|
|
2974
|
+
# reserved-key check and the native pairs set — is
|
|
2975
|
+
# string-keyed (issue #395).
|
|
2976
|
+
def normalize_xpath_namespaces(namespaces)
|
|
2977
|
+
return namespaces unless namespaces.is_a?(Hash)
|
|
2978
|
+
|
|
2979
|
+
namespaces.transform_keys(&:to_s)
|
|
2980
|
+
end
|
|
2981
|
+
|
|
2883
2982
|
# @return [Array, Object, nil] native results, or nil when the
|
|
2884
2983
|
# query must run on the Ruby engine
|
|
2885
2984
|
def native_xpath(node, expression, namespaces, first_only: false)
|
data/lib/moxml/adapter/rexml.rb
CHANGED
|
@@ -607,6 +607,11 @@ module Moxml
|
|
|
607
607
|
# XPath.match for every expression: get_elements only
|
|
608
608
|
# handles simple child-name paths — attribute terminals,
|
|
609
609
|
# absolute paths and predicates silently degrade there.
|
|
610
|
+
# REXML resolves prefixes by string spelling — symbol-keyed
|
|
611
|
+
# bindings (the common Nokogiri idiom) must normalize or
|
|
612
|
+
# namespaced elements never match (issue #395).
|
|
613
|
+
namespaces = namespaces.transform_keys(&:to_s) if
|
|
614
|
+
namespaces.is_a?(Hash)
|
|
610
615
|
if namespaces && !namespaces.empty?
|
|
611
616
|
::REXML::XPath.match(node, expression, namespaces).to_a
|
|
612
617
|
else
|
data/lib/moxml/version.rb
CHANGED
data/lib/moxml/xpath/compiler.rb
CHANGED
|
@@ -40,6 +40,7 @@ module Moxml
|
|
|
40
40
|
# @param namespaces [Hash, nil] Optional namespace prefix mappings
|
|
41
41
|
# @return [Proc] Compiled Proc that accepts a document
|
|
42
42
|
def self.compile_with_cache(ast, namespaces: nil)
|
|
43
|
+
namespaces = normalize_namespaces(namespaces)
|
|
43
44
|
cache_key = namespaces ? [ast, namespaces] : ast
|
|
44
45
|
CACHE.get_or_set(cache_key) { new(namespaces: namespaces).compile(ast) }
|
|
45
46
|
end
|
|
@@ -48,12 +49,24 @@ module Moxml
|
|
|
48
49
|
#
|
|
49
50
|
# @param namespaces [Hash, nil] Optional namespace prefix mappings
|
|
50
51
|
def initialize(namespaces: nil)
|
|
51
|
-
@namespaces = namespaces
|
|
52
|
+
@namespaces = self.class.normalize_namespaces(namespaces)
|
|
52
53
|
@literal_id = 0
|
|
53
54
|
@predicate_nodesets = []
|
|
54
55
|
@predicate_indexes = []
|
|
55
56
|
end
|
|
56
57
|
|
|
58
|
+
# Prefix lookups are string-keyed (the parser yields prefix
|
|
59
|
+
# strings); symbol-keyed bindings — the common Nokogiri spelling
|
|
60
|
+
# (`xpath("//cml:molecule", cml: URI)`) — must resolve too, or
|
|
61
|
+
# the miss falls through to prefix-spelling matching and
|
|
62
|
+
# namespaced elements never match (issue #395).
|
|
63
|
+
def self.normalize_namespaces(namespaces)
|
|
64
|
+
return nil if namespaces.nil?
|
|
65
|
+
return namespaces unless namespaces.is_a?(Hash)
|
|
66
|
+
|
|
67
|
+
namespaces.transform_keys(&:to_s)
|
|
68
|
+
end
|
|
69
|
+
|
|
57
70
|
# Compiles an XPath AST into a Ruby Proc
|
|
58
71
|
#
|
|
59
72
|
# @param ast [AST::Node] XPath AST to compile
|
|
@@ -11,11 +11,22 @@ require "spec_helper"
|
|
|
11
11
|
# - Attribute-terminal steps work in every path position
|
|
12
12
|
# (leptris-ruby#458's table: //a/@id, //@id, r/a/@id,
|
|
13
13
|
# //*[f()]/@id — fixed by the engine's VM path work).
|
|
14
|
+
CML_NS = "http://www.xml-cml.org/schema"
|
|
15
|
+
ACI_NS = "http://www.xml-cml.org/schema/asciichem"
|
|
16
|
+
|
|
14
17
|
RSpec.describe "XPath idioms across adapters" do
|
|
15
18
|
let(:default_ns_xml) do
|
|
16
19
|
'<svgmap xmlns="http://www.example.org/doc"><target href="a"/></svgmap>'
|
|
17
20
|
end
|
|
18
21
|
let(:plain_xml) { '<r><a id="x"><b/></a></r>' }
|
|
22
|
+
let(:cml_xml) do
|
|
23
|
+
<<~XML
|
|
24
|
+
<molecule xmlns="#{CML_NS}" xmlns:aci="#{ACI_NS}" id="m1">
|
|
25
|
+
<atomArray><atom id="a1"/></atomArray>
|
|
26
|
+
<aci:group multiplicity="2" bracket="paren" atomRefs="a1"/>
|
|
27
|
+
</molecule>
|
|
28
|
+
XML
|
|
29
|
+
end
|
|
19
30
|
|
|
20
31
|
Moxml::Adapter::AVAILABLE_ADAPTERS.each do |adapter_name|
|
|
21
32
|
next if adapter_name == :headed_ox # same engine as :ox
|
|
@@ -56,6 +67,26 @@ RSpec.describe "XPath idioms across adapters" do
|
|
|
56
67
|
expect(doc.xpath("//*[local-name()='a']/@id").first&.value).to eq("x")
|
|
57
68
|
end
|
|
58
69
|
|
|
70
|
+
# Issue #395: bindings hashes arrive in both key spellings
|
|
71
|
+
# (symbols are the common Nokogiri idiom); the engines must
|
|
72
|
+
# resolve both — a symbol-key miss falls through to
|
|
73
|
+
# prefix-spelling matching and namespaced elements never match.
|
|
74
|
+
# asciichem's CML group extraction rides exactly this shape.
|
|
75
|
+
it "resolves symbol-keyed namespace bindings" do
|
|
76
|
+
doc = ctx.parse(cml_xml)
|
|
77
|
+
mols = doc.xpath("//cml:molecule", cml: CML_NS)
|
|
78
|
+
expect(mols.to_a.size).to eq(1)
|
|
79
|
+
|
|
80
|
+
groups = mols.first.xpath("./aci:group", aci: ACI_NS)
|
|
81
|
+
expect(groups.to_a.size).to eq(1)
|
|
82
|
+
expect(groups.first["multiplicity"]).to eq("2")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "resolves string-keyed namespace bindings identically" do
|
|
86
|
+
doc = ctx.parse(cml_xml)
|
|
87
|
+
expect(doc.xpath("//cml:molecule", "cml" => CML_NS).to_a.size).to eq(1)
|
|
88
|
+
end
|
|
89
|
+
|
|
59
90
|
# moxml#393: a relative name-test path on the DOCUMENT resolves
|
|
60
91
|
# laxly, descendant-anchored at the root — Nokogiri's own
|
|
61
92
|
# Document#at/#search semantics, now pinned for every adapter.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
# leptris-ruby#460 — the Identity contract reads ride the C faces
|
|
6
|
+
# by plain dispatch (NativeNode subclasses inherit the C-defined
|
|
7
|
+
# name/content since binding 1.9.359). The wrapper memo stays; the
|
|
8
|
+
# ADAPTER CROSSING (bind_call through node_name/text_content) goes.
|
|
9
|
+
RSpec.describe "leptris Identity contract reads" do
|
|
10
|
+
let(:ctx) { Moxml.new(:leptris) }
|
|
11
|
+
|
|
12
|
+
before do
|
|
13
|
+
unless Moxml::Adapter::Leptris::NATIVE_READ_LAYER &&
|
|
14
|
+
Leptris::XML::NativeNode.method_defined?(:name) &&
|
|
15
|
+
Leptris::XML::NativeNode.method_defined?(:content)
|
|
16
|
+
skip "binding #{defined?(Leptris) && Leptris::VERSION} lacks the C contract faces"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def bust(node, *ivars)
|
|
21
|
+
ivars.each do |iv|
|
|
22
|
+
node.remove_instance_variable(iv) if node.instance_variable_defined?(iv)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def forbid_crossing!(method)
|
|
27
|
+
singleton = Moxml::Adapter::Leptris.singleton_class
|
|
28
|
+
singleton.send(:alias_method, :"#{method}_without_460", method)
|
|
29
|
+
singleton.send(:define_method, method) { |*| raise "adapter #{method} crossing" }
|
|
30
|
+
method
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def restore_crossing!(method)
|
|
34
|
+
singleton = Moxml::Adapter::Leptris.singleton_class
|
|
35
|
+
singleton.send(:alias_method, method, :"#{method}_without_460")
|
|
36
|
+
singleton.send(:remove_method, :"#{method}_without_460")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "element#name" do
|
|
40
|
+
it "answers without the adapter node_name crossing" do
|
|
41
|
+
unless Leptris::XML::NativeNode.method_defined?(:name_read)
|
|
42
|
+
skip "binding #{Leptris::VERSION} has no name_read face (adapter path is correct there)"
|
|
43
|
+
end
|
|
44
|
+
doc = ctx.parse('<root><item id="1">v</item></root>')
|
|
45
|
+
el = doc.root.children.first
|
|
46
|
+
expect(el.native).to be_a(Leptris::XML::NativeNode)
|
|
47
|
+
|
|
48
|
+
bust(el, :@name)
|
|
49
|
+
forbid_crossing!(:node_name)
|
|
50
|
+
begin
|
|
51
|
+
expect(el.name).to eq("item")
|
|
52
|
+
ensure
|
|
53
|
+
restore_crossing!(:node_name)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "answers the local name for prefixed elements (cross-adapter contract)" do
|
|
58
|
+
doc = ctx.parse('<root xmlns:ns="urn:u"><ns:p/></root>')
|
|
59
|
+
el = doc.root.children.first
|
|
60
|
+
bust(el, :@name)
|
|
61
|
+
expect(el.name).to eq("p")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "memoizes: warm reads return the same String" do
|
|
65
|
+
doc = ctx.parse("<root><item/></root>")
|
|
66
|
+
el = doc.root.children.first
|
|
67
|
+
first = el.name
|
|
68
|
+
expect(el.name).to equal(first)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "re-reads after name=" do
|
|
72
|
+
doc = ctx.parse("<root><item/></root>")
|
|
73
|
+
el = doc.root.children.first
|
|
74
|
+
el.name = "renamed"
|
|
75
|
+
expect(el.name).to eq("renamed")
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe "text#content" do
|
|
80
|
+
it "answers without the adapter text_content crossing" do
|
|
81
|
+
unless Leptris::XML::NativeNode.method_defined?(:text_read)
|
|
82
|
+
skip "binding #{Leptris::VERSION} has no text_read face (adapter path is correct there)"
|
|
83
|
+
end
|
|
84
|
+
doc = ctx.parse("<root><item>v</item></root>")
|
|
85
|
+
tx = doc.root.children.first.children.first
|
|
86
|
+
expect(tx.native).to be_a(Leptris::XML::NativeNode)
|
|
87
|
+
|
|
88
|
+
bust(tx, :@content)
|
|
89
|
+
forbid_crossing!(:text_content)
|
|
90
|
+
begin
|
|
91
|
+
expect(tx.content).to eq("v")
|
|
92
|
+
ensure
|
|
93
|
+
restore_crossing!(:text_content)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "memoizes: warm reads return the same String" do
|
|
98
|
+
doc = ctx.parse("<root><item>v</item></root>")
|
|
99
|
+
tx = doc.root.children.first.children.first
|
|
100
|
+
first = tx.content
|
|
101
|
+
expect(tx.content).to equal(first)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "re-reads after content=" do
|
|
105
|
+
doc = ctx.parse("<root><item>v</item></root>")
|
|
106
|
+
tx = doc.root.children.first.children.first
|
|
107
|
+
tx.content = "changed"
|
|
108
|
+
expect(tx.content).to eq("changed")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "restores entities on entity-bearing documents" do
|
|
112
|
+
ctx2 = Moxml.new(:leptris) { |c| c.restore_entities = true }
|
|
113
|
+
doc = ctx2.parse("<root><item>a & b</item></root>")
|
|
114
|
+
tx = doc.root.children.first.children.first
|
|
115
|
+
bust(tx, :@content)
|
|
116
|
+
expect(tx.content).to eq("a & b")
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
describe "the untouched faces" do
|
|
121
|
+
it "keeps text wrappers named text" do
|
|
122
|
+
doc = ctx.parse("<root><item>v</item></root>")
|
|
123
|
+
tx = doc.root.children.first.children.first
|
|
124
|
+
expect(tx.name).to eq("text")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "keeps element#text on the existing path" do
|
|
128
|
+
doc = ctx.parse("<root><item>v</item></root>")
|
|
129
|
+
el = doc.root.children.first
|
|
130
|
+
expect(el.text).to eq("v")
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: moxml
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.146
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -452,6 +452,7 @@ files:
|
|
|
452
452
|
- spec/moxml/adapter/leptris_append_gc_spec.rb
|
|
453
453
|
- spec/moxml/adapter/leptris_attribute_snapshot_spec.rb
|
|
454
454
|
- spec/moxml/adapter/leptris_binding_cap_spec.rb
|
|
455
|
+
- spec/moxml/adapter/leptris_contract_reads_spec.rb
|
|
455
456
|
- spec/moxml/adapter/leptris_doc_parts_spec.rb
|
|
456
457
|
- spec/moxml/adapter/leptris_document_declaration_spec.rb
|
|
457
458
|
- spec/moxml/adapter/leptris_inbody_comment_spec.rb
|