moxml 0.5.172 → 0.5.174

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: f8719e57bb76ceb63baa171d151028d8aff538fc351be7397b6ec5a492c8bdf1
4
- data.tar.gz: 8fa85d23570f0588da0eb5d4ce5f83d59fb28e325d587f7210d3380a8afd5e33
3
+ metadata.gz: b5f92e477a3f081f711febd54ab9425573ead518fd44ff6341744ce5e421a485
4
+ data.tar.gz: 1c7f9d77b19a460b90dc6f8ca0cb1af76c3d1a95f36e484d4a56bf2cd7be03c5
5
5
  SHA512:
6
- metadata.gz: b93fc457a9d7435e2a55cb4fb5e3320d37b5949e77b184c640dd65a8b21954aab9987f204c8916411d9bfe6e11f7f0e358faa78f1ee9cfe3477f52b2d209e857
7
- data.tar.gz: 78c66d6b3bdbb800b8cf23dde851235ab3a621bbb30fd0c413db06f9f856ba245b56f9a2c4a4d8220ca313b3bb2ef447d5737733387052bd82f2151cfd7bcdc5
6
+ metadata.gz: 654e595f1b8e8e847761e670a73565b8ef7b783a09942586bb93ae6199951d192c267359cd6f8c4f7968ed125d593119f5a47b92a04a907505bb7f1b9e1da6d0
7
+ data.tar.gz: 04f8045e8e42310697de9a141e163a41e1bde33f9a3f9451a463c5f68683e21928cac81770112cd9c30b8c2c0acaaa04a913a7ff212d4a38f660a778eb7b35bb
data/Gemfile CHANGED
@@ -9,7 +9,7 @@ gemspec
9
9
  gem "benchmark"
10
10
  gem "benchmark-ips"
11
11
  gem "get_process_mem"
12
- gem "leptris", "~> 1.9.382"
12
+ gem "leptris", "~> 1.9.386"
13
13
  gem "libxml-ruby", ">= 5.0"
14
14
  gem "nokogiri", "~> 1.18"
15
15
  gem "openssl", "~> 3.0"
data/README.adoc CHANGED
@@ -72,7 +72,7 @@ https://github.com/leptris/leptris-ruby[leptris-ruby] FFI binding
72
72
  every measured bulk operation — parse, XPath, serialization, SAX, and
73
73
  the compiled Moxml::Plan / Moxml::StructPlan materialization paths
74
74
  (StructPlan runs 2.3-2.6x raw Nokogiri on the benchmark shape);
75
- requires leptris >= 1.9.32 (see version table below).
75
+ requires leptris >= 1.9.386.0 (see version table below).
76
76
 
77
77
  === Underlying library versions
78
78
 
@@ -111,32 +111,18 @@ same libxml2 engine, governed by the consistency suite). Removal
111
111
  after the deprecation cycle.
112
112
 
113
113
  |Leptris (leptris-ruby)
