moxml 0.5.19 → 0.5.20

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 62f62c2c744354f3dc8c6436cd5404eac78738bc3da00509c1daed9e827d5195
4
- data.tar.gz: 25cddfe9066c8ebda91925a47834fb3180aaefc2b7be5f74b32409a3bdd44ffb
3
+ metadata.gz: 59c8df5982f2b80280386a94385ceed9a65b1b80524772d914e19052a564aedd
4
+ data.tar.gz: 3e3432a24b65e60bddf345955d4454a5a459f4898693fa9037b71e8a052a6115
5
5
  SHA512:
6
- metadata.gz: 4598f34a5af3aa247349f0bf0cd5ea99fceb2a60c02412b31b3e6ecc391f0e5292668b5ca9c8bb2be304dee1cc7e3706e932ffe3c73ceaa9e0f9d45476c4fa24
7
- data.tar.gz: e7c39fcc1a5dad848d9b4484e6065b3af1a890a8b4085a5d7cf731d20010a480d6ef0e2c6f8cbd7a579cc9c524360364475c2fb29c1704632fa7472a25a2eabc
6
+ metadata.gz: 3c041e77c6230d320e5a2779f08ffe29505780d4eac520ce1c12c83d5532102153787b592d999067daef2aabfedf08c5a1830d374baa224a9d795e20816faf69
7
+ data.tar.gz: 54367812683befdea88202d68a7c15c14b91184e3d350cef9510d94a8e6c769d307f311282041d2816626de181697a8f78b429cb7e71ae2b2d11638d34d0a1f9
@@ -76,6 +76,9 @@ module Moxml
76
76
  # only walks the root subtree, so declaration, DOCTYPE, PIs and
77
77
  # document-level text are assembled around it explicitly.
78
78
  def serialize_document(doc, options)
79
+ fast = fast_document_output(doc, options)
80
+ return fast if fast
81
+
79
82
  # Nokogiri's document shape: every top-level part is
80
83
  # newline-terminated, at any indent — declaration, DOCTYPE,
81
84
  # document PIs, the root element, trailing newline after it.
@@ -108,6 +111,69 @@ module Moxml
108
111
  parts.join
109
112
  end
110
113
 
114
+ # Issue #158: the engine's whole-document serializer is one C
115
+ # call; the composed path serializes the root through the
116
+ # element face, which copies the subtree into a fresh document
117
+ # on every call (~4.5x slower end to end). The engine's output
118
+ # is byte-identical to the composed one EXCEPT epilog parts
119
+ # glue directly to the root — so the fast path declines
120
+ # whenever anything follows the root, any attachment overrides
121
+ # a part, or the engine's declaration line differs from the
122
+ # facade's canonical form (checked post-hoc: a source
123
+ # declaration carrying standalone or another version would
124
+ # diverge).
125
+ def fast_document_output(doc, options)
126
+ return nil unless LIBXML2_LAYOUT_PARITY
127
+ return nil if attachments.get(doc, :declaration) ||
128
+ attachments.get(doc, :doctype) ||
129
+ attachments.get(doc, :document_text) ||
130
+ attachments.get(doc, :entity_markers)
131
+
132
+ include_decl = !options[:no_declaration] && options.fetch(:declaration) do
133
+ document_has_declaration?(doc)
134
+ end
135
+
136
+ root_seen = false
137
+ doc.children.each do |child|
138
+ if child.is_a?(::Leptris::XML::Element)
139
+ return nil if root_seen
140
+
141
+ root_seen = true
142
+ elsif root_seen
143
+ # Epilog parts glue directly to the root in the engine's
144
+ # document output — compose those.
145
+ return nil
146
+ end
147
+ end
148
+
149
+ # The engine's subset serializer mangles every declaration
150
+ # after the first (loses its "<") — moxml's own formatter is
151
+ # correct, so multi-declaration subsets compose.
152
+ dt = doc.doctype
153
+ if dt&.class&.method_defined?(:internal_subset) &&
154
+ (subset = dt.internal_subset) && subset.scan("<!").size > 1
155
+ return nil
156
+ end
157
+
158
+ kwargs = {
159
+ indent: options.fetch(:indent, 0),
160
+ no_decl: !include_decl,
161
+ encoding: options[:encoding],
162
+ }
163
+ if INDENT_UNIT_SUPPORTED && options[:indent_text].is_a?(String)
164
+ kwargs[:indent_text] = options[:indent_text]
165
+ end
166
+ output = doc.to_xml(**kwargs)
167
+ return nil if output.nil? || output.empty?
168
+
169
+ if include_decl && !output.start_with?(default_declaration_xml(doc, options))
170
+ return nil
171
+ end
172
+
173
+ output << "\n" unless output.end_with?("\n")
174
+ output
175
+ end
176
+
111
177
  def native_doctype_xml(doc)
112
178
  dt = doc.doctype
113
179
  return nil unless dt
data/lib/moxml/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Moxml
4
- VERSION = "0.5.19"
4
+ VERSION = "0.5.20"
5
5
  end
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.19
4
+ version: 0.5.20
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-31 00:00:00.000000000 Z
11
+ date: 2026-09-01 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