moxml 0.5.17 → 0.5.18
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/docs/_pages/adapter-protocol.adoc +6 -3
- data/docs/_pages/adapters/leptris.adoc +9 -4
- data/lib/moxml/adapter/leptris/serialize.rb +6 -2
- data/lib/moxml/adapter/leptris.rb +20 -6
- data/lib/moxml/adapter/nokogiri.rb +2 -0
- data/lib/moxml/version.rb +1 -1
- data/spec/moxml/adapter/leptris_spec.rb +27 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c793d84315c4005a5141698aeb716c001d23b7157b768c77cbdb3539a4b08f53
|
|
4
|
+
data.tar.gz: 35c1d60e6d3a8e17e9768c733d028962bcb6e5798e3c8528b18deaebd855ae5f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '092b193420e9117adbd6dade8718474c9a72de401eb0b7a741d36639bbd7e9285c7e53d55f96b482b17bea3382d1da3adb1cae6bbc7b787c552859d80377db39'
|
|
7
|
+
data.tar.gz: 18a342a60a7dda872730dd2a9158aa852948596e21fc4613961d0336ece2f12977d02fe434e7fa64429f3ce73015a4434285f3f052425c4eb6d88c20a9571db7
|
|
@@ -18,7 +18,9 @@ code disagree.
|
|
|
18
18
|
== Method groups
|
|
19
19
|
|
|
20
20
|
Parse and document lifecycle::
|
|
21
|
-
`parse(xml, options, context)
|
|
21
|
+
`parse(xml, options, context)` — `noblanks: true` drops
|
|
22
|
+
whitespace-only text nodes where the engine has the flag
|
|
23
|
+
(Nokogiri, leptris), `create_document`, `create` factories
|
|
22
24
|
(`create_native_element`, `create_native_text`, `create_native_cdata`,
|
|
23
25
|
`create_native_comment`, `create_native_processing_instruction`,
|
|
24
26
|
`create_native_declaration`, `create_native_doctype`,
|
|
@@ -56,8 +58,9 @@ the tracked native; wrappers re-key through `refresh_native!`.
|
|
|
56
58
|
Serialization::
|
|
57
59
|
`serialize(node, options)`. Options: `indent`, `encoding`,
|
|
58
60
|
`declaration`, `no_declaration`, `expand_empty`, `line_ending`,
|
|
59
|
-
`indent_text` (the indent-unit string —
|
|
60
|
-
|
|
61
|
+
`indent_text` (the indent-unit string — Nokogiri and
|
|
62
|
+
leptris >= 1.9.45; leptris text-bearing leaves wait on
|
|
63
|
+
leptris/leptris#658).
|
|
61
64
|
Entity-marker restoration is owned by the wrapper layer
|
|
62
65
|
(`Node#to_xml`), guarded by `entity_bearing?`.
|
|
63
66
|
|
|
@@ -30,6 +30,11 @@ ctx.config.adapter_name # => :leptris / :nokogiri / :rexml (Opal)
|
|
|
30
30
|
|
|
31
31
|
== Parse options
|
|
32
32
|
|
|
33
|
+
`noblanks: true`::
|
|
34
|
+
Drop whitespace-only text nodes (libxml2 `XML_PARSE_NOBLANKS`
|
|
35
|
+
parity, issue #153) — the parse shape canon's pretty-printer
|
|
36
|
+
compares against `Nokogiri::XML(xml, &:noblanks)`.
|
|
37
|
+
|
|
33
38
|
`readonly: true`::
|
|
34
39
|
The binding memoizes every read and refuses mutations — the
|
|
35
40
|
parse-and-read lifecycle for multi-pass consumers (comparison, diff,
|
|
@@ -62,13 +67,13 @@ implementation over one `leptris_node_traverse` call.
|
|
|
62
67
|
|
|
63
68
|
== Known limitations (tracked upstream)
|
|
64
69
|
|
|
70
|
+
* Tab indentation honors the indent-unit string on leptris >= 1.9.45
|
|
71
|
+
(`indent_text:`), byte-identical to Nokogiri on element-only
|
|
72
|
+
trees; text-bearing leaves still emit spaces until the engine fix
|
|
73
|
+
(leptris/leptris#658).
|
|
65
74
|
* A PI preceding the DOCTYPE reorders on serialization — libleptris
|
|
66
75
|
normalizes DOCTYPE-first and the document node does not record its
|
|
67
76
|
relative position.
|
|
68
|
-
* Tab indentation: the binding's `indent_text` is the display-form
|
|
69
|
-
boolean, not Nokogiri's indent-unit string — the unit ask is
|
|
70
|
-
leptris-ruby#109. moxml forwards `indent_text:` to Nokogiri
|
|
71
|
-
meanwhile.
|
|
72
77
|
|
|
73
78
|
Resolved with leptris-ruby 1.9.42 (leptris/leptris#636/#612): child
|
|
74
79
|
PIs serialize on their own indented lines, DOCTYPE internal subsets
|
|
@@ -63,11 +63,15 @@ module Moxml
|
|
|
63
63
|
include_decl = options.fetch(:declaration) do
|
|
64
64
|
options[:no_declaration] ? false : document_has_declaration?(node)
|
|
65
65
|
end
|
|
66
|
-
|
|
66
|
+
kwargs = {
|
|
67
67
|
indent: options.fetch(:indent, 0),
|
|
68
68
|
no_decl: !include_decl,
|
|
69
69
|
encoding: options[:encoding],
|
|
70
|
-
|
|
70
|
+
}
|
|
71
|
+
if INDENT_UNIT_SUPPORTED && options[:indent_text].is_a?(String)
|
|
72
|
+
kwargs[:indent_text] = options[:indent_text]
|
|
73
|
+
end
|
|
74
|
+
xml = node.to_xml(**kwargs)
|
|
71
75
|
# Element output always ends with the close tag — but the
|
|
72
76
|
# engine's serializer appends a stray trailing newline when
|
|
73
77
|
# the element's last text child is non-ASCII (fixed engine
|
|
@@ -40,6 +40,15 @@ module Moxml
|
|
|
40
40
|
LIBXML2_LAYOUT_PARITY =
|
|
41
41
|
Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.42")
|
|
42
42
|
|
|
43
|
+
# leptris-ruby#109 (1.9.45): Element#to_xml takes the
|
|
44
|
+
# indent-unit string, so moxml's per-child document composition
|
|
45
|
+
# can carry `indent_text:` through. Text-bearing leaves still
|
|
46
|
+
# emit spaces until the engine fix (leptris/leptris#658); the
|
|
47
|
+
# boolean display form stays document-level and is never
|
|
48
|
+
# forwarded (the element face raises on it).
|
|
49
|
+
INDENT_UNIT_SUPPORTED =
|
|
50
|
+
Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.45")
|
|
51
|
+
|
|
43
52
|
NO_PARSE_ERRORS = [].freeze
|
|
44
53
|
private_constant :NO_PARSE_ERRORS
|
|
45
54
|
|
|
@@ -81,7 +90,7 @@ module Moxml
|
|
|
81
90
|
::Leptris::XML::Document.parse(
|
|
82
91
|
processed,
|
|
83
92
|
readonly: options[:readonly] == true,
|
|
84
|
-
options:
|
|
93
|
+
options: parse_flags(options),
|
|
85
94
|
)
|
|
86
95
|
rescue ::Leptris::XML::ParseError => e
|
|
87
96
|
# libleptris has no recovery mode that survives unclosed
|
|
@@ -104,11 +113,16 @@ module Moxml
|
|
|
104
113
|
doc
|
|
105
114
|
end
|
|
106
115
|
|
|
107
|
-
# nil
|
|
108
|
-
# options hash as plain defaults (
|
|
109
|
-
#
|
|
110
|
-
|
|
111
|
-
|
|
116
|
+
# nil when no parse flag is requested — the binding treats a
|
|
117
|
+
# nil options hash as plain defaults (matching libxml2/
|
|
118
|
+
# Nokogiri semantics: blanks kept, no ATTLIST defaults).
|
|
119
|
+
# noblanks (issue #153) drops whitespace-only text nodes,
|
|
120
|
+
# libxml2 XML_PARSE_NOBLANKS parity.
|
|
121
|
+
def parse_flags(options)
|
|
122
|
+
flags = 0
|
|
123
|
+
flags |= ::Leptris::XML::ParseOptions::DTDATTR if options[:dtdattr] == true
|
|
124
|
+
flags |= ::Leptris::XML::ParseOptions::NOBLANKS if options[:noblanks] == true
|
|
125
|
+
flags.zero? ? nil : ::Leptris::XML::ParseOptions.new(flags)
|
|
112
126
|
end
|
|
113
127
|
|
|
114
128
|
def parse_errors(native_doc)
|
|
@@ -26,11 +26,13 @@ module Moxml
|
|
|
26
26
|
::Nokogiri::XML::DocumentFragment.parse(processed_xml) do |config|
|
|
27
27
|
config.strict.nonet
|
|
28
28
|
config.recover unless options[:strict]
|
|
29
|
+
config.noblanks if options[:noblanks]
|
|
29
30
|
end
|
|
30
31
|
else
|
|
31
32
|
::Nokogiri::XML(processed_xml, nil, "UTF-8") do |config|
|
|
32
33
|
config.strict.nonet
|
|
33
34
|
config.recover unless options[:strict]
|
|
35
|
+
config.noblanks if options[:noblanks]
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
rescue ::Nokogiri::XML::SyntaxError => e
|
data/lib/moxml/version.rb
CHANGED
|
@@ -185,6 +185,33 @@ RSpec.describe Moxml::Adapter::Leptris do
|
|
|
185
185
|
expect(doc.to_xml).to include("<?renamed changed?>")
|
|
186
186
|
end
|
|
187
187
|
|
|
188
|
+
it "matches raw Nokogiri with tab units on element-only trees" do
|
|
189
|
+
skip "requires the indent unit (leptris 1.9.45+)" unless described_class::INDENT_UNIT_SUPPORTED
|
|
190
|
+
|
|
191
|
+
source = %(<r><a><b/></a><c><d/><e/></c></r>)
|
|
192
|
+
target = Nokogiri::XML(source).to_xml(indent: 2, indent_text: "\t", encoding: "UTF-8")
|
|
193
|
+
output = ctx.parse(source).to_xml(
|
|
194
|
+
indent: 2, declaration: true, expand_empty: false,
|
|
195
|
+
encoding: "UTF-8", indent_text: "\t"
|
|
196
|
+
)
|
|
197
|
+
expect(output).to eq(target)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it "drops space-only text nodes with noblanks and matches Nokogiri (issue #153)" do
|
|
201
|
+
source = %(<a><t>1</t> <n/></a>)
|
|
202
|
+
recipe = {
|
|
203
|
+
indent: 2, declaration: true, expand_empty: false, encoding: "UTF-8"
|
|
204
|
+
}
|
|
205
|
+
target = Nokogiri::XML(source, &:noblanks).to_xml(indent: 2, encoding: "UTF-8")
|
|
206
|
+
|
|
207
|
+
doc = ctx.parse(source, noblanks: true)
|
|
208
|
+
expect(doc.root.children.to_a.select(&:text?)).to be_empty
|
|
209
|
+
expect(doc.to_xml(recipe)).to eq(target)
|
|
210
|
+
|
|
211
|
+
via_nokogiri = Moxml.new(:nokogiri).parse(source, noblanks: true).to_xml(recipe)
|
|
212
|
+
expect(via_nokogiri).to eq(target)
|
|
213
|
+
end
|
|
214
|
+
|
|
188
215
|
it "reports the tracked native for a re-added document PI" do
|
|
189
216
|
doc = ctx.parse("<?pi-src orig?><root/>")
|
|
190
217
|
moved = doc.children.to_a[0]
|
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.18
|
|
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-08-
|
|
11
|
+
date: 2026-08-31 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
|