114
- |>= 1.9.194.1
115
- |Hard floor — `MINIMUM_BINDING_VERSION`; older bindings do not load.
116
- Raised from 1.9.32 (2026-09-20): every known consumer resolves a
117
- modern binding, and the sub-1.9.194 accommodation paths are deleted.
118
- Newer bindings unlock more native surface automatically:
119
- 1.9.194.1+ hot-read aliases, 1.9.201.1+ the C struct
120
- executor (`Moxml::StructPlan`; the floor is the varargs-mint fix),
121
- 1.9.204+ native document-level parts (created DOCTYPEs as native
122
- nodes, document-PI removal, declaration clear), 1.9.240+ the bulk
123
- SAX record drain (`Handler#on_sax_records`) — and 1.9.242+ is
124
- REQUIRED for that drain to be CORRECT: 1.9.240/241 drain documents
125
- containing duplicate attributes without surfacing the fatal error
126
- (moxml#281), so the drain arms only on 1.9.242+, where such
127
- documents fall back to the callback path and the error fires.
128
- 1.9.255.2+ C-minted walk/build wrappers (construction identity
129
- without the Ruby mint); 1.9.273.1+ opt-in parse-skip flags
130
- (`skip_dup_detection`, `skip_source_positions`); 1.9.290.0+ XSLT
131
- top-level params threading and the bulk child-list append
132
- (one crossing for N children); 1.9.292.0+ native cross-document
133
- root adoption (the engine deep-copies a foreign root in C).
134
- Current recommendation: 1.9.292+ (the native-adoption train;
135
- carries the plan-ABI surface, the 1.9.290 XSLT-params and
136
- bulk-append faces, and the 1.9.292 engine deep-copy root install).
114
+ |>= 1.9.386.0
115
+ |ENFORCED hard floor — `MINIMUM_BINDING_VERSION`; the adapter refuses
116
+ to load below it. Raised 1.9.32 → 1.9.194.1 (2026-09-20) → 1.9.386.0
117
+ (2026-10-30, the tested pair): every accommodation path below it is
118
+ deleted and all native faces through the 1.9.385 parent-axis train
119
+ are unconditional. The capability report
120
+ (`Moxml::Adapter::Leptris.capabilities`) answers what the installed
121
+ pair serves; cross-import schema sets (`Context#xsd_set`) ride the
122
+ compile_set face (1.9.386.0 ✓).
137
123
  |===
138
124
 
139
- NOTE: moxml's dev Gemfile pins `leptris ~> 1.9.321` (the tested pair; the gemspec itself has zero runtime dependencies). Consumers of the leptris adapter should run leptris 1.9.320+ — earlier engines carry silent wrong-answer plan-path defects (moxml#344); moxml gates degrade to the always-correct slower paths below it.
125
+ NOTE: moxml's dev Gemfile pins `leptris ~> 1.9.386` (the tested pair; the gemspec itself has zero runtime dependencies). The adapter enforces the floor at load.
140
126
  `ox ~> 2.14`, `libxml-ruby >= 5.0`, and the vendored oga fork — the CI
141
127
  matrix tests exactly those floors.
142
128
 
@@ -147,7 +133,7 @@ the runtime environment:
147
133
 
148
134
  . If running on Opal (`RUBY_ENGINE == "opal"`), Oga is used (pure Ruby, no C extensions)
149
135
  . Otherwise, if the installed leptris gem supports programmatic document
150
- construction (`Leptris::XML::Document.create`, leptris >= 1.9.32), Leptris is used
136
+ construction (`Leptris::XML::Document.create`, leptris >= 1.9.386.0), Leptris is used
151
137
  . Otherwise, Moxml detects already-loaded XML libraries in this order:
152
138
  .. Nokogiri
153
139
  .. Ox
@@ -158,7 +144,7 @@ the runtime environment:
158
144
  ----
159
145
  # Automatic detection — picks the best available adapter
160
146
  ctx = Moxml.new
161
- ctx.config.adapter_name # => :leptris (leptris >= 1.9.32), :nokogiri otherwise, :oga on Opal
147
+ ctx.config.adapter_name # => :leptris (leptris >= 1.9.386.0), :nokogiri otherwise, :oga on Opal
162
148
 
163
149
  # Explicit override — always takes precedence
164
150
  ctx = Moxml.new(:ox)
@@ -48,6 +48,7 @@ Generated by `bundle exec rake docs:coverage` from the coverage matrix and the d
48
48
  | validation schema sets | equivalent | equivalent | equivalent | equivalent | equivalent | equivalent | equivalent
49
49
  | validation substitution dismissal | equivalent | equivalent | equivalent | equivalent | equivalent | equivalent | equivalent
50
50
  | loud capability contracts | equivalent | equivalent | equivalent | equivalent | equivalent | equivalent | equivalent
51
+ | engine capability report | equivalent | equivalent | equivalent | equivalent | equivalent | equivalent | equivalent
51
52
  |===
52
53
 
53
54
  *equivalent* — all adapters answer the same observable result. *loud (...)* — the adapter raises the named error for that face. *D-NN* — a registered divergence in link:divergences.html[the register], with its rationale. Every cell cites a pin; see the processing model's `Pins::` line for the enforcing specs.
@@ -314,7 +314,7 @@ answers without raising. RELAX NG rides engines with an RNG face
314
314
 
315
315
  === Errors and loud degradation
316
316
 
317
- Pins:: `spec/consistency/loud_degradation_spec.rb`
317
+ Pins:: `spec/consistency/loud_degradation_spec.rb`, `spec/moxml/adapter_capabilities_spec.rb`
318
318
 
319
319
  * `Moxml::Error` hierarchy; `Moxml::XPathError`, `Moxml::XsltError`,
320
320
  `Moxml::AdapterError` (e.g. schema-handle/adapter misroute),
@@ -324,6 +324,12 @@ Pins:: `spec/consistency/loud_degradation_spec.rb`
324
324
  * Adapter degradation is loud: a present-but-unusable preferred adapter
325
325
  warns at configuration and misroutes fail at the wrap, not deep in
326
326
  a call.
327
+ * Engines with a capability story answer `Adapter.capabilities` — one
328
+ frozen report of the runtime-variable faces they serve plus their
329
+ engine version, queried once at attach. The support faces (xsd,
330
+ relaxng, xslt, digest) answer even when unconditional; internal
331
+ routing gates the floor made constant are absent by design.
332
+ Adapters without a capability story answer nil.
327
333
 
328
334
  === Performance: a declared, non-semantic channel
329
335
 
@@ -698,6 +698,15 @@ namespace_validation_mode: :strict)
698
698
  nil
