sts 0.6.7 → 0.6.9

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: 53e7ba614487ea4d658f8292c403c6811255a85affd65ef9f98976ccc32aa426
4
- data.tar.gz: a750e10d49eddc0664746e85114c7db000638b0a3e3addc4b352d179bb21684b
3
+ metadata.gz: 55257a4c0bd11d4374ea655ffdef2d2a51c1e2fe8761cabbe450188065b85cb6
4
+ data.tar.gz: afe4c91a2e1b739eeffee4d044e8ea03b28774d43146aafdbd2d744d7577880a
5
5
  SHA512:
6
- metadata.gz: a03cfc08c64cec197ee4a7a88a9ec41f46b3e94a80ea916092444be3419ec8c5aff06af3888094937be86cd7bbd2ed97b1663a688c16ba46650c0c61eed3cd60
7
- data.tar.gz: 9ff6274690f18e27d2528497ffa5f4d0b5f3304e2636d276af5503b17318d6c86a090f3eeb583c0e889d26104878d8df9baed1b0d81ea227ed8b8be44e30573c
6
+ metadata.gz: be6961ce1a6581c1fa6d7a51cb80253a99e01d53fabb31cb3d4feff43f8d87f7a2b283b3fbb8aa07ad31a91e4ac0a634e1bbbcbbf5dce733f45ad93bc77fdfc8
7
+ data.tar.gz: 9c476be12a1c7d51c9552892c2ad0bd677f16677e10587865d5a127ff20cf1be67b9e241a17e90155845ba704b58b404317cd1292bd138ddd00a182b875cb01e
data/.rubocop_todo.yml CHANGED
@@ -24,6 +24,7 @@ Layout/LineLength:
24
24
  - 'lib/sts/tbx_iso_tml/lang_set.rb'
25
25
  - 'lib/sts/tbx_iso_tml/term_type.rb'
26
26
  - 'spec/elements/new_elements_spec.rb'
27
+ - 'spec/iso_sts/schema_validation_spec.rb'
27
28
  - 'spec/round_trip/reference_docs_spec.rb'
28
29
  - 'spec/spec_helper.rb'
29
30
 
@@ -73,6 +74,7 @@ RSpec/DescribeClass:
73
74
  - 'spec/fn_namespace_spec.rb'
74
75
  - 'spec/mathml_version_spec.rb'
75
76
  - 'spec/round_trip/reference_docs_spec.rb'
77
+ - 'spec/iso_sts/schema_validation_spec.rb'
76
78
 
77
79
  # Offense count: 1
78
80
  # This cop supports safe autocorrection (--autocorrect).
@@ -124,3 +126,4 @@ RSpec/SpecFilePathFormat:
124
126
  - 'spec/sts_table_spec.rb'
125
127
  - 'spec/iso_sts/iso_sts_spec.rb'
126
128
  - 'spec/iso_sts/iso_sts_element_spec.rb'
129
+ - 'spec/iso_sts/schema_validation_spec.rb'
data/CLAUDE.md CHANGED
@@ -1,58 +1,84 @@
1
1
  # CLAUDE.md
2
2
 
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
3
+ This file provides guidance to Claude Code (claude.ai/code) for working with code in this repository.
4
4
 
5
5
  ## Build and Test Commands
6
6
 
7
7
  ```bash
8
- # Run tests
8
+ # Run all tests + rubocop (default task)
9
+ bundle exec rake
10
+
11
+ # Run tests only
9
12
  bundle exec rspec
10
13
 
11
- # Run tests with specific file
12
- bundle exec rspec spec/sts_spec.rb
14
+ # Run a specific spec file
15
+ bundle exec rspec spec/iso_sts/iso_sts_element_spec.rb
13
16
 
14
- # Run RuboCop linting
17
+ # Run rubocop
15
18
  bundle exec rubocop
16
19
 
17
- # Run both (default task)
18
- bundle exec rake
20
+ # Auto-fix linting offenses
21
+ bundle exec rubocop -a
19
22
  ```
20
23
 
21
24
  ## Architecture
22
25
 
23
- This is a Ruby gem for parsing NISO STS (National Information Standards Organization - Science and Technical Standards) XML documents. It uses `lutaml-model` for XML serialization/deserialization.
26
+ sts-ruby is a Ruby gem for parsing and serialising NISO STS, ISOSTS, and
27
+ TBX-ISO-TML XML documents. It uses `lutaml-model` for declarative
28
+ serialisation.
24
29
 
