moxml 0.5.148 → 0.5.150

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.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/dependent-repos.json +7 -2
  3. data/.github/workflows/dependent-tests.yml +4 -1
  4. data/.github/workflows/nightly-fuzz.yml +80 -0
  5. data/.github/workflows/performance-release.yml +79 -0
  6. data/.github/workflows/performance.yml +59 -0
  7. data/Rakefile +23 -0
  8. data/benchmark/README.md +106 -0
  9. data/benchmark/scoreboard.json +115 -0
  10. data/benchmark/scoreboard.rb +556 -0
  11. data/bin/generate-model-coverage +21 -0
  12. data/docs/_pages/adapter-compatibility.adoc +3 -3
  13. data/docs/_pages/divergences.adoc +88 -39
  14. data/docs/_pages/ecosystem.adoc +62 -0
  15. data/docs/_pages/headed-ox-limitations.adoc +1 -1
  16. data/docs/_pages/headed-ox.adoc +2 -2
  17. data/docs/_pages/index.adoc +4 -0
  18. data/docs/_pages/model-coverage.adoc +57 -0
  19. data/docs/_pages/performance.adoc +29 -0
  20. data/docs/_pages/why-moxml.adoc +87 -0
  21. data/docs/_references/processing-model.adoc +69 -3
  22. data/lib/compat/opal/moxml_boot.rb +4 -0
  23. data/lib/moxml/adapter/base.rb +73 -0
  24. data/lib/moxml/adapter/leptris.rb +293 -23
  25. data/lib/moxml/adapter/libxml.rb +179 -25
  26. data/lib/moxml/adapter/nokogiri.rb +10 -0
  27. data/lib/moxml/adapter/oga.rb +71 -9
  28. data/lib/moxml/adapter/ox.rb +34 -2
  29. data/lib/moxml/adapter/rexml.rb +82 -17
  30. data/lib/moxml/c14n/data_model.rb +8 -0
  31. data/lib/moxml/c14n/processor.rb +17 -8
  32. data/lib/moxml/context.rb +33 -1
  33. data/lib/moxml/document.rb +18 -4
  34. data/lib/moxml/node.rb +75 -8
  35. data/lib/moxml/node_set.rb +42 -1
  36. data/lib/moxml/reference/normalizer.rb +63 -0
  37. data/lib/moxml/reference/parser.rb +417 -0
  38. data/lib/moxml/reference/writer.rb +121 -0
  39. data/lib/moxml/reference.rb +205 -0
  40. data/lib/moxml/relaxng.rb +62 -0
  41. data/lib/moxml/sax/block_handler.rb +7 -0
  42. data/lib/moxml/sax/handler.rb +20 -0
  43. data/lib/moxml/version.rb +1 -1
  44. data/lib/moxml/xpath/compiler.rb +17 -2
  45. data/lib/moxml/xpath/ordering.rb +97 -0
  46. data/lib/moxml/xpath.rb +29 -0
  47. data/lib/moxml.rb +2 -0
  48. data/spec/consistency/adapter_parity_spec.rb +24 -0
  49. data/spec/consistency/citation_hygiene_spec.rb +30 -0
  50. data/spec/consistency/differential_taxonomy_spec.rb +117 -0
  51. data/spec/consistency/divergence_register_spec.rb +9 -1
  52. data/spec/consistency/eol_normalization_spec.rb +2 -0
  53. data/spec/consistency/loud_degradation_spec.rb +2 -0
  54. data/spec/consistency/metamorphic_properties_spec.rb +195 -0
  55. data/spec/consistency/metamorphic_spec.rb +138 -0
  56. data/spec/consistency/model_coverage_audit_spec.rb +144 -61
  57. data/spec/consistency/published_docs_spec.rb +49 -0
  58. data/spec/consistency/reference_differential_spec.rb +186 -0
  59. data/spec/consistency/xpath_idioms_spec.rb +34 -5
  60. data/spec/consistency/xslt_spec.rb +2 -0
  61. data/spec/integration/shared_examples/edge_cases.rb +0 -13
  62. data/spec/moxml/adapter/leptris_attribute_snapshot_spec.rb +10 -7
  63. data/spec/moxml/adapter/leptris_spec.rb +23 -3
  64. data/spec/moxml/adapter/ox_spec.rb +1 -1
  65. data/spec/moxml/adapter/shared_examples/adapter_contract.rb +0 -8
  66. data/spec/moxml/attribute_resolver_spec.rb +35 -0
  67. data/spec/moxml/c14n/adapter_delegation_spec.rb +35 -6
  68. data/spec/moxml/c14n/character_encoding_spec.rb +7 -13
  69. data/spec/moxml/c14n/comments_pis_spec.rb +35 -8
  70. data/spec/moxml/c14n/subset_spec.rb +2 -12
  71. data/spec/moxml/c14n/w3c_examples_spec.rb +2 -5
  72. data/spec/moxml/doctype_spec.rb +7 -0
  73. data/spec/moxml/document_parse_diagnostics_spec.rb +2 -0
  74. data/spec/moxml/element_indent_spec.rb +34 -0
  75. data/spec/moxml/entity_spec.rb +2 -0
  76. data/spec/moxml/node_spec.rb +0 -3
  77. data/spec/moxml/plan_conformance_spec.rb +2 -0
  78. data/spec/moxml/processing_instruction_spec.rb +9 -0
  79. data/spec/moxml/reference_opal_spec.rb +29 -0
  80. data/spec/moxml/reference_spec.rb +162 -0
  81. data/spec/moxml/relax_ng_spec.rb +67 -0
  82. data/spec/moxml/sax_spec.rb +47 -74
  83. data/spec/moxml/text_spec.rb +2 -0
  84. data/spec/moxml/to_html_spec.rb +2 -0
  85. data/spec/moxml/xhtml_output_spec.rb +2 -0
  86. data/spec/moxml/xpath/axes_spec.rb +2 -2
  87. data/spec/moxml/xpath_capabilities_spec.rb +11 -38
  88. data/spec/moxml/xsd_spec.rb +38 -0
  89. data/spec/support/input_generator.rb +154 -0
  90. data/spec/support/input_taxonomy.rb +219 -0
  91. data/spec/support/model_coverage.rb +159 -0
  92. data/spec/support/xml_generator.rb +54 -0
  93. metadata +32 -2
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The model-coverage matrix (TODO.sota/01, TODO.sota/07): every face
4
+ # family of the processing model mapped to the normative section it
5
+ # cites, the pin that enforces it, and per-adapter dispositions
6
+ # (registered divergence or named loud error). One source of truth for
7
+ # the audit, the model-document pin lists, and the published coverage
8
+ # page.
9
+ module ModelCoverage
10
+ MODEL_COVERAGE_MATRIX = {
11
+ "document order and children listing" => {
12
+ section: "Document order and traversal",
13
+ pin: "spec/consistency/adapter_parity_spec.rb",
14
+ },
15
+ "name resolution" => {
16
+ section: "Names and namespaces",
17
+ pin: "spec/consistency/xpath_idioms_spec.rb",
18
+ },
19
+ "namespace resolution and bindings normalization" => {
20
+ section: "Names and namespaces",
21
+ pin: "spec/consistency/xpath_idioms_spec.rb",
22
+ },
23
+ "attribute access" => {
24
+ section: "Access semantics",
25
+ pin: "spec/moxml/attribute_resolver_spec.rb",
26
+ },
27
+ "text/content/raw_content" => {
28
+ section: "Access semantics",
29
+ pin: "spec/moxml/text_spec.rb",
30
+ },
31
+ "parsing modes and diagnostics" => {
32
+ section: "Parsing",
33
+ pin: "spec/moxml/document_parse_diagnostics_spec.rb",
34
+ },
35
+ "EOL normalization" => {
36
+ section: "Parsing",
37
+ pin: "spec/consistency/eol_normalization_spec.rb",
38
+ exempt: { oga: "D-02", ox: "D-03" },
39
+ },
40
+ "entity modes" => {
41
+ section: "Parsing",
42
+ pin: "spec/moxml/entity_spec.rb",
43
+ },
44
+ "XPath evaluation and declared idioms" => {
45
+ section: "XPath evaluation",
46
+ pin: "spec/consistency/xpath_idioms_spec.rb",
47
+ },
48
+ "serialization shapes (xml/html/xhtml)" => {
49
+ section: "Serialization",
50
+ pin: "spec/moxml/xhtml_output_spec.rb",
51
+ },
52
+ "indentation knobs" => {
53
+ section: "Serialization",
54
+ pin: "spec/moxml/to_html_spec.rb",
55
+ exempt: { oga: "D-09", ox: "D-09", headed_ox: "D-09",
56
+ libxml: "D-09", leptris: "D-09" },
57
+ },
58
+ "canonicalization" => {
59
+ section: "Canonicalization",
60
+ pin: "spec/moxml/c14n/adapter_delegation_spec.rb",
61
+ exempt: { ox: "D-05", headed_ox: "D-05" },
62
+ },
63
+ "XSLT" => {
64
+ section: "XSLT",
65
+ pin: "spec/consistency/xslt_spec.rb",
66
+ loud: { oga: "Moxml::NotImplementedError",
67
+ ox: "Moxml::NotImplementedError",
68
+ headed_ox: "Moxml::NotImplementedError",
69
+ rexml: "Moxml::NotImplementedError",
70
+ libxml: "Moxml::NotImplementedError" },
71
+ },
72
+ "SAX" => {
73
+ section: "SAX",
74
+ pin: "spec/moxml/sax_spec.rb",
75
+ },
76
+ "materialization" => {
77
+ section: "Materialization",
78
+ pin: "spec/moxml/plan_conformance_spec.rb",
79
+ },
80
+ "loud capability contracts" => {
81
+ section: "Errors and loud degradation",
82
+ pin: "spec/consistency/loud_degradation_spec.rb",
83
+ },
84
+ }.freeze
85
+
86
+ # Normative sections that are not face families (meta/apparatus).
87
+ MODEL_COVERAGE_NON_FACE = [
88
+ "Status and precedence",
89
+ "Mission and invariant",
90
+ "Object model",
91
+ "Performance: a declared, non-semantic channel",
92
+ ].freeze
93
+
94
+ MODEL_COVERAGE_ADAPTERS = %i[nokogiri oga rexml ox headed_ox libxml leptris].freeze
95
+
96
+ module_function
97
+
98
+ def families
99
+ MODEL_COVERAGE_MATRIX.keys
100
+ end
101
+
102
+ def sections
103
+ MODEL_COVERAGE_MATRIX.values.map { |cell| cell[:section] }.uniq
104
+ end
105
+
106
+ def pins_for(section)
107
+ MODEL_COVERAGE_MATRIX.values.select { |cell| cell[:section] == section }
108
+ .filter_map { |cell| cell[:pin] }.uniq.sort
109
+ end
110
+
111
+ def disposition(family, adapter)
112
+ cell = MODEL_COVERAGE_MATRIX.fetch(family)
113
+ if (id = (cell[:exempt] || {})[adapter])
114
+ [:specd, id]
115
+ elsif (error = (cell[:loud] || {})[adapter])
116
+ [:loud, error]
117
+ else
118
+ [:equivalent, nil]
119
+ end
120
+ end
121
+
122
+ def cell_text(family, adapter)
123
+ kind, detail = disposition(family, adapter)
124
+ case kind
125
+ when :specd then detail
126
+ when :loud then "loud (#{detail.split('::').last})"
127
+ else "equivalent"
128
+ end
129
+ end
130
+
131
+ # The published page block, deterministic (no clock, no engine
132
+ # versions): the page is a view of the committed matrix and register,
133
+ # so a data change without regeneration fails CI.
134
+ def render_page_block
135
+ lines = []
136
+ lines << "Generated by `bundle exec rake docs:coverage` from the " \
137
+ "coverage matrix and the divergence register. Do not edit " \
138
+ "by hand: `spec/consistency/published_docs_spec.rb` fails " \
139
+ "when this block is stale."
140
+ lines << ""
141
+ lines << %([cols="4#{',1' * MODEL_COVERAGE_ADAPTERS.size}",options="header"])
142
+ lines << "|==="
143
+ lines << "| Face family | " \
144
+ "#{MODEL_COVERAGE_ADAPTERS.map { |adapter| adapter.to_s.tr('_', ' ') }.join(' | ')}"
145
+ families.each do |family|
146
+ lines << "| #{family} | " \
147
+ "#{MODEL_COVERAGE_ADAPTERS.map { |adapter| cell_text(family, adapter) }.join(' | ')}"
148
+ end
149
+ lines << "|==="
150
+ lines << ""
151
+ lines << "*equivalent* — all adapters answer the same observable " \
152
+ "result. *loud (...)* — the adapter raises the named error " \
153
+ "for that face. *D-NN* — a registered divergence in " \
154
+ "link:divergences.html[the register], with its rationale. " \
155
+ "Every cell cites a pin; see the processing model's " \
156
+ "`Pins::` line for the enforcing specs."
157
+ lines.join("\n")
158
+ end
159
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Seeded XML generator (TODO.sota/02): composes random
4
+ # taxonomy-class documents — elements, text, attributes, namespaces,
5
+ # comments, PIs, CDATA — deterministic per seed. The metamorphic
6
+ # suite runs its properties over generated docs; a failing seed is a
7
+ # reproducible regression.
8
+ module XmlGenerator
9
+ ELEMENT_NAMES = %w[r a b node item entry rec child leaf].freeze
10
+ ATTR_NAMES = %w[id name kind type ref value flag].freeze
11
+ TEXT_POOL = [
12
+ "plain text", "text with spaces ", "entities &amp; &lt;tags&gt;",
13
+ "unicode déjà vu", "numbers 12345", "", " ", "tail "
14
+ ].freeze
15
+ PI_TARGETS = %w[render probe].freeze
16
+
17
+ module_function
18
+
19
+ # Deterministic RNG: Ruby's Mersenne with an explicit seed.
20
+ def generate(seed)
21
+ rng = Random.new(seed)
22
+ depth = rng.rand(1..5)
23
+ body = compose(rng, depth)
24
+ %(<root#{attrs(rng, depth)}>#{body}</root>)
25
+ end
26
+
27
+ def compose(rng, depth)
28
+ parts = []
29
+ rng.rand(1..4).times do
30
+ case rng.rand(depth.zero? ? 5 : 10)
31
+ when 0..4 then parts << element(rng, depth)
32
+ when 5 then parts << TEXT_POOL.sample(random: rng)
33
+ when 6 then parts << "<!-- #{format('%04x', rng.rand(65_536))} -->"
34
+ when 7 then parts << "<?#{PI_TARGETS.sample(random: rng)} d#{format('%02x', rng.rand(256))}?>"
35
+ when 8 then parts << "<![CDATA[raw #{format('%04x', rng.rand(65_536))} <stuff>]]>"
36
+ when 9 then parts << format("<e n=\"%d\"/>", rng.rand(100))
37
+ end
38
+ end
39
+ parts.join
40
+ end
41
+
42
+ def element(rng, depth)
43
+ name = ELEMENT_NAMES.sample(random: rng)
44
+ ns = rng.rand(4).zero? ? %( xmlns="urn:g#{rng.rand(3)}") : ""
45
+ body = depth.positive? ? compose(rng, depth - 1) : TEXT_POOL.sample(random: rng)
46
+ "<#{name}#{ns}#{attrs(rng, depth)}>#{body}</#{name}>"
47
+ end
48
+
49
+ def attrs(rng, _depth)
50
+ (0...rng.rand(0..3)).map do |i|
51
+ %( #{ATTR_NAMES.sample(random: rng)}#{i}="v#{rng.rand(100)}")
52
+ end.join
53
+ end
54
+ 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.148
4
+ version: 0.5.150
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-10-20 00:00:00.000000000 Z
11
+ date: 2026-10-21 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
@@ -24,7 +24,10 @@ files:
24
24
  - ".github/workflows/dependent-repos.json"
25
25
  - ".github/workflows/dependent-tests.yml"
26
26
  - ".github/workflows/docs.yml"
27
+ - ".github/workflows/nightly-fuzz.yml"
27
28
  - ".github/workflows/opal.yml"
29
+ - ".github/workflows/performance-release.yml"
30
+ - ".github/workflows/performance.yml"
28
31
  - ".github/workflows/rake.yml"
29
32
  - ".github/workflows/release.yml"
30
33
  - ".github/workflows/round-trip.yml"
@@ -39,12 +42,16 @@ files:
39
42
  - LICENSE.md
40
43
  - README.adoc
41
44
  - Rakefile
45
+ - benchmark/README.md
42
46
  - benchmark/pipeline_bench.rb
43
47
  - benchmark/plan_bench.rb
44
48
  - benchmark/sax_bench.rb
49
+ - benchmark/scoreboard.json
50
+ - benchmark/scoreboard.rb
45
51
  - benchmarks/.gitignore
46
52
  - benchmarks/generate_report.rb
47
53
  - bin/console
54
+ - bin/generate-model-coverage
48
55
  - bin/setup
49
56
  - data/w3c_entities.json
50
57
  - docs/ENTITY_SUPPORT_FOR_LUTAML_MODEL.md
@@ -74,15 +81,18 @@ files:
74
81
  - docs/_pages/configuration.adoc
75
82
  - docs/_pages/conversion-apis.adoc
76
83
  - docs/_pages/divergences.adoc
84
+ - docs/_pages/ecosystem.adoc
77
85
  - docs/_pages/error-handling.adoc
78
86
  - docs/_pages/headed-ox-limitations.adoc
79
87
  - docs/_pages/headed-ox.adoc
80
88
  - docs/_pages/index.adoc
81
89
  - docs/_pages/installation.adoc
90
+ - docs/_pages/model-coverage.adoc
82
91
  - docs/_pages/node-api-reference.adoc
83
92
  - docs/_pages/performance.adoc
84
93
  - docs/_pages/quick-start.adoc
85
94
  - docs/_pages/thread-safety.adoc
95
+ - docs/_pages/why-moxml.adoc
86
96
  - docs/_references/document-api.adoc
87
97
  - docs/_references/index.adoc
88
98
  - docs/_references/processing-model.adoc
@@ -227,6 +237,11 @@ files:
227
237
  - lib/moxml/node_set.rb
228
238
  - lib/moxml/plan.rb
229
239
  - lib/moxml/processing_instruction.rb
240
+ - lib/moxml/reference.rb
241
+ - lib/moxml/reference/normalizer.rb
242
+ - lib/moxml/reference/parser.rb
243
+ - lib/moxml/reference/writer.rb
244
+ - lib/moxml/relaxng.rb
230
245
  - lib/moxml/sax.rb
231
246
  - lib/moxml/sax/block_handler.rb
232
247
  - lib/moxml/sax/element_handler.rb
@@ -297,6 +312,7 @@ files:
297
312
  - lib/moxml/xpath/engine.rb
298
313
  - lib/moxml/xpath/errors.rb
299
314
  - lib/moxml/xpath/lexer.rb
315
+ - lib/moxml/xpath/ordering.rb
300
316
  - lib/moxml/xpath/parser.rb
301
317
  - lib/moxml/xpath/ruby/generator.rb
302
318
  - lib/moxml/xpath/ruby/node.rb
@@ -312,12 +328,18 @@ files:
312
328
  - sig/moxml.rbs
313
329
  - spec/consistency/README.md
314
330
  - spec/consistency/adapter_parity_spec.rb
331
+ - spec/consistency/citation_hygiene_spec.rb
332
+ - spec/consistency/differential_taxonomy_spec.rb
315
333
  - spec/consistency/divergence_register_spec.rb
316
334
  - spec/consistency/document_text_spec.rb
317
335
  - spec/consistency/eol_normalization_spec.rb
318
336
  - spec/consistency/html_doctype_spec.rb
319
337
  - spec/consistency/loud_degradation_spec.rb
338
+ - spec/consistency/metamorphic_properties_spec.rb
339
+ - spec/consistency/metamorphic_spec.rb
320
340
  - spec/consistency/model_coverage_audit_spec.rb
341
+ - spec/consistency/published_docs_spec.rb
342
+ - spec/consistency/reference_differential_spec.rb
321
343
  - spec/consistency/round_trip_spec.rb
322
344
  - spec/consistency/spec_constant_uniqueness_spec.rb
323
345
  - spec/consistency/xpath_idioms_spec.rb
@@ -516,6 +538,7 @@ files:
516
538
  - spec/moxml/document_spec.rb
517
539
  - spec/moxml/element_add_element_spec.rb
518
540
  - spec/moxml/element_attribute_pairs_spec.rb
541
+ - spec/moxml/element_indent_spec.rb
519
542
  - spec/moxml/element_spec.rb
520
543
  - spec/moxml/entity_preservation_spec.rb
521
544
  - spec/moxml/entity_reference_spec.rb
@@ -548,6 +571,9 @@ files:
548
571
  - spec/moxml/processing_instruction_spec.rb
549
572
  - spec/moxml/readonly_parse_spec.rb
550
573
  - spec/moxml/recover_mode_spec.rb
574
+ - spec/moxml/reference_opal_spec.rb
575
+ - spec/moxml/reference_spec.rb
576
+ - spec/moxml/relax_ng_spec.rb
551
577
  - spec/moxml/sax/namespace_splitter_spec.rb
552
578
  - spec/moxml/sax_entity_parity_spec.rb
553
579
  - spec/moxml/sax_spec.rb
@@ -609,8 +635,12 @@ files:
609
635
  - spec/performance/xpath_benchmark_spec.rb
610
636
  - spec/spec_helper.rb
611
637
  - spec/support/allocation_helper.rb
638
+ - spec/support/input_generator.rb
639
+ - spec/support/input_taxonomy.rb
640
+ - spec/support/model_coverage.rb
612
641
  - spec/support/opal.rb
613
642
  - spec/support/w3c_namespace_helpers.rb
643
+ - spec/support/xml_generator.rb
614
644
  - spec/support/xml_matchers.rb
615
645
  - spec/unit/rexml_isolated_test.rb
616
646
  homepage: https://github.com/lutaml/moxml