699
699
  end
700
700
 
701
+ # The engine capability report (#493): a frozen hash of the
702
+ # runtime-variable faces this adapter serves, plus its engine
703
+ # version — queried once at attach, never version-gate
704
+ # constants. Adapters without a capability story answer nil
705
+ # (documented last resort, plan_rows-style).
706
+ def capabilities
707
+ nil
708
+ end
709
+
701
710
  # Struct-plan executor (Moxml::StructPlan): +spec+ compiles
702
711
  # the consumer's shape as {name => [Struct class, attrs
703
712
  # Hash (name => slot Symbol), text slot, children slot]}.
@@ -29,7 +29,22 @@ module Moxml
29
29
  # Raised 1.9.32 -> 1.9.194.1 (2026-09-20): every known consumer
30
30
  # resolves a modern binding (canon itself pins ~> 1.9.193), and
31
31
  # the sub-1.9.194 accommodation paths are deleted.
32
- MINIMUM_BINDING_VERSION = "1.9.194.1"
32
+ # Raised 1.9.194.1 -> 1.9.386.0 (2026-10-30, owner directive
33
+ # "raise all floors"): the tested pair — every gate below it
34
+ # unwound, and the floor is ENFORCED (the load refuses below it;
35
+ # the README's "older bindings do not load" claim is now true).
36
+ MINIMUM_BINDING_VERSION = "1.9.386.0"
37
+
38
+ if Gem::Version.new(::Leptris::VERSION.to_s) <
39
+ Gem::Version.new(MINIMUM_BINDING_VERSION)
40
+ raise Moxml::AdapterError.new(
41
+ "the leptris binding is #{::Leptris::VERSION}; moxml requires " \
42
+ ">= #{MINIMUM_BINDING_VERSION} (the tested floor — older " \
43
+ "bindings are untested and their accommodation paths are deleted)",
44
+ adapter: :leptris,
45
+ operation: "load",
46
+ )
47
+ end
33
48
 
34
49
  # leptris_parse_html_string shipped in bindings 1.9.80
35
50
  # (libleptris 1.9.75, engine #659) as Leptris::XML.parse_html.
@@ -193,8 +208,7 @@ module Moxml
193
208
  # so the gate names the first release where the drain is
194
209
  # CORRECT, not merely present. Dev floor pins ~> 1.9.238;
195
210
  # older bindings take the callback Parser below.
196
- NATIVE_SAX_RECORDS =
197
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.242")
211
+ NATIVE_SAX_RECORDS = true
198
212
 
199
213
  # Document#absorb (engine #1548): one call transfers a source
200
214
  # document's pool ownership into the destination, so
@@ -208,8 +222,7 @@ module Moxml
208
222
  # lesson).
209
223
  NATIVE_DOC_ABSORB =
210
224
  defined?(::Leptris::XML::Document) &&
211
- ::Leptris::XML::Document.method_defined?(:absorb) &&
212
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.311.3")
225
+ ::Leptris::XML::Document.method_defined?(:absorb)
213
226
 
214
227
  # Document#to_html indent kwargs (issue #354, engine
215
228
  # leptris#1637 via leptris-ruby#421): the nested HTML layout
@@ -218,7 +231,6 @@ module Moxml
218
231
  # to_html takes no kwargs and would raise ArgumentError from
219
232
  # the pass-through.
220
233
  HTML_SERIALIZE_INDENT =
221
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.338.0") &&
222
234
  defined?(::Leptris::XML::Document) &&
223
235
  ::Leptris::XML::Document.method_defined?(:to_html) &&