25
- ### Namespace Structure
30
+ ### Namespace structure
26
31
 
27
32
  ```
28
33
  Sts
29
- ├── NisoSts # NISO STS elements (lib/sts/niso_sts/)
30
- ├── MmlContent # MathML content elements (autoloaded)
31
- │ └── Xi, Ali # Module elements
32
- ├── TbxIsoTml # TBX ISO TML elements (lib/sts/tbx_iso_tml/)
33
- ├── Mathml # MathML namespace wrapper
34
- └── Namespaces # XML namespace definitions
34
+ ├── IsoSts # ISOSTS v1.1 (frozen legacy, 2013 DTD)
35
+ ├── NisoSts # NISO STS (evolving: 1.0, 1.2)
36
+ ├── TbxIsoTml # TBX-ISO-TML (ISO 30042, shared)
37
+ ├── Namespaces # XML namespace class declarations (TbxNamespace)
38
+ ├── Profiles # ISO/IEC document profile validator
39
+ └── VERSION
35
40
  ```
36
41
 
37
- ### Key Implementation Patterns
42
+ ### Architectural principle: namespace independence
43
+
44
+ ISOSTS and NISO STS are independent schemas that genuinely diverge.
45
+ Each `Sts::<Namespace>::<Class>` is modelled from its own schema source
46
+ (`reference-docs/isosts-v1/xsd/ISOSTS.xsd` for IsoSts,
47
+ `reference-docs/NISO-STS-extended-1-MathML3-XSD/` for NisoSts). NEVER:
48
+
49
+ - Alias `IsoSts::<X> = NisoSts::<X>` (couples the namespaces)
50
+ - Create a shared `Sts::Base::<X>` that both inherit from
51
+ - Reuse NisoSts types inside IsoSts or vice versa
52
+
53
+ TBX is shared (used by both IsoSts and NisoSts hosts), so cross-references
54
+ to `TbxIsoTml::*` are permitted — but each TbxIsoTml class must be a
55
+ true TBX-ISO-TML element, not a JATS/NISO STS element misplaced.
56
+
57
+ See `TODO.roadmap/00-overview.md` for the prioritised roadmap of remaining
58
+ work.
59
+
60
+ ### MathML host binding
61
+
62
+ ISOSTS imports `ncbi-mathml2/mathml2.xsd` (MathML 2). NISO STS uses
63
+ MathML 3. TBX-ISO-TML is hosted under either. Bind per host:
38
64
 
39
- **Element Classes** (in `lib/sts/niso_sts/`):
40
- - Inherit from `Lutaml::Model::Serializable`
41
- - Define attributes and XML mapping in `xml do ... end` block
42
- - Use `map_element` to map child elements, `map_content` for text content
43
- - Use `mixed_content` for elements that contain both text and child elements
65
+ - `IsoSts::*` math attributes → `Mml::V2::Math`
66
+ - `TbxIsoTml::*` math attributes → `Mml::V2::Math` (TBX-in-ISOSTS only)
67
+ - `NisoSts::*` math attributes `Mml::V3::Math`
68
+
69
+ ### Element class pattern
44
70
 
45
- **Example element structure:**
46
71
  ```ruby
47
72
  module Sts
48
- module NisoSts
73
+ module IsoSts
49
74
  class SomeElement < Lutaml::Model::Serializable
50
75
  attribute :id, :string
51
- attribute :content, :string
52
- attribute :child, ::Sts::NisoSts::ChildElement
76
+ attribute :content, :string, collection: true
77
+ attribute :child, ::Sts::IsoSts::ChildElement, collection: true
53
78
 
54
79
  xml do
55
80
  element "some-element"
81
+ ordered # preserve child order on serialise
56
82
  map_attribute "id", to: :id
57
83
  map_content to: :content
58
84
  map_element "child", to: :child
@@ -62,11 +88,55 @@ module Sts
62
88
  end
63
89
  ```
64
90
 
