moxml 0.5.67 → 0.5.69
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/customized_leptris/declaration.rb +4 -4
- data/lib/moxml/adapter/customized_leptris/doctype.rb +5 -3
- data/lib/moxml/adapter/customized_leptris/document_pi.rb +2 -1
- data/lib/moxml/adapter/customized_leptris/entity_reference.rb +5 -3
- data/lib/moxml/adapter/leptris/document_parts.rb +57 -6
- data/lib/moxml/adapter/leptris.rb +52 -8
- data/lib/moxml/version.rb +1 -1
- data/spec/moxml/adapter/leptris_doc_parts_spec.rb +84 -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: d107d95a6e6c40031e9ea519397fe43ecbb08bf991ea5308bb72cc1510df0525
|
|
4
|
+
data.tar.gz: 574d6d7b1b5b211a87992b772358c0bfd96cdf0133c5cd2a2ac6547115139f02
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fc99001a56408820af4db232e682b4a5723eb1ef36545909b38144973c3b1583cca7966f89c08ee9b6d6c450bd034fc90bf53300f35e041b8f394154c18e80d7
|
|
7
|
+
data.tar.gz: 15cae743eca3abed5bcf07d4ea264974602b247b9b7edfee018ccf73b0dc4732bb2420779ee8cb90b7a6d7055fe274a51ec5d2509fab9536c056df1d9339a1cf
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
module Moxml
|
|
4
4
|
module Adapter
|
|
5
5
|
module CustomizedLeptris
|
|
6
|
-
# Wrapper for an XML declaration. libleptris
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
6
|
+
# Wrapper for an XML declaration. libleptris gained declaration
|
|
7
|
+
# setters (#1094) but has no first-class declaration node and no
|
|
8
|
+
# way to clear the state, so Moxml exposes this mutable,
|
|
9
|
+
# removable value object instead.
|
|
10
10
|
class Declaration
|
|
11
11
|
attr_accessor :version, :encoding, :standalone, :parent_doc
|
|
12
12
|
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
module Moxml
|
|
4
4
|
module Adapter
|
|
5
5
|
module CustomizedLeptris
|
|
6
|
-
# Wrapper for a programmatic DOCTYPE. libleptris
|
|
7
|
-
#
|
|
8
|
-
#
|
|
6
|
+
# Wrapper for a programmatic DOCTYPE. libleptris can create
|
|
7
|
+
# one (Document#set_doctype, 1.9.176 / #212) but cannot unset
|
|
8
|
+
# it, and the facade contract makes DOCTYPEs removable nodes —
|
|
9
|
+
# so Moxml keeps this value object as the lifecycle record in
|
|
10
|
+
# the document's attachments.
|
|
9
11
|
class Doctype
|
|
10
12
|
attr_accessor :name, :external_id, :system_id, :parent_doc
|
|
11
13
|
|
|
@@ -9,7 +9,8 @@ module Moxml
|
|
|
9
9
|
# the root), reachable through Document#processing_instructions
|
|
10
10
|
# as [target, data] pairs. This pseudo-native gives the pairs a
|
|
11
11
|
# node identity so the moxml contract can list them as document
|
|
12
|
-
# children
|
|
12
|
+
# children (and answer mutations: creation routes native via
|
|
13
|
+
# add_pi; removal has no engine entry).
|
|
13
14
|
class DocumentPI
|
|
14
15
|
attr_accessor :target, :data, :parent_doc
|
|
15
16
|
alias content data
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
module Moxml
|
|
4
4
|
module Adapter
|
|
5
5
|
module CustomizedLeptris
|
|
6
|
-
# libleptris expands the five built-in entities
|
|
7
|
-
# and has no custom ones
|
|
8
|
-
# as Moxml::Entity::Reference values over marker-bearing
|
|
6
|
+
# Parse-path face: libleptris expands the five built-in entities
|
|
7
|
+
# at parse time and has no custom ones, so parsed references are
|
|
8
|
+
# carried as Moxml::Entity::Reference values over marker-bearing
|
|
9
|
+
# text. Programmatic creation is native (NATIVE_ENTITY_REFS,
|
|
10
|
+
# binding >= 1.9.177).
|
|
9
11
|
EntityReference = ::Moxml::Entity::Reference
|
|
10
12
|
end
|
|
11
13
|
end
|
|
@@ -23,11 +23,13 @@ module Moxml
|
|
|
23
23
|
def assemble_document_children(doc)
|
|
24
24
|
children = []
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
# Attached DOCTYPEs (NATIVE_DOC_PARTS) list the STORED
|
|
27
|
+
# native — the same object the attaching wrapper was
|
|
28
|
+
# refreshed onto — so wrapper identity holds; doc.doctype
|
|
29
|
+
# mints a fresh DocType per call and would fork wrappers.
|
|
30
|
+
doctype_native = attachments.get(doc, :doctype)
|
|
31
|
+
doctype_native = doc.doctype unless doctype_native.is_a?(::Leptris::XML::DocType)
|
|
32
|
+
children << doctype_native if doctype_native
|
|
31
33
|
|
|
32
34
|
# The libxml2-model document node lists prolog PIs/comments,
|
|
33
35
|
# the root, and epilog PIs/comments in document order — the
|
|
@@ -55,10 +57,25 @@ module Moxml
|
|
|
55
57
|
when CustomizedLeptris::Declaration
|
|
56
58
|
child.parent_doc = doc
|
|
57
59
|
attachments.set(doc, :declaration, child)
|
|
60
|
+
mirror_declaration_native(doc, child) if NATIVE_DOC_PARTS
|
|
58
61
|
when CustomizedLeptris::Doctype
|
|
62
|
+
if NATIVE_DOC_PARTS
|
|
63
|
+
dt = doc.set_doctype(child.name,
|
|
64
|
+
public_id: child.external_id,
|
|
65
|
+
system_id: child.system_id)
|
|
66
|
+
attachments.set(doc, :doctype, dt)
|
|
67
|
+
return dt
|
|
68
|
+
end
|
|
59
69
|
child.parent_doc = doc
|
|
60
70
|
attachments.set(doc, :doctype, child)
|
|
61
71
|
when ::Leptris::XML::DocType
|
|
72
|
+
if NATIVE_DOC_PARTS
|
|
73
|
+
dt = doc.set_doctype(child.root_name,
|
|
74
|
+
public_id: child.public_id,
|
|
75
|
+
system_id: child.system_id)
|
|
76
|
+
attachments.set(doc, :doctype, dt)
|
|
77
|
+
return dt
|
|
78
|
+
end
|
|
62
79
|
raise Moxml::DocumentStructureError.new(
|
|
63
80
|
"libleptris does not support attaching a native DocType to a document",
|
|
64
81
|
)
|
|
@@ -112,7 +129,7 @@ module Moxml
|
|
|
112
129
|
end
|
|
113
130
|
|
|
114
131
|
doctype = attachments.get(doc, :doctype)
|
|
115
|
-
parts << doctype.to_xml << "\n" if doctype
|
|
132
|
+
parts << doctype.to_xml << "\n" if doctype.is_a?(CustomizedLeptris::Doctype)
|
|
116
133
|
|
|
117
134
|
native = native_doctype_xml(doc)
|
|
118
135
|
parts << native << "\n" if native
|
|
@@ -304,6 +321,40 @@ module Moxml
|
|
|
304
321
|
attachments.get(native, :had_source_declaration) ? true : false
|
|
305
322
|
end
|
|
306
323
|
|
|
324
|
+
# Write a created declaration through to the engine's
|
|
325
|
+
# document state (setters, libleptris 1.9.176 / #1094) so
|
|
326
|
+
# native reads and serialization see the same truth the
|
|
327
|
+
# facade does. Removal clears it (clear_declaration).
|
|
328
|
+
def mirror_declaration_native(doc, child)
|
|
329
|
+
# The engine setters reject empty values; the facade's
|
|
330
|
+
# minimal declarations may carry them (serializer formats
|
|
331
|
+
# what it gets). Mirror only non-empty parts — the wrapper
|
|
332
|
+
# remains the record for what the facade shows.
|
|
333
|
+
unless child.version.to_s.empty?
|
|
334
|
+
::Leptris::XML::FFI.check_status(
|
|
335
|
+
::Leptris::XML::FFI.leptris_document_set_version(
|
|
336
|
+
doc.c_ptr, child.version.to_s
|
|
337
|
+
),
|
|
338
|
+
)
|
|
339
|
+
end
|
|
340
|
+
unless child.encoding.to_s.empty?
|
|
341
|
+
::Leptris::XML::FFI.check_status(
|
|
342
|
+
::Leptris::XML::FFI.leptris_document_set_encoding(
|
|
343
|
+
doc.c_ptr, child.encoding.to_s
|
|
344
|
+
),
|
|
345
|
+
)
|
|
346
|
+
end
|
|
347
|
+
case child.standalone.to_s
|
|
348
|
+
when "yes" then sa = 1
|
|
349
|
+
when "no" then sa = 0
|
|
350
|
+
end
|
|
351
|
+
::Leptris::XML::FFI.check_status(
|
|
352
|
+
::Leptris::XML::FFI.leptris_document_set_standalone(
|
|
353
|
+
doc.c_ptr, sa || -1
|
|
354
|
+
),
|
|
355
|
+
)
|
|
356
|
+
end
|
|
357
|
+
|
|
307
358
|
def marker_text_for(parent, name)
|
|
308
359
|
return nil unless parent.is_a?(::Leptris::XML::Element)
|
|
309
360
|
|
|
@@ -12,9 +12,12 @@ module Moxml
|
|
|
12
12
|
# Adapter over the leptris FFI binding (libleptris C library).
|
|
13
13
|
#
|
|
14
14
|
# libleptris provides DOM parsing, a native XPath 1.0 engine, SAX,
|
|
15
|
-
# and serialization.
|
|
16
|
-
#
|
|
17
|
-
#
|
|
15
|
+
# and serialization. Its document-level creation surfaces exist
|
|
16
|
+
# (set_doctype 1.9.176/#212, declaration setters #1094) but are
|
|
17
|
+
# SET-ONLY — no unset for declaration, DOCTYPE, or document PIs —
|
|
18
|
+
# while the moxml facade contract makes those parts removable
|
|
19
|
+
# nodes. CustomizedLeptris value objects therefore remain the
|
|
20
|
+
# lifecycle record, attached through NativeAttachment.
|
|
18
21
|
class Leptris < Base
|
|
19
22
|
# The binding floor (issue #149): 1.9.32 carried the traverse
|
|
20
23
|
# fix (leptris-ruby#89) and made built documents reflect their
|
|
@@ -551,6 +554,16 @@ module Moxml
|
|
|
551
554
|
(!defined?(::Leptris::XML::Native) ||
|
|
552
555
|
::Leptris::XML::Native.respond_to?(:plan_structs))
|
|
553
556
|
|
|
557
|
+
# leptris-ruby#275 (binding 1.9.204, the remove half of the
|
|
558
|
+
# document-level surfaces): remove_pi, clear_declaration,
|
|
559
|
+
# remove_doctype complete the set-only creation entries.
|
|
560
|
+
# Attached DOCTYPEs materialize as native nodes, document-PI
|
|
561
|
+
# removal works, and declaration state mirrors through.
|
|
562
|
+
NATIVE_DOC_PARTS =
|
|
563
|
+
Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.204.0") &&
|
|
564
|
+
::Leptris::XML::Document.method_defined?(:remove_doctype) &&
|
|
565
|
+
::Leptris::XML::Document.method_defined?(:clear_declaration)
|
|
566
|
+
|
|
554
567
|
def self.plan_structs(native, spec)
|
|
555
568
|
return nil unless NATIVE_PLAN_STRUCTS
|
|
556
569
|
|
|
@@ -954,6 +967,9 @@ module Moxml
|
|
|
954
967
|
def remove_declaration(native_doc)
|
|
955
968
|
attachments.delete(native_doc, :declaration)
|
|
956
969
|
attachments.delete(native_doc, :had_source_declaration)
|
|
970
|
+
if NATIVE_DOC_PARTS && native_doc.is_a?(::Leptris::XML::Document)
|
|
971
|
+
native_doc.clear_declaration
|
|
972
|
+
end
|
|
957
973
|
end
|
|
958
974
|
|
|
959
975
|
def create_native_namespace(element, prefix, uri)
|
|
@@ -1496,6 +1512,15 @@ module Moxml
|
|
|
1496
1512
|
attr
|
|
1497
1513
|
end
|
|
1498
1514
|
|
|
1515
|
+
def actual_native(child_native, parent_native)
|
|
1516
|
+
if NATIVE_DOC_PARTS && child_native.is_a?(CustomizedLeptris::Doctype) &&
|
|
1517
|
+
parent_native.is_a?(::Leptris::XML::Document)
|
|
1518
|
+
attached = attachments.get(parent_native, :doctype)
|
|
1519
|
+
return attached if attached.is_a?(::Leptris::XML::DocType)
|
|
1520
|
+
end
|
|
1521
|
+
child_native
|
|
1522
|
+
end
|
|
1523
|
+
|
|
1499
1524
|
def add_child(parent, child)
|
|
1500
1525
|
if NATIVE_READ_LAYER && !(NATIVE_MUTATIONS_COHERENT &&
|
|
1501
1526
|
parent.is_a?(::Leptris::XML::NativeNode) &&
|
|
@@ -1588,14 +1613,33 @@ module Moxml
|
|
|
1588
1613
|
remove_declaration(node.parent_doc) if node.parent_doc
|
|
1589
1614
|
when CustomizedLeptris::Doctype
|
|
1590
1615
|
attachments.delete(node.parent_doc, :doctype) if node.parent_doc
|
|
1616
|
+
when ::Leptris::XML::DocType
|
|
1617
|
+
if NATIVE_DOC_PARTS
|
|
1618
|
+
doc = node.document || doc_for(node)
|
|
1619
|
+
if doc
|
|
1620
|
+
doc.remove_doctype
|
|
1621
|
+
attachments.delete(doc, :doctype)
|
|
1622
|
+
end
|
|
1623
|
+
end
|
|
1591
1624
|
when CustomizedLeptris::EntityReference
|
|
1592
1625
|
marker_text_for(node.parent, node.name)&.unlink
|
|
1593
1626
|
when CustomizedLeptris::DocumentPI
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1627
|
+
if NATIVE_DOC_PARTS && node.parent_doc
|
|
1628
|
+
pis = node.parent_doc.processing_instructions
|
|
1629
|
+
index = pis.index do |target, data|
|
|
1630
|
+
target == node.target && data == node.data
|
|
1631
|
+
end
|
|
1632
|
+
if index
|
|
1633
|
+
node.parent_doc.remove_pi(index)
|
|
1634
|
+
node.parent_doc = nil
|
|
1635
|
+
end
|
|
1636
|
+
else
|
|
1637
|
+
raise Moxml::NotImplementedError.new(
|
|
1638
|
+
"libleptris has no document-level PI removal",
|
|
1639
|
+
adapter: :leptris,
|
|
1640
|
+
feature: :remove,
|
|
1641
|
+
)
|
|
1642
|
+
end
|
|
1599
1643
|
else
|
|
1600
1644
|
node.unlink
|
|
1601
1645
|
end
|
data/lib/moxml/version.rb
CHANGED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require "leptris"
|
|
5
|
+
rescue LoadError
|
|
6
|
+
return
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
require "moxml/adapter/leptris"
|
|
10
|
+
|
|
11
|
+
# leptris-ruby#275 (binding 1.9.204, the remove half): attached
|
|
12
|
+
# DOCTYPEs materialize as native nodes with wrapper identity, and
|
|
13
|
+
# document-PI removal / declaration clear work natively. Below the
|
|
14
|
+
# gate the legacy CustomizedLeptris paths keep the contract.
|
|
15
|
+
RSpec.describe Moxml::Adapter::Leptris do
|
|
16
|
+
around do |example|
|
|
17
|
+
Moxml.with_config(:leptris, true, "UTF-8") do
|
|
18
|
+
example.run
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
let(:ctx) { Moxml.new(:leptris) }
|
|
23
|
+
let(:gate) do
|
|
24
|
+
Moxml::Adapter::Leptris::NATIVE_DOC_PARTS
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "created DOCTYPE as a native node" do
|
|
28
|
+
it "attaches, lists once with wrapper identity, serializes, and removes" do
|
|
29
|
+
skip "requires binding 1.9.204+ (leptris-ruby#275)" unless gate
|
|
30
|
+
|
|
31
|
+
doc = ctx.parse("<root/>")
|
|
32
|
+
doctype = doc.create_doctype("root", "-//X//DTD Y//EN", "y.dtd")
|
|
33
|
+
doc.add_child(doctype)
|
|
34
|
+
|
|
35
|
+
listed = doc.children.grep(Moxml::Doctype)
|
|
36
|
+
expect(listed.size).to eq(1)
|
|
37
|
+
expect(listed.first).to equal(doctype)
|
|
38
|
+
expect(doc.to_xml)
|
|
39
|
+
.to include(%(<!DOCTYPE root PUBLIC "-//X//DTD Y//EN" "y.dtd">))
|
|
40
|
+
|
|
41
|
+
doctype.remove
|
|
42
|
+
expect(doc.children).to all(be_a(Moxml::Element))
|
|
43
|
+
expect(doc.to_xml).not_to include("DOCTYPE")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe "document-level PI removal" do
|
|
48
|
+
it "removes the PI from children and serialization" do
|
|
49
|
+
skip "requires binding 1.9.204+ (leptris-ruby#275)" unless gate
|
|
50
|
+
|
|
51
|
+
doc = ctx.parse("<root/>")
|
|
52
|
+
doc.add_child(doc.create_processing_instruction("before", "data"))
|
|
53
|
+
expect(doc.children.count { |c| c.is_a?(Moxml::ProcessingInstruction) })
|
|
54
|
+
.to eq(1)
|
|
55
|
+
|
|
56
|
+
doc.children
|
|
57
|
+
.find { |c| c.is_a?(Moxml::ProcessingInstruction) }
|
|
58
|
+
.remove
|
|
59
|
+
expect(doc.children.count { |c| c.is_a?(Moxml::ProcessingInstruction) })
|
|
60
|
+
.to eq(0)
|
|
61
|
+
expect(doc.to_xml).not_to include("<?before")
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe "declaration mirroring" do
|
|
66
|
+
it "writes created declarations through to engine state and clears on remove" do
|
|
67
|
+
skip "requires binding 1.9.204+ (leptris-ruby#275)" unless gate
|
|
68
|
+
|
|
69
|
+
doc = ctx.parse("<root/>")
|
|
70
|
+
declaration = doc.create_declaration("1.1", "UTF-8", "yes")
|
|
71
|
+
doc.add_child(declaration)
|
|
72
|
+
|
|
73
|
+
ffi = Leptris::XML::FFI
|
|
74
|
+
native = doc.native
|
|
75
|
+
expect(ffi.leptris_document_version(native.c_ptr)).to eq("1.1")
|
|
76
|
+
expect(ffi.leptris_document_standalone(native.c_ptr)).to eq(1)
|
|
77
|
+
expect(doc.to_xml).to include(%(version="1.1"))
|
|
78
|
+
expect(doc.to_xml).to include(%(standalone="yes"))
|
|
79
|
+
|
|
80
|
+
declaration.remove
|
|
81
|
+
expect(doc.to_xml).not_to include("version=")
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
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.69
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -433,6 +433,7 @@ files:
|
|
|
433
433
|
- spec/moxml/adapter/base_spec.rb
|
|
434
434
|
- spec/moxml/adapter/entity_restoration_spec.rb
|
|
435
435
|
- spec/moxml/adapter/headed_ox_spec.rb
|
|
436
|
+
- spec/moxml/adapter/leptris_doc_parts_spec.rb
|
|
436
437
|
- spec/moxml/adapter/leptris_spec.rb
|
|
437
438
|
- spec/moxml/adapter/libxml_internals_spec.rb
|
|
438
439
|
- spec/moxml/adapter/libxml_spec.rb
|