224
236
  ::Leptris::XML::Document.instance_method(:to_html)
@@ -240,7 +252,6 @@ module Moxml
240
252
  # the rescue-to-empty fallback. The kwarg probe pairs the
241
253
  # floor (a binding without the kwarg cannot arm).
242
254
  RECOVER_MODE =
243
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.344.0") &&
244
255
  ::Leptris::XML::ParseOptions.instance_method(:initialize)
245
256
  .parameters.any? { |_, key| key == :recover }
246
257
 
@@ -250,7 +261,6 @@ module Moxml
250
261
  # per-attribute reads behind ::Leptris::XML::Element
251
262
  # #attribute_pairs.
252
263
  ELEMENT_ATTR_SNAPSHOT =
253
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.353.0") &&
254
264
  ::Leptris::XML::Element.method_defined?(:attributes_snapshot)
255
265
 
256
266
  # Markup-accumulating builder face (leptris-ruby#374 lever 2,
@@ -263,7 +273,6 @@ module Moxml
263
273
  # pairs the gate (misrelease races — NATIVE_PLAN_STRUCTS
264
274
  # lesson).
265
275
  NATIVE_XSD =
266
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.321.0") &&
267
276
  defined?(::Leptris::XML::XSD) &&
268
277
  ::Leptris::XML::FFI.respond_to?(:leptris_xsd_validate)
269
278
 
@@ -284,15 +293,13 @@ module Moxml
284
293
  # finalizer and frees now. Face-probed with the version
285
294
  # floor (the NATIVE_DOC_ABSORB pairing).
286
295
  XSD_RELEASE =
287
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.342.0") &&
288
296
  defined?(::Leptris::XML::XSD::Schema) &&
289
297
  ::Leptris::XML::XSD::Schema.method_defined?(:release)
290
298
 
291
299
  NATIVE_BUILDER =
292
300
  defined?(::Leptris::XML::Builder) &&
293
301
  defined?(::Leptris::XML::Document) &&
294
- ::Leptris::XML::Document.method_defined?(:build) &&
295
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.313.0")
302
+ ::Leptris::XML::Document.method_defined?(:build)
296
303
 
297
304
  # XSLT 1.0/2.0/3.0 through the engine's compiled-stylesheet
298
305
  # faces (Moxml::XSLT contract). Top-level parameters are not
@@ -320,6 +327,34 @@ module Moxml
320
327
  BINDING_OF_CAP = 8_192
321
328
 
322
329
  class << self
330
+ # The engine capability report (#493): one structured face
331
+ # answering what THIS installed binding+engine serves, queried
332
+ # once at attach — the replacement for the version-gate-
333
+ # constant class. The support faces (xsd, relaxng, xslt,
334
+ # digest) answer even when the floor makes them unconditional —
335
+ # consumers ask for them by name; the internal routing gates
336
+ # the floor made constant are absent by design. Frozen; the
337
+ # keys are the model's capability names.
338
+ def capabilities
339
+ @capabilities ||= {
340
+ engine_version: ::Leptris::VERSION,
341
+ native_read_layer: !NATIVE_READ_LAYER.nil?,
342
+ native_xpath_seams: !NATIVE_XPATH_SEAMS.nil?,
343
+ bulk_xpath_rows: BULK_XPATH_ROWS,
344
+ add_element_full: ADD_ELEMENT_FULL,
345
+ native_strings_utf8: !NATIVE_STRINGS_UTF8.nil?,
346
+ native_mutations_coherent: !NATIVE_MUTATIONS_COHERENT.nil?,
347
+ native_entity_refs: !NATIVE_ENTITY_REFS.nil?,
348
+ native_bulk_fixed: !NATIVE_BULK_FIXED.nil?,
349
+ native_plan_structs: NATIVE_PLAN_STRUCTS,
350
+ native_plan_typed: NATIVE_PLAN_TYPED,
351
+ digest: DIGEST_SUPPORTED,
352
+ xsd: XSD_SUPPORTED,
353
+ relaxng: RELAXNG_SUPPORTED,
354
+ xslt: XSLT_SUPPORTED,
355
+ }.freeze
356
+ end
357
+
323
358
  # WeakMap has no #clear — 0.5.100's valve crashed every parse
324
359
  # crossing the cap on 3.4+ (NoMethodError). Replace the
325
360
  # registry wholesale, type-preserving: the WeakMap flavor