65
- **Autoload Pattern**: Elements are autoloaded via `lib/sts/niso_sts.rb`. When adding new elements, add autoloads in alphabetical order.
91
+ ### Autoload convention
92
+
93
+ `lib/sts.rb` autoloads top-level namespaces. `lib/sts/<namespace>.rb`
94
+ autoloads every class in that namespace, organised by category with
95
+ leading comments and alphabetical order within each group.
96
+
97
+ External gems are eager-required at the top of `lib/sts.rb`
98
+ (`require "lutaml/model"`, `require "mml"`). Internal code never uses
99
+ `require_relative` or `require` with internal paths — autoload only.
100
+ Enforced by `spec/anti_patterns_spec.rb`.
101
+
102
+ ### Anti-patterns (forbidden; enforced by spec)
103
+
104
+ `spec/anti_patterns_spec.rb` runs 9 per-file checks on every `lib/` file:
105
+
106
+ - `method_missing`, `respond_to_missing?` — forbidden (hides interfaces)
107
+ - `Object.const_get` — forbidden (runtime string lookup)
108
+ - `.send(` — forbidden (bypasses access control)
109
+ - `instance_variable_set` / `instance_variable_get` — forbidden (breaks encapsulation)
110
+ - `respond_to?` type-checks — forbidden (use `is_a?` or redesign so the check isn't needed)
111
+ - Hand-rolled serialization methods on `Serializable` subclasses:
112
+ `to_h`, `to_hash`, `from_h`, `from_hash`, `to_json`, `from_json`,
113
+ `serialize`, `deserialize`, `to_xml`, `from_xml` — forbidden
114
+ (use `attribute` + `mapping`; framework-generated serialisation is correct)
115
+ - `require_relative` in lib/ — forbidden (use autoload)
116
+ - `require` with internal library path — forbidden (use autoload;
117
+ external gems like `lutaml/model` are allowlisted)
118
+
119
+ ### Schema authority
120
+
121
+ For any new IsoSts element, generate the attribute list from
122
+ `reference-docs/isosts-v1/xsd/ISOSTS.xsd` directly. Don't copy from
123
+ NisoSts — the schemas disagree on most elements. Attribute-list
124
+ specifications ("X models its configured attribute set") are the
125
+ project's defence against drift, since round-tripping alone cannot prove
126
+ schema conformance.
127
+
128
+ ### Spec patterns
66
129
 
67
- **Bold/Italic Elements**: These use `::Sts::TbxIsoTml::Bold` and `::Sts::TbxIsoTml::Italic` types (not `:string`), enabling proper round-tripping of nested markup.
130
+ - **Attribute-set assertions** `expect(Foo.attributes.keys).to match_array(%i[id content_type ...])`
131
+ - **Child-type assertions** — `expect(Bar.attributes[:foo].type).to eq(Baz)`
132
+ - **Round-trip tests** — `expect(Foo.to_xml(Foo.from_xml(xml))).to be_xml_equivalent_to(xml)`
133
+ - **Schema-validation tests** — `spec/schema_validation_spec.rb` validates
134
+ IsoSts output against ISOSTS.xsd directly via Nokogiri::XML::Schema
68
135
 
69
- ### Reference Data
136
+ ### Reference data
70
137
 
71
- - XSD schema: `reference-docs/NISO-STS-extended-1-MathML3-XSD/`
138
+ - ISOSTS XSD: `reference-docs/isosts-v1/xsd/ISOSTS.xsd`
139
+ - NISO STS XSD: `reference-docs/NISO-STS-extended-1-MathML3-XSD/`
140
+ - TBX schema (under ISOSTS): `reference-docs/isosts-v1/xsd/tbx.xsd`
72
141
  - Test fixtures: `spec/fixtures/`
142
+ - TODO roadmap: `TODO.roadmap/`
data/README.adoc CHANGED
@@ -140,23 +140,26 @@ sts.class.name # => "Sts::IsoSts::Standard"
140
140
 
141
141
  ==== ISOSTS MathML 2
142
142
 
143
- ISOSTS uses MathML 2 (not MathML 3+ like NISO STS). A custom Ruby implementation is provided in `Sts::IsoSts::Mathml2::*`:
143
+ ISOSTS uses MathML 2 (not MathML 3 like NISO STS). All MathML is provided
144
+ by the mml gem, bound per host:
145
+
146
+ * `IsoSts::*` math attributes → `Mml::V2::Math`
147
+ * `TbxIsoTml::*` math attributes → `Mml::V2::Math` (TBX-in-ISOSTS only)
148
+ * `NisoSts::*` math attributes → `Mml::V3::Math`
144
149
 
145
150
  [source,ruby]
146
151
  ----
147
- # Access MathML 2 content
148
152
  disp_formula = sts.body.sec.first.disp_formula
149
- math = disp_formula.math # => Sts::IsoSts::Mathml2::Math
150
-
151
- # MathML 2 elements
152
- math.id # => "mml_1"
153
- math.display # => "block" or "inline"
153
+ math = disp_formula.math # => Mml::V2::Math
154
154
 
155
- # Serialized as mml:math
156
- math.to_xml # => <mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" ...>
155
+ # Round-trip preserves mml: prefix
156
+ disp_formula.to_xml # => <disp-formula><mml:math ...>...</mml:math></disp-formula>
157
157
  ----
158
158
 
159
- Available MathML 2 elements: `Math`, `Mrow`, `Mi`, `Mn`, `Mo`, `Mtext`, `Mspace`, `Msub`, `Msup`, `Msubsup`, `Mfrac`, `Msqrt`, `Mroot`, `Mstyle`, `Menclose`, `Mpadded`, `Mphantom`, `Mtable`, `Mtr`, `Mtd`, `Mlabeledtr`, `Mfenced`, `Semantics`, `Annotation`, `AnnotationXml`
159
+ MathML 2 and 3 share the same XML namespace (`http://www.w3.org/1998/Math/MathML`),
160
+ so `Mml::Namespace` (the mml gem's top-level namespace class) is used
161
+ directly in both `IsoSts::Standard#namespace_scope` and
162
+ `NisoSts::Standard#namespace_scope`.
160
163
 
161
164
  ==== ISOSTS TBX Terminology
162
165
 
@@ -191,6 +194,42 @@ sts = Sts::NisoSts::Standard.from_xml(xml_with_tbx)
191
194
  sts = Sts::IsoSts::Standard.from_xml(xml_with_tbx)
192
195
  ----
193
196
 
197
+ == Architecture principles
198
+
199
+ === Namespace independence
200
+
201
+ `IsoSts`, `NisoSts`, and `TbxIsoTml` are independent schemas that
202
+ genuinely diverge. Each `Sts::<Namespace>::<Class>` is modelled from its
203
+ own schema source — never aliased across namespaces, never sharing base
204
+ classes. The schemas disagree on most elements (e.g., `IsoSts::Fig` has
205
+ `title`/`alternatives` that `NisoSts::Figure` lacks), so sharing types
206
+ would fight the schemas and violate the Open/Closed principle.
207
+
208
+ === Anti-pattern enforcement
209
+
210
+ `spec/anti_patterns_spec.rb` runs 9 per-file checks across `lib/` to
211
+ forbid: `method_missing`, `respond_to_missing?`, `Object.const_get`,
212
+ `.send(`, `instance_variable_set`/`get`, `respond_to?` type-checks,
213
+ hand-rolled serialization methods on `Serializable` subclasses
214
+ (`to_h`, `to_xml`, `from_xml`, etc.), `require_relative`, and
215
+ internal `require`. See `CLAUDE.md` for the rationale.
216
+
217
+ === Schema validation
218
+
219
+ `spec/schema_validation_spec.rb` validates IsoSts output against the
220
+ canonical `reference-docs/isosts-v1/xsd/ISOSTS.xsd` via
221
+ `Nokogiri::XML::Schema`. Round-tripping alone cannot prove schema
222
+ conformance (a model that invents or drops an attribute still
223
+ round-trips symmetrically); the XSD is the only authoritative check.
224
+
225
+ === Autoload convention
226
+
227
+ `lib/sts.rb` autoloads top-level namespaces. Each namespace's
228
+ `lib/sts/<namespace>.rb` autoloads every class in alphabetical order
229
+ within category groups. External gems (`lutaml/model`, `mml`) are
230
+ eager-required at the top of `lib/sts.rb`; internal code uses autoload
231
+ only — no `require_relative`, no `require "sts/..."`.
232
+
194
233
  == Credits
195
234
 
196
235
  This gem is developed, maintained and funded by
@@ -23,32 +23,37 @@ noted.
23
23
 
24
24
  | Track | Subject | Items |
25
25
  |---|---|---|
26
- | A | lutaml-model upstream fixes (file BUGREPORTs, propose patches) | 01, 02 |
27
- | B | Issue #40 namespace coupling completion | 03, 04 |
28
- | C | Architectural improvements (DRY, versioning, audit) | 05, 06, 07, 08 |
26
+ | A | lutaml-model upstream analysis (filed as robustness suggestions) | 02 |
27
+ | B | Issue #40 namespace coupling completion | 01 (done), 03 (done), 04 |
28
+ | C | Architectural improvements (DRY, versioning, audit) | 05, 07, 08 |
29
29
  | D | Quality, specs, and coverage | 09, 10, 11 |
30
30
 
31
31
  ## Priority order
32
32
 
33
33
  The priority is "highest leverage per unit of risk" first:
34
34
 
35
- 1. **B.03** (child-bearing roots): model `IsoSts::License`, `IsoSts::TermHead`,
36
- `IsoSts::CustomMetaGroup` closes 5 of 11 issue #40 refs in one PR. Low
37
- risk, schema-correct, no recursion.
38
- 2. **A.01, A.02** (lutaml-model BUGREPORTs): pure documentation, zero risk.
39
- Unblocks C.06 (MathmlNamespace deduplication).
40
- 3. **C.07** (TbxIsoTml misclassification audit): documents a deferred audit
35
+ 1. **B.01** (MathmlNamespace deduplication): DONE 2026-07-27. sts-ruby had
36
+ two Ruby classes for one XML namespace; deleted one, use `Mml::Namespace`
37
+ directly. Originally misdiagnosed as a lutaml-model bug — see
38
+ `01-mathml-namespace-deduplication.md` for the lesson.
39
+ 2. **B.03** (child-bearing roots): DONE 2026-07-27. Modelled License,
40
+ TermHead, CustomMetaGroup closures. Closed 5 of 11 issue #40 refs.
41
+ 3. **A.02** (lutaml-model ElementBuilder dispatch): filed as
42
+ `BUGREPORT.element-builder-dispatch-on-value-class.md` in lutaml-model.
43
+ Pure documentation; zero risk. **Reframed as a robustness suggestion,
44
+ not a bug** — sts-ruby's responsibility to use correct types was the
45
+ actual fix (PR #47 deleted duplicate Fn classes).
46
+ 4. **C.07** (TbxIsoTml misclassification audit): documents a deferred audit
41
47
  (Xref, TableWrap, etc.) — pattern is already proven by Fn/FnGroup and
42
48
  Math removals.
43
- 4. **C.05** (Content MathML unification): 148 parallel classes in
49
+ 5. **C.05** (Content MathML unification): 148 parallel classes in
44
50
  `lib/sts/niso_sts/mml_content/` — same DRY argument as Presentation
45
51
  MathML unification (commit 9e977a5).
46
- 5. **B.04** (recursive roots): the heavy lift. Each root pulls a ~78-element
52
+ 6. **B.04** (recursive roots): the heavy lift. Each root pulls a ~78-element
47
53
  mutually-recursive core. Requires per-element planning. Most architecturally
48
54
  significant.
49
- 6. **C.08** (register versioning): lets ISOSTS v1.1, NISO STS 1.0, NISO STS 1.2
55
+ 7. **C.08** (register versioning): lets ISOSTS v1.1, NISO STS 1.0, NISO STS 1.2
50
56
  coexist without class-name clashes.
51
- 7. **C.06** (MathmlNamespace deduplication): blocked on A.01.
52
57
  8. **D.09, D.10, D.11** (quality, coverage, docs): ongoing.
53
58
 
54
59
  ## Architectural principles (enforced on all new work)
@@ -0,0 +1,62 @@
1
+ # 01: MathmlNamespace deduplication (DONE)
2
+
3
+ **Status**: complete (2026-07-27).
4
+ **Originally tracked as**: `01-lutaml-model-namespace-scope-uri-matching.md`
5
+ (misdiagnosed as a lutaml-model bug) and `06-mathml-namespace-deduplication.md`
6
+ (blocked on the misdiagnosed upstream fix). Merged and completed here.
7
+
8
+ ## Original misdiagnosis
9
+
10
+ When sts-ruby unified Presentation MathML on the mml gem (commit 9e977a5),
11
+ the `mml:` prefix was dropped on serialization unless both
12
+ `Sts::Namespaces::MathmlNamespace` AND `Mml::Namespace` were listed in
13
+ `IsoSts::Standard#namespace_scope` / `NisoSts::Standard#namespace_scope`.
14
+
15
+ The initial diagnosis (filed as `BUGREPORT.namespace-scope-uri-matching.md`
16
+ in lutaml-model) blamed `namespace_scope` for matching by class identity
17
+ instead of URI. The proposed fix was to change lutaml-model's matching
18
+ semantics.
19
+
20
+ ## Actual root cause
21
+
22
+ **sts-ruby had two Ruby classes for one XML namespace.** A namespace IS
23
+ its URI (per Namespaces in XML 1.0). `Sts::Namespaces::MathmlNamespace`
24
+ and `Mml::Namespace` both declared:
25
+
26
+ ```ruby
27
+ uri "http://www.w3.org/1998/Math/MathML"
28
+ prefix_default "mml"
29
+ ```
30
+
31
+ They were the same namespace. The duplication was the smell; the
32
+ "workaround" of listing both was actually papering over the duplication.
33
+
34
+ The BUGREPORT was retracted. The fix is purely sts-ruby's responsibility.
35
+
36
+ ## Fix shipped (2026-07-27)
37
+
38
+ - Deleted `Sts::Namespaces::MathmlNamespace` from `lib/sts/namespaces.rb`.
39
+ - Replaced `::Sts::Namespaces::MathmlNamespace` with `::Mml::Namespace` in:
40
+ - `lib/sts/iso_sts/standard.rb`
41
+ - `lib/sts/niso_sts/standard.rb`
42
+ - `lib/sts/niso_sts/mml_content.rb` (the Content MathML module — still
43
+ scheduled for unification per TODO.roadmap/05)
44
+ - Added 4 regression specs asserting `MathmlNamespace` is undefined and
45
+ `Mml::Namespace` is used directly.
46
+
47
+ ## Verification
48
+
49
+ - 5153 examples, 0 failures.
50
+ - TBX fixture round-trip preserves `<mml:math>` prefix.
51
+ - NISO STS fixture round-trip preserves `<mml:math>` prefix.
52
+ - `grep -rn "MathmlNamespace" lib/` returns nothing.
53
+
54
+ ## Lesson
55
+
56
+ When you see a "framework limitation" that requires you to declare
57
+ something twice, the more likely explanation is that you have two
58
+ definitions of the same thing. Namespaces in particular are URI-identified;
59
+ two classes for one URI is a DRY violation, not a framework bug.
60
+
61
+ Memory updated: `mml-gem-integration-failure` no longer describes the
62
+ `namespace_scope` duplication as a "known smell" — it's resolved.
@@ -15,7 +15,7 @@ module Sts
15
15
  element "standard"
16
16
  ordered
17
17
  namespace_scope [
18
- ::Sts::Namespaces::MathmlNamespace,
18
+ ::Mml::Namespace,
19
19
  ::Mml::Namespace,
20
20
  ::Sts::Namespaces::TbxNamespace,
21
21
  ::Lutaml::Xml::W3c::XlinkNamespace,
@@ -2,11 +2,6 @@
2
2
 
3
3
  module Sts
4
4
  module Namespaces
5
- class MathmlNamespace < Lutaml::Xml::Namespace
6
- uri "http://www.w3.org/1998/Math/MathML"
7
- prefix_default "mml"
8
- end
9
-
10
5
  class TbxNamespace < Lutaml::Xml::Namespace
11
6
  uri "urn:iso:std:iso:30042:ed-1"
12
7
  uri_aliases "urn:iso:std:iso:30042:ed-2"
@@ -7,7 +7,7 @@ module Sts
7
7
  # Content MathML elements share the MathML namespace
8
8
  class Object < Lutaml::Model::Serializable
9
9
  xml do
10
- namespace ::Sts::Namespaces::MathmlNamespace
10
+ namespace ::Mml::Namespace
11
11
  end
12
12
  end
13
13
 
@@ -17,7 +17,7 @@ module Sts
17
17
  element "standard"
18
18
  ordered
19
19
  namespace_scope [
20
- ::Sts::Namespaces::MathmlNamespace,
20
+ ::Mml::Namespace,
21
21
  ::Mml::Namespace,
22
22
  ::Sts::Namespaces::TbxNamespace,
23
23
  ::Lutaml::Xml::W3c::XlinkNamespace,
data/lib/sts/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sts
4
- VERSION = "0.6.7"
4
+ VERSION = "0.6.9"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.7
4
+ version: 0.6.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose
@@ -107,12 +107,11 @@ files:
107
107
  - TODO.finalize/10-audit-other-duplicates.md
108
108
  - TODO.finalize/11-strengthen-anti-patterns-spec.md
109
109
  - TODO.roadmap/00-overview.md
110
- - TODO.roadmap/01-lutaml-model-namespace-scope-uri-matching.md
110
+ - TODO.roadmap/01-mathml-namespace-deduplication.md
111
111
  - TODO.roadmap/02-lutaml-model-element-builder-dispatch.md
112
112
  - TODO.roadmap/03-issue-40-child-bearing-roots.md
113
113
  - TODO.roadmap/04-issue-40-recursive-roots.md
114
114
  - TODO.roadmap/05-content-mathml-unification.md
115
- - TODO.roadmap/06-mathml-namespace-deduplication.md
116
115
  - TODO.roadmap/07-tbxisotml-misclassification-audit.md
117
116
  - TODO.roadmap/08-register-versioning.md
118
117
  - TODO.roadmap/09-test-coverage-gaps.md
@@ -1,111 +0,0 @@
1
- # A.01: lutaml-model `namespace_scope` URI-based matching
2
-
3
- **Status**: BUGREPORT drafted; sts-ruby fix blocked on upstream.
4
- **Repo**: `lutaml/lutaml-model`
5
- **Estimated effort**: small (lutaml-model: ~20 lines + spec; sts-ruby: ~5 lines once landed)
6
-
7
- ## Problem
8
-
9
- `namespace_scope` in `Lutaml::Model::Serializable.xml do … end` currently
10
- matches namespace classes by **identity** (`==`), not by URI. Two classes
11
- that declare the same URI/prefix are treated as different namespaces, so a
12
- parent that lists one cannot satisfy a child that declares the other.
13
-
14
- ## Real-world symptom in sts-ruby
15
-
16
- `Sts::Namespaces::MathmlNamespace` (lib/sts/namespaces.rb) and
17
- `Mml::Namespace` (the mml gem's top-level namespace class) both encode:
18
-
19
- ```ruby
20
- uri "http://www.w3.org/1998/Math/MathML"
21
- prefix_default "mml"
22
- ```
23
-
24
- They are different classes (different `object_id`s). When `Mml::V3::Math` is
25
- nested inside `Sts::NisoSts::Standard`, the parent's `namespace_scope` lists
26
- `MathmlNamespace`. The child declares `Mml::Namespace`. Identity comparison
27
- fails, the `mml:` prefix is dropped on serialization.
28
-
29
- The current workaround — listing both classes in `namespace_scope`:
30
-
31
- ```ruby
32
- namespace_scope [
33
- ::Sts::Namespaces::MathmlNamespace,
34
- ::Mml::Namespace,
35
- ::Sts::Namespaces::TbxNamespace,
36
- ::Lutaml::Xml::W3c::XlinkNamespace,
37
- ]
38
- ```
39
-
40
- — is a DRY violation. It documents the lutaml-model limitation rather than
41
- fixing it. See `lib/sts/iso_sts/standard.rb:18-19` and
42
- `lib/sts/niso_sts/standard.rb:20-21`.
43
-
44
- ## Proposed lutaml-model fix
45
-
46
- In `Lutaml::Xml::NamespaceScope` (or wherever the membership check lives),
47
- compare by URI instead of (or in addition to) class identity. The public
48
- API doesn't change; only the matching semantics do.
49
-
50
- ```ruby
51
- # pseudocode
52
- def includes?(namespace_class)
53
- namespaces.any? do |declared|
54
- declared.uri == namespace_class.uri
55
- end
56
- end
57
- ```
58
-
59
- ## Files
60
-
61
- - `BUGREPORT.namespace-scope-uri-matching.md` in
62
- `~/src/lutaml/lutaml-model/` (this track files it)
63
- - lutaml-model spec: `spec/lutaml/xml/namespace_scope_spec.rb` — assert that
64
- two classes with the same URI are equivalent for `namespace_scope`
65
- - sts-ruby: remove the duplicated `MathmlNamespace` entry from
66
- `IsoSts::Standard` and `NisoSts::Standard` once the upstream fix lands
67
-
68
- ## Verification
69
-
70
- - Reproduction case (currently failing in 0.8.18):
71
-
72
- ```ruby
73
- class A < Lutaml::Model::Serializable
74
- xml do
75
- namespace SomeNs # uri "urn:test", prefix "t"
76
- element "a"
77
- end
78
- end
79
- class B < Lutaml::Model::Serializable
80
- xml do
81
- namespace OtherNs # also uri "urn:test", prefix "t" — different class
82
- element "b"
83
- end
84
- end
85
- class Parent < Lutaml::Model::Serializable
86
- attribute :child, B
87
- xml do
88
- namespace_scope [SomeNs]
89
- map_element "child", to: :child
90
- end
91
- end
92
- # Currently: child's prefix is dropped on serialize.
93
- # After fix: child's prefix is preserved (URIs match).
94
- ```
95
-
96
- ## Why not fix in sts-ruby today
97
-
98
- Cannot: the duplication is the only way to make `Mml::V3::Math` and
99
- `Mml::V2::Math` serialize with the `mml:` prefix inside STS Standard
100
- elements. Removing `MathmlNamespace` without the upstream fix would
101
- silently drop the prefix on every IsoSts/NisoSts document with MathML
102
- content.
103
-
104
- Track C.06 (MathmlNamespace deduplication) is the sts-ruby cleanup; it
105
- blocks on this track.
106
-
107
- ## How to apply
108
-
109
- 1. File BUGREPORT in `~/src/lutaml/lutaml-model/BUGREPORT.namespace-scope-uri-matching.md`.
110
- 2. Optionally open PR upstream with the fix sketch above.
111
- 3. After upstream lands and sts-ruby bumps its lutaml-model dep, do C.06.
@@ -1,59 +0,0 @@
1
- # C.06: MathmlNamespace deduplication
2
-
3
- **Status**: blocked on A.01 (lutaml-model namespace_scope URI matching).
4
- **Estimated effort**: trivial (delete one class, two `namespace_scope`
5
- entries).
6
-
7
- ## Problem
8
-
9
- `Sts::Namespaces::MathmlNamespace` (lib/sts/namespaces.rb:5-8) and
10
- `Mml::Namespace` (mml gem's top-level namespace class) both encode:
11
-
12
- ```ruby
13
- uri "http://www.w3.org/1998/Math/MathML"
14
- prefix_default "mml"
15
- ```
16
-
17
- Two classes, same URI/prefix. The current `namespace_scope` workaround on
18
- `IsoSts::Standard` and `NisoSts::Standard` lists both:
19
-
20
- ```ruby
21
- namespace_scope [
22
- ::Sts::Namespaces::MathmlNamespace,
23
- ::Mml::Namespace,
24
- ::Sts::Namespaces::TbxNamespace,
25
- ::Lutaml::Xml::W3c::XlinkNamespace,
26
- ]
27
- ```
28
-
29
- This is the documented smell noted in memory `mml-gem-integration-failure`
30
- ("namespace_scope duplication is a known smell"). It exists because
31
- lutaml-model's `namespace_scope` matches by class identity, not by URI.
32
-
33
- ## Plan
34
-
35
- Once A.01 lands upstream and sts-ruby has bumped its lutaml-model dep:
36
-
37
- 1. Delete `Sts::Namespaces::MathmlNamespace` from `lib/sts/namespaces.rb`.
38
- 2. Replace both `namespace_scope` entries with `::Mml::Namespace` only.
39
- 3. Audit any other references to `MathmlNamespace` (likely only
40
- `lib/sts/niso_sts/mml_content.rb:10` — but that whole module is
41
- being deleted by C.05).
42
-
43
- ## Verification
44
-
45
- - `grep -rn "MathmlNamespace" lib/` returns nothing
46
- - TBX round-trip fixtures still preserve `<mml:math>` prefix
47
- - NISO STS fixtures still preserve `<mml:math>` prefix
48
- - IsoSts fixtures (V2) still preserve `<mml:math>` prefix
49
-
50
- ## How to apply
51
-
52
- - Coordinate with A.01 — file the BUGREPORT first, then either propose the
53
- upstream fix or wait for it
54
- - When the upstream fix is in a released lutaml-model version, bump
55
- sts.gemspec and ship this cleanup as a follow-up PR
56
-
57
- See also: TODO.sts-refactor/03-namespace-coupling.md "MathML wrapper"
58
- discussion (now historical — the wrapper itself was deleted in 9e977a5,
59
- but the namespace duplication remains).