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 +4 -4
- data/.rubocop_todo.yml +3 -0
- data/CLAUDE.md +99 -29
- data/README.adoc +49 -10
- data/TODO.roadmap/00-overview.md +18 -13
- data/TODO.roadmap/01-mathml-namespace-deduplication.md +62 -0
- data/lib/sts/iso_sts/standard.rb +1 -1
- data/lib/sts/namespaces.rb +0 -5
- data/lib/sts/niso_sts/mml_content.rb +1 -1
- data/lib/sts/niso_sts/standard.rb +1 -1
- data/lib/sts/version.rb +1 -1
- metadata +2 -3
- data/TODO.roadmap/01-lutaml-model-namespace-scope-uri-matching.md +0 -111
- data/TODO.roadmap/06-mathml-namespace-deduplication.md +0 -59
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 55257a4c0bd11d4374ea655ffdef2d2a51c1e2fe8761cabbe450188065b85cb6
|
|
4
|
+
data.tar.gz: afe4c91a2e1b739eeffee4d044e8ea03b28774d43146aafdbd2d744d7577880a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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)
|
|
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
|
|
12
|
-
bundle exec rspec spec/
|
|
14
|
+
# Run a specific spec file
|
|
15
|
+
bundle exec rspec spec/iso_sts/iso_sts_element_spec.rb
|
|
13
16
|
|
|
14
|
-
# Run
|
|
17
|
+
# Run rubocop
|
|
15
18
|
bundle exec rubocop
|
|
16
19
|
|
|
17
|
-
#
|
|
18
|
-
bundle exec
|
|
20
|
+
# Auto-fix linting offenses
|
|
21
|
+
bundle exec rubocop -a
|
|
19
22
|
```
|
|
20
23
|
|
|
21
24
|
## Architecture
|
|
22
25
|
|
|
23
|
-
|
|
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
|
|
30
|
+
### Namespace structure
|
|
26
31
|
|
|
27
32
|
```
|
|
28
33
|
Sts
|
|
29
|
-
├──
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
├──
|
|
33
|
-
├──
|
|
34
|
-
└──
|
|
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
|
-
###
|
|
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
|
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
|
73
|
+
module IsoSts
|
|
49
74
|
class SomeElement < Lutaml::Model::Serializable
|
|
50
75
|
attribute :id, :string
|
|
51
|
-
attribute :content, :string
|
|
52
|
-
attribute :child, ::Sts::
|
|
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
|
-
|
|
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
|
-
**
|
|
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
|
|
136
|
+
### Reference data
|
|
70
137
|
|
|
71
|
-
- 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
|
|
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 # =>
|
|
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
|
-
#
|
|
156
|
-
|
|
155
|
+
# Round-trip preserves mml: prefix
|
|
156
|
+
disp_formula.to_xml # => <disp-formula><mml:math ...>...</mml:math></disp-formula>
|
|
157
157
|
----
|
|
158
158
|
|
|
159
|
-
|
|
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
|
data/TODO.roadmap/00-overview.md
CHANGED
|
@@ -23,32 +23,37 @@ noted.
|
|
|
23
23
|
|
|
24
24
|
| Track | Subject | Items |
|
|
25
25
|
|---|---|---|
|
|
26
|
-
| A | lutaml-model upstream
|
|
27
|
-
| B | Issue #40 namespace coupling completion | 03, 04 |
|
|
28
|
-
| C | Architectural improvements (DRY, versioning, audit) | 05,
|
|
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.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
data/lib/sts/iso_sts/standard.rb
CHANGED
data/lib/sts/namespaces.rb
CHANGED
|
@@ -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"
|
data/lib/sts/version.rb
CHANGED
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.
|
|
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-
|
|
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).
|