@@ -546,9 +581,7 @@ module Moxml
546
581
  # there.
547
582
  NATIVE_IDENTITY = NATIVE_MUTATIONS_COHERENT
548
583
 
549
- NATIVE_C_MINT =
550
- NATIVE_IDENTITY &&
551
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.255.2")
584
+ NATIVE_C_MINT = NATIVE_IDENTITY
552
585
 
553
586
  NATIVE_KLASS_CHILDREN = NATIVE_IDENTITY
554
587
  end
@@ -1007,7 +1040,6 @@ module Moxml
1007
1040
  # of NoMethodError-ing — the 1.9.199.0 lesson).
1008
1041
  NATIVE_XSLT_PARAMS =
1009
1042
  NATIVE_READ_LAYER &&
1010
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.290.0") &&
1011
1043
  ::Leptris::XML::XSLT::Stylesheet.instance_method(:apply_to)
1012
1044
  .parameters.size > 1
1013
1045
 
@@ -1177,8 +1209,7 @@ module Moxml
1177
1209
  # SILENT wrong answers, so the gate names the fixed engine:
1178
1210
  # below 1.9.320.0 the plan faces degrade to the
1179
1211
  # always-correct generic wrapper walk.
1180
- NATIVE_PLAN_ROWS =
1181
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.320.0")
1212
+ NATIVE_PLAN_ROWS = true
1182
1213
 
1183
1214
  # leptris-ruby#272 (binding 1.9.201.1): Native.plan_structs —
1184
1215
  # the C struct executor behind Moxml::StructPlan. The floor
@@ -1193,9 +1224,8 @@ module Moxml
1193
1224
  # captures) — the struct executor degrades to the Ruby Plan
1194
1225
  # fallback below the fix, same as the varargs-mint floor.
1195
1226
  NATIVE_PLAN_STRUCTS =
1196
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.320.0") &&
1197
- (!defined?(::Leptris::XML::Native) ||
1198
- ::Leptris::XML::Native.respond_to?(:plan_structs))
1227
+ !defined?(::Leptris::XML::Native) ||
1228
+ ::Leptris::XML::Native.respond_to?(:plan_structs)
1199
1229
 
1200
1230
  # leptris-ruby#275 (binding 1.9.204, the remove half of the
1201
1231
  # document-level surfaces): remove_pi, clear_declaration,
@@ -1211,7 +1241,6 @@ module Moxml
1211
1241
  ::Leptris::XML::Native.respond_to?(:plan_structs_typed?)
1212
1242
 
1213
1243
  NATIVE_DOC_PARTS =
1214
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.204.0") &&
1215
1244
  ::Leptris::XML::Document.method_defined?(:remove_doctype) &&
1216
1245
  ::Leptris::XML::Document.method_defined?(:clear_declaration)
1217
1246
 
@@ -2259,9 +2288,7 @@ module Moxml
2259
2288
  end
2260
2289
  end
2261
2290
 
2262
- NATIVE_ROOT_ADOPT =
2263
- NATIVE_READ_LAYER &&
2264
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.292.0")
2291
+ NATIVE_ROOT_ADOPT = NATIVE_READ_LAYER
2265
2292
 
2266
2293
  # The engine deep-copies the foreign subtree into the target
2267
2294
  # document's pool (leptris#1495) and the binding memoizes the
@@ -3406,9 +3433,7 @@ module Moxml
3406
3433
  end
3407
3434
  end
3408
3435
 
3409
- NATIVE_APPEND_CHILDREN =
3410
- NATIVE_READ_LAYER &&
3411
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.290.0")
3436
+ NATIVE_APPEND_CHILDREN = NATIVE_READ_LAYER
3412
3437
 
3413
3438
  def replace_children(node, new_children)
3414
3439
  # Cross-pool children: the binding's bulk face adopts per
@@ -3862,8 +3887,7 @@ module Moxml
3862
3887
  # (parent-of-attribute names the OWNER element) plus the
3863
3888
  # cross-doc adopt attribute-chain fix, and standoc's svg
3864
3889
  # id cleanup rides `./@id/..` hot (moxml#474).
3865
- PARENT_AXIS_NATIVE =
3866
- Gem::Version.new(::Leptris::VERSION) >= Gem::Version.new("1.9.385")
3890
+ PARENT_AXIS_NATIVE = true
3867
3891
  NON_PARENT_REVERSE_AXES = %w[ancestor ancestor-or-self
3868
3892
  preceding preceding-sibling].freeze
