mml 2.3.3 → 2.3.5
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 +2 -35
- data/TODO.spacing-issues/01-dir-unmapped-v3common.md +82 -0
- data/TODO.spacing-issues/02-rspace-missing-mpadded-v4.md +69 -0
- data/TODO.spacing-issues/03-lspace-rspace-non-mo-tokens.md +79 -0
- data/TODO.spacing-issues/04-schema-audit-summary.md +80 -0
- data/lib/mml/base/content/ci.rb +1 -2
- data/lib/mml/base/content/cn.rb +1 -1
- data/lib/mml/base/content/csymbol.rb +1 -2
- data/lib/mml/base/mfenced.rb +1 -1
- data/lib/mml/base/mi.rb +1 -1
- data/lib/mml/base/mn.rb +1 -1
- data/lib/mml/base/mpadded.rb +2 -0
- data/lib/mml/base/mrow.rb +1 -2
- data/lib/mml/base/ms.rb +1 -2
- data/lib/mml/base/msgroup.rb +1 -2
- data/lib/mml/base/munder.rb +1 -1
- data/lib/mml/base/v3_common.rb +5 -0
- data/lib/mml/v2.rb +0 -2
- data/lib/mml/v3.rb +0 -2
- data/lib/mml/v4.rb +0 -2
- data/lib/mml/version.rb +1 -1
- data/lib/mml/versioned_parser.rb +18 -11
- data/lib/mml.rb +14 -3
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d2f675899b728ca8ae66ea735aa372b53d3c3126302547ef675e0a2d02157247
|
|
4
|
+
data.tar.gz: 0f9c4233bad5670c2df79e626853006733aa32b9ef493e751672b2822db743e8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c5d78174cf85dbfea29367c4227f5e3f72381b540095cc6527821281f10809ea9ef36c5c61de25992c2586363df1d5ded285598bec6170345c952f498e850519
|
|
7
|
+
data.tar.gz: 48b6ad8ea3e57a21f73be9189ec18b5eb3cfdd8d1fc6113a26552ba16a538aa00a2ab3e2f4116145af0a5d5c77fa92676f85aaae5f13b33a48fc04da0eb1e0a0
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,34 +1,12 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-04-
|
|
3
|
+
# on 2026-04-20 06:58:18 UTC using RuboCop version 1.86.0.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
|
-
# Offense count:
|
|
10
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
11
|
-
# Configuration parameters: EnforcedStyleAlignWith.
|
|
12
|
-
# SupportedStylesAlignWith: either, start_of_block, start_of_line
|
|
13
|
-
Layout/BlockAlignment:
|
|
14
|
-
Exclude:
|
|
15
|
-
- 'spec/lutaml_default_register_spec.rb'
|
|
16
|
-
|
|
17
|
-
# Offense count: 1
|
|
18
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
19
|
-
Layout/BlockEndNewline:
|
|
20
|
-
Exclude:
|
|
21
|
-
- 'spec/lutaml_default_register_spec.rb'
|
|
22
|
-
|
|
23
|
-
# Offense count: 2
|
|
24
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
25
|
-
# Configuration parameters: Width, EnforcedStyleAlignWith, AllowedPatterns.
|
|
26
|
-
# SupportedStylesAlignWith: start_of_line, relative_to_receiver
|
|
27
|
-
Layout/IndentationWidth:
|
|
28
|
-
Exclude:
|
|
29
|
-
- 'spec/lutaml_default_register_spec.rb'
|
|
30
|
-
|
|
31
|
-
# Offense count: 137
|
|
9
|
+
# Offense count: 136
|
|
32
10
|
# This cop supports safe autocorrection (--autocorrect).
|
|
33
11
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
34
12
|
# URISchemes: http, https
|
|
@@ -102,14 +80,3 @@ RSpec/SpecFilePathFormat:
|
|
|
102
80
|
RSpec/UnspecifiedException:
|
|
103
81
|
Exclude:
|
|
104
82
|
- 'spec/mml/v3_spec.rb'
|
|
105
|
-
|
|
106
|
-
# Offense count: 1
|
|
107
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
108
|
-
# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
|
|
109
|
-
# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
|
|
110
|
-
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
|
|
111
|
-
# FunctionalMethods: let, let!, subject, watch
|
|
112
|
-
# AllowedMethods: lambda, proc, it
|
|
113
|
-
Style/BlockDelimiters:
|
|
114
|
-
Exclude:
|
|
115
|
-
- 'spec/lutaml_default_register_spec.rb'
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# TODO: `dir` attribute declared but not XML-mapped in V3Common
|
|
2
|
+
|
|
3
|
+
## Severity: High (data loss on round-trip)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
|
|
7
|
+
`V3Common` (`lib/mml/base/v3_common.rb`) declares `attribute :dir, :string` but never
|
|
8
|
+
calls `map_attribute "dir", to: :dir` in an `xml do...end` block. The attribute exists
|
|
9
|
+
as a Ruby property but is never populated from XML input and never serialized to XML
|
|
10
|
+
output. This means `dir="ltr"` or `dir="rtl"` is silently dropped during round-trip.
|
|
11
|
+
|
|
12
|
+
The only element with a working `dir` mapping is `Mspace` (`lib/mml/base/mspace.rb:33`),
|
|
13
|
+
which declares it independently.
|
|
14
|
+
|
|
15
|
+
## Schema Evidence
|
|
16
|
+
|
|
17
|
+
All three schemas confirm `dir` is valid on these elements:
|
|
18
|
+
|
|
19
|
+
### MathML 3 XSD (`schemas/mathml3/mathml3-presentation.xsd`)
|
|
20
|
+
- `TokenAtt` attribute group (line 624-631): `dir` on ALL token elements (mi, mn, mo, mtext, ms)
|
|
21
|
+
- `mrow.attributes` (line 713-720): `dir` on mrow
|
|
22
|
+
- `mstyle.generalattributes` (line 1010-1017): `dir` on mstyle
|
|
23
|
+
- `math.attributes` inherits mstyle.generalattributes
|
|
24
|
+
|
|
25
|
+
### MathML 4 Core RNC (`schemas/mathml4/mathml4-core.rnc`)
|
|
26
|
+
- `MathMLPGlobalAttributes` (line 139): `attribute dir {"ltr" | "rtl"}?` — on ALL presentation elements
|
|
27
|
+
|
|
28
|
+
### MathML 2 XSD (`schemas/mathml2/presentation/common-attribs.xsd`)
|
|
29
|
+
- Does NOT have `dir` (added in MathML 3)
|
|
30
|
+
|
|
31
|
+
## Affected Elements (V3 + V4)
|
|
32
|
+
|
|
33
|
+
| Element | V3Common included? | dir mapped? |
|
|
34
|
+
|---------|-------------------|-------------|
|
|
35
|
+
| mi | yes | **NO** |
|
|
36
|
+
| mn | yes | **NO** |
|
|
37
|
+
| mo | yes | **NO** |
|
|
38
|
+
| mtext | yes | **NO** |
|
|
39
|
+
| ms | yes | **NO** |
|
|
40
|
+
| mrow | yes | **NO** |
|
|
41
|
+
| mstyle | yes | **NO** |
|
|
42
|
+
| math | yes | **NO** |
|
|
43
|
+
| mspace | no (independent) | yes |
|
|
44
|
+
|
|
45
|
+
## Fix
|
|
46
|
+
|
|
47
|
+
Add an `xml do...end` block with the `dir` mapping to `V3Common`:
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
# lib/mml/base/v3_common.rb
|
|
51
|
+
module Mml
|
|
52
|
+
module Base
|
|
53
|
+
module V3Common
|
|
54
|
+
def self.included(klass)
|
|
55
|
+
klass.class_eval do
|
|
56
|
+
attribute :dir, :string
|
|
57
|
+
include V3PresentationAttributes
|
|
58
|
+
|
|
59
|
+
xml do
|
|
60
|
+
namespace Mml::Namespace
|
|
61
|
+
map_attribute "dir", to: :dir
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Test Case
|
|
71
|
+
|
|
72
|
+
```xml
|
|
73
|
+
<math xmlns="http://www.w3.org/1998/Math/MathML">
|
|
74
|
+
<mrow dir="rtl">
|
|
75
|
+
<mi dir="rtl">x</mi>
|
|
76
|
+
<mo>+</mo>
|
|
77
|
+
<mn>1</mn>
|
|
78
|
+
</mrow>
|
|
79
|
+
</math>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The `dir` attributes are currently silently dropped during round-trip.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# TODO: `rspace` attribute missing from `mpadded` (MathML 4)
|
|
2
|
+
|
|
3
|
+
## Severity: Medium (V4 data loss on round-trip)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
|
|
7
|
+
`Base::Mpadded` (`lib/mml/base/mpadded.rb`) has `lspace` but not `rspace`.
|
|
8
|
+
In MathML 3, `mpadded` only has `lspace` — this was correct. But MathML 4
|
|
9
|
+
added `rspace` to `mpadded.attributes`, and the gem doesn't support it.
|
|
10
|
+
|
|
11
|
+
## Schema Evidence
|
|
12
|
+
|
|
13
|
+
### MathML 3 XSD (`schemas/mathml3/mathml3-presentation.xsd`, line 1491-1499)
|
|
14
|
+
```xml
|
|
15
|
+
<xs:attributeGroup name="mpadded.attributes">
|
|
16
|
+
<xs:attribute name="height" type="m:mpadded-length"/>
|
|
17
|
+
<xs:attribute name="depth" type="m:mpadded-length"/>
|
|
18
|
+
<xs:attribute name="width" type="m:mpadded-length"/>
|
|
19
|
+
<xs:attribute name="lspace" type="m:mpadded-length"/>
|
|
20
|
+
<xs:attribute name="voffset" type="m:mpadded-length"/>
|
|
21
|
+
</xs:attributeGroup>
|
|
22
|
+
```
|
|
23
|
+
No `rspace` — V3 is correct.
|
|
24
|
+
|
|
25
|
+
### MathML 4 Core RNC (`schemas/mathml4/mathml4-core.rnc`, line 289-297)
|
|
26
|
+
```
|
|
27
|
+
mpadded.attributes =
|
|
28
|
+
MathMLPGlobalAttributes,
|
|
29
|
+
attribute height {mpadded-length-percentage}?,
|
|
30
|
+
attribute depth {mpadded-length-percentage}?,
|
|
31
|
+
attribute width {mpadded-length-percentage}?,
|
|
32
|
+
attribute lspace {mpadded-length-percentage}?,
|
|
33
|
+
attribute rspace {mpadded-length-percentage}?, # <-- NEW IN V4
|
|
34
|
+
attribute voffset {mpadded-length-percentage}?
|
|
35
|
+
```
|
|
36
|
+
`rspace` added in V4.
|
|
37
|
+
|
|
38
|
+
## Current State
|
|
39
|
+
|
|
40
|
+
`lib/mml/base/mpadded.rb`:
|
|
41
|
+
```ruby
|
|
42
|
+
attribute :lspace, :string # has lspace
|
|
43
|
+
# NO rspace
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Fix
|
|
47
|
+
|
|
48
|
+
Add `rspace` to `Base::Mpadded`:
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
# lib/mml/base/mpadded.rb
|
|
52
|
+
attribute :rspace, :string # add after lspace
|
|
53
|
+
|
|
54
|
+
# in xml do...end block:
|
|
55
|
+
map_attribute "rspace", to: :rspace # add after lspace mapping
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Since `Base::Mpadded` is shared by V3 and V4, adding `rspace` is harmless for V3
|
|
59
|
+
(the attribute will be accepted but wouldn't be generated by a spec-compliant V3 producer).
|
|
60
|
+
|
|
61
|
+
## Test Case
|
|
62
|
+
|
|
63
|
+
```xml
|
|
64
|
+
<math xmlns="http://www.w3.org/1998/Math/MathML">
|
|
65
|
+
<mpadded rspace="0.5em"><mi>x</mi></mpadded>
|
|
66
|
+
</math>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The `rspace` attribute is currently silently dropped during V4 round-trip.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# TODO: `lspace`/`rspace` on non-mo token elements (data fidelity, NOT spec)
|
|
2
|
+
|
|
3
|
+
## Severity: Low (data fidelity enhancement, not a spec compliance bug)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
|
|
7
|
+
Real-world MathML documents sometimes use `lspace` or `rspace` on non-`<mo>` token
|
|
8
|
+
elements (e.g., `<mi rspace="thickmathspace">`). The gem silently drops these
|
|
9
|
+
attributes during round-trip because they're only implemented on `Mml::Base::Mo`.
|
|
10
|
+
|
|
11
|
+
The original TODO report (`TODO-mml-missing-rspace.md`) claimed these are valid
|
|
12
|
+
on ALL token elements per the MathML spec. This claim is **incorrect**.
|
|
13
|
+
|
|
14
|
+
## Schema Evidence: `lspace`/`rspace` are `mo`-only across ALL versions
|
|
15
|
+
|
|
16
|
+
### MathML 2 XSD (`schemas/mathml2/presentation/common-attribs.xsd`)
|
|
17
|
+
- `Operator.attrib` (line 57-105): contains `lspace` and `rspace`
|
|
18
|
+
- Only `mo.attlist` references `Operator.attrib` (line 46-50)
|
|
19
|
+
- `mi.attlist`, `mn.attlist`, `mtext.attlist`, `ms.attlist` do NOT reference it
|
|
20
|
+
|
|
21
|
+
### MathML 3 XSD (`schemas/mathml3/mathml3-presentation.xsd`)
|
|
22
|
+
- `mo.attributes` (line 203-204): `lspace`, `rspace` directly on mo
|
|
23
|
+
- `mi.attributes` (line 152-156): only CommonAtt + CommonPresAtt + TokenAtt — no lspace/rspace
|
|
24
|
+
- `mn.attributes` (line 163-167): same
|
|
25
|
+
- `mtext.attributes` (line 346-350): same
|
|
26
|
+
- `ms.attributes` (line 441-447): same + lquote/rquote
|
|
27
|
+
|
|
28
|
+
### MathML 4 Core RNC (`schemas/mathml4/mathml4-core.rnc`)
|
|
29
|
+
- `mo.attributes` (line 228-229): `attribute lspace`, `attribute rspace`
|
|
30
|
+
- `mi.attributes` (line 217-218): only MathMLPGlobalAttributes
|
|
31
|
+
- `mn.attributes` (line 220-222): only MathMLPGlobalAttributes
|
|
32
|
+
- `mtext.attributes` (line 238-240): only MathMLPGlobalAttributes
|
|
33
|
+
- `ms.attributes` (line 249-251): only MathMLPGlobalAttributes
|
|
34
|
+
|
|
35
|
+
## Conclusion
|
|
36
|
+
|
|
37
|
+
The TODO report's claim that `lspace`/`rspace` are defined on a "TokenEl type" and
|
|
38
|
+
apply to all token elements is fabricated. No such type exists in any schema version.
|
|
39
|
+
These are `mo`-specific operator spacing attributes, always have been.
|
|
40
|
+
|
|
41
|
+
## Real-World Impact
|
|
42
|
+
|
|
43
|
+
196 normative diffs in the Metanorma round-trip test suite — documents use
|
|
44
|
+
`<mi rspace="thickmathspace">` in practice. Even though the spec doesn't mandate
|
|
45
|
+
supporting this, the gem should preserve the attribute to prevent data loss.
|
|
46
|
+
|
|
47
|
+
## Recommended Fix (Optional Enhancement)
|
|
48
|
+
|
|
49
|
+
If round-trip fidelity for these non-standard uses is desired, add `lspace` and
|
|
50
|
+
`rspace` to the non-mo token elements. This should be documented as a data
|
|
51
|
+
fidelity enhancement, not a spec compliance fix.
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
# Add to Mml::Base::Mi, Mml::Base::Mn, Mml::Base::Mtext, Mml::Base::Ms
|
|
55
|
+
attribute :lspace, :string
|
|
56
|
+
attribute :rspace, :string
|
|
57
|
+
|
|
58
|
+
# In xml do...end block:
|
|
59
|
+
map_attribute "lspace", to: :lspace
|
|
60
|
+
map_attribute "rspace", to: :rspace
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Test Case
|
|
64
|
+
|
|
65
|
+
```xml
|
|
66
|
+
<math xmlns="http://www.w3.org/1998/Math/MathML">
|
|
67
|
+
<mrow>
|
|
68
|
+
<mstyle mathvariant="normal"><mi>µmol</mi></mstyle>
|
|
69
|
+
<mi rspace="thickmathspace"></mi>
|
|
70
|
+
<msup><mstyle mathvariant="normal"><mi>mol</mi></mstyle>
|
|
71
|
+
<mrow><mo>−</mo><mn>1</mn></mrow>
|
|
72
|
+
</msup>
|
|
73
|
+
</mrow>
|
|
74
|
+
</math>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The `<mi rspace="thickmathspace">` currently loses its `rspace` during round-trip.
|
|
78
|
+
This is a data fidelity issue, NOT a spec violation — the input document is the one
|
|
79
|
+
not complying with the spec.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Schema Audit Summary: Token Element Attributes
|
|
2
|
+
|
|
3
|
+
## Audit Scope
|
|
4
|
+
|
|
5
|
+
Systematic comparison of token element attributes across:
|
|
6
|
+
- MathML 2 XSD (`schemas/mathml2/`)
|
|
7
|
+
- MathML 3 XSD (`schemas/mathml3/`)
|
|
8
|
+
- MathML 4 Core + Presentation RNC (`schemas/mathml4/`)
|
|
9
|
+
- mml gem implementation (`lib/mml/base/`, `lib/mml/v3/`, `lib/mml/v4/`)
|
|
10
|
+
|
|
11
|
+
## Attribute Origin by Schema Version
|
|
12
|
+
|
|
13
|
+
### V3 Token Element Attribute Composition
|
|
14
|
+
|
|
15
|
+
| Attribute Group | Attributes | Used by |
|
|
16
|
+
|----------------|-----------|---------|
|
|
17
|
+
| `CommonAtt` | id, xref, class, style, href | ALL elements |
|
|
18
|
+
| `CommonPresAtt` | mathcolor, mathbackground | ALL pres elements |
|
|
19
|
+
| `TokenAtt` | mathvariant, mathsize, dir | mi, mn, mo, mtext, ms |
|
|
20
|
+
| `DeprecatedTokenAtt` | fontfamily, fontweight, fontstyle, fontsize, color, background | tokens (V3 only) |
|
|
21
|
+
| mo-specific | form, fence, separator, lspace, rspace, stretchy, symmetric, maxsize, minsize, largeop, movablelimits, accent, linebreak*, indent* | mo only |
|
|
22
|
+
| ms-specific | lquote, rquote | ms only |
|
|
23
|
+
|
|
24
|
+
### V4 Token Element Attribute Composition
|
|
25
|
+
|
|
26
|
+
| Attribute Group | Attributes | Used by |
|
|
27
|
+
|----------------|-----------|---------|
|
|
28
|
+
| `MathMLPGlobalAttributes` | id, class, style, dir, mathcolor, mathbackground, mathsize, mathvariant, displaystyle, scriptlevel, intent, arg | ALL elements |
|
|
29
|
+
| mo-specific (core) | form, lspace, rspace, stretchy, symmetric, maxsize, minsize, largeop, movablelimits | mo only |
|
|
30
|
+
| mo-specific (pres) | linebreak*, indent*, accent | mo only |
|
|
31
|
+
| ms-specific | lquote, rquote | ms only |
|
|
32
|
+
|
|
33
|
+
## Gem Implementation Matrix
|
|
34
|
+
|
|
35
|
+
| Attribute | Mi | Mn | Mo | Mtext | Ms | Mspace | Source |
|
|
36
|
+
|-----------|----|----|-----|-------|----|--------|--------|
|
|
37
|
+
| mathcolor | G | G | G | G | G | B | UniversalPresentationAttributes |
|
|
38
|
+
| mathbackground | G | G | G | G | G | B | UniversalPresentationAttributes |
|
|
39
|
+
| mathsize | G | G | G | G | G | - | UniversalPresentationAttributes |
|
|
40
|
+
| mathvariant | B | B | B | B | B | B | Base::Mi/Mn/Mo/Mtext/Ms |
|
|
41
|
+
| displaystyle | G | G | G | G | G | - | UniversalPresentationAttributes |
|
|
42
|
+
| scriptlevel | G | G | G | G | G | - | UniversalPresentationAttributes |
|
|
43
|
+
| **dir** | **G** | **G** | **G** | **G** | **G** | **B** | **V3Common (UNMAPPED!)** |
|
|
44
|
+
| intent | V4 | V4 | V4 | V4 | V4 | - | V4OnlyAttributes |
|
|
45
|
+
| arg | V4 | V4 | V4 | V4 | V4 | - | V4OnlyAttributes |
|
|
46
|
+
| form | - | - | B | - | - | - | Base::Mo |
|
|
47
|
+
| lspace | - | - | B | - | - | - | Base::Mo |
|
|
48
|
+
| rspace | - | - | B | - | - | - | Base::Mo |
|
|
49
|
+
| stretchy | - | - | B | - | - | - | Base::Mo |
|
|
50
|
+
| symmetric | - | - | B | - | - | - | Base::Mo |
|
|
51
|
+
| maxsize | - | - | B | - | - | - | Base::Mo |
|
|
52
|
+
| minsize | - | - | B | - | - | - | Base::Mo |
|
|
53
|
+
| largeop | - | - | B | - | - | - | Base::Mo |
|
|
54
|
+
| movablelimits | - | - | B | - | - | - | Base::Mo |
|
|
55
|
+
| accent | - | - | B | - | - | - | Base::Mo |
|
|
56
|
+
| fence | - | - | V3O | - | - | - | V3Only::OperatorAttributes |
|
|
57
|
+
| separator | - | - | V3O | - | - | - | V3Only::OperatorAttributes |
|
|
58
|
+
| linebreak* | - | - | B | - | - | B | Base::Mo / Base::Mspace |
|
|
59
|
+
| indent* | - | - | B | - | - | B | Base::Mo / Base::Mspace |
|
|
60
|
+
| lquote | - | - | - | - | B | - | Base::Ms |
|
|
61
|
+
| rquote | - | - | - | - | B | - | Base::Ms |
|
|
62
|
+
| Deprecated font | V3 | V3 | V3 | V3 | V3 | - | DeprecatedFontAttributes |
|
|
63
|
+
|
|
64
|
+
**G** = from gem global modules, **B** = from base module, **V3O** = V3-only module, **V4** = V4-only
|
|
65
|
+
|
|
66
|
+
Legend: G=UniversalPresentationAttributes/V3Common, B=Base::*, V3O=V3Only, V4=V4Only
|
|
67
|
+
|
|
68
|
+
## Issues Found
|
|
69
|
+
|
|
70
|
+
1. **`dir` unmapped** (see `01-dir-unmapped-v3common.md`) — HIGH
|
|
71
|
+
2. **`rspace` missing from mpadded** (see `02-rspace-missing-mpadded-v4.md`) — MEDIUM
|
|
72
|
+
3. **`lspace`/`rspace` on non-mo tokens** (see `03-lspace-rspace-non-mo-tokens.md`) — LOW
|
|
73
|
+
|
|
74
|
+
## What Was Already Correct
|
|
75
|
+
|
|
76
|
+
- `separator` on mo: correctly in `V3Only::OperatorAttributes`, only for V2/V3
|
|
77
|
+
- `fence` on mo: same module, same scoping
|
|
78
|
+
- Deprecated font attributes: correctly scoped to V3 only via `DeprecatedFontAttributes`
|
|
79
|
+
- `mspace` dir: correctly has both attribute + mapping independently
|
|
80
|
+
- All `mo`-specific attributes (form, stretchy, etc.) correctly scoped to Base::Mo only
|
data/lib/mml/base/content/ci.rb
CHANGED
|
@@ -9,8 +9,7 @@ module Mml
|
|
|
9
9
|
attribute :type, :string
|
|
10
10
|
attribute :definition_url, :string
|
|
11
11
|
attribute :encoding_value, :string
|
|
12
|
-
attribute :value, :string
|
|
13
|
-
|
|
12
|
+
attribute :value, :string, collection: true
|
|
14
13
|
# Presentation elements that can appear inside ci
|
|
15
14
|
attribute :msub_value, :msub, collection: true
|
|
16
15
|
attribute :msup_value, :msup, collection: true
|
data/lib/mml/base/content/cn.rb
CHANGED
|
@@ -10,8 +10,7 @@ module Mml
|
|
|
10
10
|
attribute :definition_url, :string
|
|
11
11
|
attribute :encoding_value, :string
|
|
12
12
|
attribute :cd, :string
|
|
13
|
-
attribute :value, :string
|
|
14
|
-
|
|
13
|
+
attribute :value, :string, collection: true
|
|
15
14
|
# Presentation elements that can appear inside csymbol
|
|
16
15
|
attribute :msub_value, :msub, collection: true
|
|
17
16
|
attribute :msup_value, :msup, collection: true
|
data/lib/mml/base/mfenced.rb
CHANGED
data/lib/mml/base/mi.rb
CHANGED
|
@@ -7,7 +7,7 @@ module Mml
|
|
|
7
7
|
# Use fully qualified names (e.g., Mml::Namespace).
|
|
8
8
|
def self.included(klass)
|
|
9
9
|
klass.class_eval do
|
|
10
|
-
attribute :value, :string
|
|
10
|
+
attribute :value, :string, collection: true
|
|
11
11
|
attribute :mathcolor, :string
|
|
12
12
|
attribute :mathbackground, :string
|
|
13
13
|
attribute :mathsize, :string
|
data/lib/mml/base/mn.rb
CHANGED
|
@@ -7,7 +7,7 @@ module Mml
|
|
|
7
7
|
# Use fully qualified names (e.g., Mml::Namespace).
|
|
8
8
|
def self.included(klass)
|
|
9
9
|
klass.class_eval do
|
|
10
|
-
attribute :value, :string
|
|
10
|
+
attribute :value, :string, collection: true
|
|
11
11
|
attribute :mathcolor, :string
|
|
12
12
|
attribute :mathbackground, :string
|
|
13
13
|
attribute :mathvariant, :string
|
data/lib/mml/base/mpadded.rb
CHANGED
|
@@ -12,6 +12,7 @@ module Mml
|
|
|
12
12
|
attribute :voffset, :string
|
|
13
13
|
attribute :height, :string
|
|
14
14
|
attribute :lspace, :string
|
|
15
|
+
attribute :rspace, :string
|
|
15
16
|
attribute :depth, :string
|
|
16
17
|
attribute :width, :string
|
|
17
18
|
|
|
@@ -25,6 +26,7 @@ module Mml
|
|
|
25
26
|
map_attribute "voffset", to: :voffset
|
|
26
27
|
map_attribute "height", to: :height
|
|
27
28
|
map_attribute "lspace", to: :lspace
|
|
29
|
+
map_attribute "rspace", to: :rspace
|
|
28
30
|
map_attribute "depth", to: :depth
|
|
29
31
|
map_attribute "width", to: :width
|
|
30
32
|
end
|
data/lib/mml/base/mrow.rb
CHANGED
data/lib/mml/base/ms.rb
CHANGED
data/lib/mml/base/msgroup.rb
CHANGED
|
@@ -11,8 +11,7 @@ module Mml
|
|
|
11
11
|
attribute :mathbackground, :string
|
|
12
12
|
attribute :position, :integer
|
|
13
13
|
attribute :shift, :integer
|
|
14
|
-
attribute :msgroup_text, :string
|
|
15
|
-
|
|
14
|
+
attribute :msgroup_text, :string, collection: true
|
|
16
15
|
xml do
|
|
17
16
|
namespace Mml::Namespace
|
|
18
17
|
element "msgroup"
|
data/lib/mml/base/munder.rb
CHANGED
data/lib/mml/base/v3_common.rb
CHANGED
data/lib/mml/v2.rb
CHANGED
data/lib/mml/v3.rb
CHANGED
data/lib/mml/v4.rb
CHANGED
data/lib/mml/version.rb
CHANGED
data/lib/mml/versioned_parser.rb
CHANGED
|
@@ -5,7 +5,6 @@ module Mml
|
|
|
5
5
|
# Shared parse entrypoint for versioned modules.
|
|
6
6
|
def parse(input, namespace_exist: true,
|
|
7
7
|
context: Mml::UNSPECIFIED_CONTEXT, register: nil)
|
|
8
|
-
self::Configuration.adapter ||= Mml::DEFAULT_ADAPTER
|
|
9
8
|
context_id = parse_context_id(context, register)
|
|
10
9
|
root_class = Lutaml::Model::GlobalContext.resolve_type(
|
|
11
10
|
:math,
|
|
@@ -18,14 +17,6 @@ module Mml
|
|
|
18
17
|
)
|
|
19
18
|
end
|
|
20
19
|
|
|
21
|
-
# Namespace-less MathML is normalized before handing it to lutaml-model.
|
|
22
|
-
def parse_with_no_namespace(input)
|
|
23
|
-
adapter = self::Configuration.adapter || Mml::DEFAULT_ADAPTER
|
|
24
|
-
Moxml.new(adapter).parse(input).tap do |doc|
|
|
25
|
-
doc.root.add_namespace(nil, self::Namespace.uri)
|
|
26
|
-
end.to_xml
|
|
27
|
-
end
|
|
28
|
-
|
|
29
20
|
# Version modules keep their own default context id.
|
|
30
21
|
def parse_context_id(context, register)
|
|
31
22
|
Mml::ContextOptions.normalize_context_option(
|
|
@@ -36,11 +27,27 @@ module Mml
|
|
|
36
27
|
)
|
|
37
28
|
end
|
|
38
29
|
|
|
39
|
-
#
|
|
30
|
+
# Inject the MathML namespace into the raw XML string before parsing.
|
|
31
|
+
# This avoids a double parse-serialize cycle (previously the code used
|
|
32
|
+
# Moxml to parse → add namespace → serialize → parse again).
|
|
33
|
+
#
|
|
34
|
+
# String-level injection is safe for well-formed MathML: the root element
|
|
35
|
+
# is always <math>. For malformed input, the subsequent from_xml parse will
|
|
36
|
+
# raise a proper error.
|
|
40
37
|
def xml_input(input, namespace_exist)
|
|
41
38
|
return input if namespace_exist
|
|
42
39
|
|
|
43
|
-
|
|
40
|
+
inject_namespace(input, self::Namespace.uri)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def inject_namespace(xml_string, namespace_uri)
|
|
46
|
+
# Add xmlns attribute to the <math> root element in the raw XML string.
|
|
47
|
+
# Handles both <math> and <math ...> (with existing attributes).
|
|
48
|
+
xml_string.sub(/<math([\s>])/) do
|
|
49
|
+
"<math xmlns=\"#{namespace_uri}\"#{::Regexp.last_match(1)}"
|
|
50
|
+
end
|
|
44
51
|
end
|
|
45
52
|
end
|
|
46
53
|
end
|
data/lib/mml.rb
CHANGED
|
@@ -5,10 +5,23 @@ require "lutaml/model"
|
|
|
5
5
|
module Mml
|
|
6
6
|
class Error < StandardError; end
|
|
7
7
|
|
|
8
|
-
DEFAULT_ADAPTER = RUBY_ENGINE == "opal" ? :oga : :ox
|
|
9
8
|
SUPPORTED_VERSIONS = [2, 3, 4].freeze
|
|
10
9
|
UNSPECIFIED_CONTEXT = Object.new.freeze
|
|
11
10
|
|
|
11
|
+
# Returns the appropriate XML adapter, respecting the host application's
|
|
12
|
+
# configuration. Opal always uses Oga; CRuby delegates to
|
|
13
|
+
# Lutaml::Model::Config.xml_adapter_type so that users control the adapter
|
|
14
|
+
# from a single configuration point.
|
|
15
|
+
module_function
|
|
16
|
+
|
|
17
|
+
def default_adapter
|
|
18
|
+
if RUBY_ENGINE == "opal"
|
|
19
|
+
:oga
|
|
20
|
+
else
|
|
21
|
+
Lutaml::Model::Config.xml_adapter_type
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
12
25
|
autoload :Namespace, "mml/namespace"
|
|
13
26
|
autoload :CommonElements, "mml/common_elements"
|
|
14
27
|
autoload :ContextOptions, "mml/context_options"
|
|
@@ -17,8 +30,6 @@ module Mml
|
|
|
17
30
|
autoload :V3, "mml/v3"
|
|
18
31
|
autoload :V4, "mml/v4"
|
|
19
32
|
|
|
20
|
-
module_function
|
|
21
|
-
|
|
22
33
|
def parse(
|
|
23
34
|
input,
|
|
24
35
|
namespace_exist: true,
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mml
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.3.
|
|
4
|
+
version: 2.3.5
|
|
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-04-
|
|
11
|
+
date: 2026-04-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|
|
@@ -59,6 +59,10 @@ files:
|
|
|
59
59
|
- Gemfile
|
|
60
60
|
- README.adoc
|
|
61
61
|
- Rakefile
|
|
62
|
+
- TODO.spacing-issues/01-dir-unmapped-v3common.md
|
|
63
|
+
- TODO.spacing-issues/02-rspace-missing-mpadded-v4.md
|
|
64
|
+
- TODO.spacing-issues/03-lspace-rspace-non-mo-tokens.md
|
|
65
|
+
- TODO.spacing-issues/04-schema-audit-summary.md
|
|
62
66
|
- bin/console
|
|
63
67
|
- bin/setup
|
|
64
68
|
- lib/mml.rb
|