3869
3893
  REVERSE_AXIS_CACHE = XPath::Cache.new(200)
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.172"
4
+ VERSION = "0.5.174"
5
5
  end
@@ -93,11 +93,11 @@ RSpec.describe Moxml::Adapter do
93
93
  end
94
94
  end
95
95
 
96
- it "pins the leptris binding floor at 1.9.194.1 (issue #149; raised 2026-09-20)" do
96
+ it "pins the leptris binding floor at 1.9.386.0 (raised 2026-09-20, raised again 2026-10-30; enforced at load)" do
97
97
  skip "leptris not installed" unless described_class.available?(:leptris)
98
98
 
99
99
  adapter = described_class.load(:leptris)
100
- expect(adapter::MINIMUM_BINDING_VERSION).to eq("1.9.194.1")
100
+ expect(adapter::MINIMUM_BINDING_VERSION).to eq("1.9.386.0")
101
101
  expect(Gem::Version.new(Leptris::VERSION))
102
102
  .to be >= Gem::Version.new(adapter::MINIMUM_BINDING_VERSION)
103
103
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Processing model §Errors and loud degradation (normative): pinned here.
4
+
5
+ require "spec_helper"
6
+
7
+ # The engine capability report (#493): one structured face answering
8
+ # what the installed binding+engine serves — queried once at attach,
9
+ # the replacement for the version-gate-constant class. Only
10
+ # runtime-variable faces appear; anything the floor makes
11
+ # unconditional is absent by design.
12
+ RSpec.describe "engine capability report" do
13
+ it "answers for leptris with the engine version and known faces" do
14
+ caps = Moxml::Adapter::Leptris.capabilities
15
+ expect(caps).to be_frozen
16
+ expect(caps[:engine_version]).to match(/\A1\.\d+\.\d+/)
17
+ expect(caps.keys).to include(
18
+ :native_read_layer, :native_plan_structs, :native_plan_typed,
19
+ :xsd, :relaxng, :xslt, :digest
20
+ )
21
+ end
22
+
23
+ it "reports only booleans beyond the version" do
24
+ caps = Moxml::Adapter::Leptris.capabilities
25
+ caps.except(:engine_version).each_value do |value|
26
+ expect(value).to eql(true).or eql(false)
27
+ end
28
+ end
29
+
30
+ it "keeps the unwound internal gates out of the report" do
31
+ caps = Moxml::Adapter::Leptris.capabilities
32
+ expect(caps.keys).not_to include(
33
+ :prefixed_attr_predicates_native, :libxml2_layout_parity,
34
+ :indent_unit_supported, :element_unit_comments,
35
+ :native_bulk_sax_records, :native_document_parts, :native_plan_rows
36
+ )
37
+ expect(caps[:xsd]).to be(true)
38
+ expect(caps[:xslt]).to be(true)
39
+ end
40
+
41
+ it "is memoized — repeated queries answer the same frozen object" do
42
+ expect(Moxml::Adapter::Leptris.capabilities)
43
+ .to equal(Moxml::Adapter::Leptris.capabilities)
44
+ end
45
+
46
+ it "answers nil on adapters without a capability story" do
47
+ expect(Moxml::Adapter::Base.capabilities).to be_nil
48
+ end
49
+ end
@@ -113,6 +113,10 @@ module ModelCoverage
113
113
  section: "Errors and loud degradation",
114
114
  pin: "spec/consistency/loud_degradation_spec.rb",
115
115
  },
116
+ "engine capability report" => {
117
+ section: "Errors and loud degradation",
118
+ pin: "spec/moxml/adapter_capabilities_spec.rb",
119
+ },
116
120
  }.freeze
117
121
 
118
122
  # Normative sections that are not face families (meta/apparatus).
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.172
4
+ version: 0.5.174
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -514,6 +514,7 @@ files:
514
514
  - spec/moxml/adapter/rexml_spec.rb
515
515
  - spec/moxml/adapter/shared_examples/.gitkeep
516
516
  - spec/moxml/adapter/shared_examples/adapter_contract.rb
517
+ - spec/moxml/adapter_capabilities_spec.rb
517
518
  - spec/moxml/adapter_deprecation_spec.rb
518
519
  - spec/moxml/adapter_registry_spec.rb
519
520
  - spec/moxml/adapter_spec.rb