mml 2.0.3 → 2.2.0
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/.github/workflows/release.yml +10 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +20 -91
- data/Gemfile +2 -1
- data/README.adoc +365 -4
- data/lib/mml/v3/common_attributes.rb +22 -0
- data/lib/mml/v3/configuration.rb +105 -0
- data/lib/mml/v3/maction.rb +22 -0
- data/lib/mml/v3/maligngroup.rb +20 -0
- data/lib/mml/v3/malignmark.rb +20 -0
- data/lib/mml/v3/math.rb +20 -0
- data/lib/mml/v3/menclose.rb +21 -0
- data/lib/mml/v3/merror.rb +19 -0
- data/lib/mml/v3/mfenced.rb +28 -0
- data/lib/mml/v3/mfrac.rb +27 -0
- data/lib/mml/v3/mfraction.rb +27 -0
- data/lib/mml/v3/mglyph.rb +46 -0
- data/lib/mml/v3/mi.rb +38 -0
- data/lib/mml/v3/mlabeledtr.rb +31 -0
- data/lib/mml/v3/mlongdiv.rb +25 -0
- data/lib/mml/v3/mmultiscripts.rb +27 -0
- data/lib/mml/v3/mn.rb +38 -0
- data/lib/mml/v3/mo.rb +86 -0
- data/lib/mml/v3/mover.rb +23 -0
- data/lib/mml/v3/mpadded.rb +29 -0
- data/lib/mml/v3/mphantom.rb +19 -0
- data/lib/mml/v3/mprescripts.rb +18 -0
- data/lib/mml/v3/mroot.rb +19 -0
- data/lib/mml/v3/mrow.rb +25 -0
- data/lib/mml/v3/ms.rb +43 -0
- data/lib/mml/v3/mscarries.rb +27 -0
- data/lib/mml/v3/mscarry.rb +23 -0
- data/lib/mml/v3/msgroup.rb +25 -0
- data/lib/mml/v3/msline.rb +28 -0
- data/lib/mml/v3/mspace.rb +58 -0
- data/lib/mml/v3/msqrt.rb +19 -0
- data/lib/mml/v3/msrow.rb +21 -0
- data/lib/mml/v3/mstack.rb +27 -0
- data/lib/mml/v3/mstyle.rb +211 -0
- data/lib/mml/v3/msub.rb +21 -0
- data/lib/mml/v3/msubsup.rb +23 -0
- data/lib/mml/v3/msup.rb +21 -0
- data/lib/mml/v3/mtable.rb +61 -0
- data/lib/mml/v3/mtd.rb +23 -0
- data/lib/mml/v3/mtext.rb +38 -0
- data/lib/mml/v3/mtr.rb +29 -0
- data/lib/mml/v3/munder.rb +25 -0
- data/lib/mml/v3/munderover.rb +25 -0
- data/lib/mml/v3/namespace.rb +10 -0
- data/lib/mml/v3/none.rb +18 -0
- data/lib/mml/v3/semantics.rb +19 -0
- data/lib/mml/v3/version.rb +7 -0
- data/lib/mml/v3.rb +85 -0
- data/lib/mml/v4/a.rb +31 -0
- data/lib/mml/v4/common_attributes.rb +26 -0
- data/lib/mml/v4/configuration.rb +106 -0
- data/lib/mml/v4/maction.rb +30 -0
- data/lib/mml/v4/maligngroup.rb +28 -0
- data/lib/mml/v4/malignmark.rb +28 -0
- data/lib/mml/v4/math.rb +27 -0
- data/lib/mml/v4/menclose.rb +29 -0
- data/lib/mml/v4/merror.rb +27 -0
- data/lib/mml/v4/mfenced.rb +36 -0
- data/lib/mml/v4/mfrac.rb +35 -0
- data/lib/mml/v4/mfraction.rb +31 -0
- data/lib/mml/v4/mglyph.rb +46 -0
- data/lib/mml/v4/mi.rb +41 -0
- data/lib/mml/v4/mlabeledtr.rb +34 -0
- data/lib/mml/v4/mlongdiv.rb +29 -0
- data/lib/mml/v4/mmultiscripts.rb +35 -0
- data/lib/mml/v4/mn.rb +40 -0
- data/lib/mml/v4/mo.rb +86 -0
- data/lib/mml/v4/mover.rb +31 -0
- data/lib/mml/v4/mpadded.rb +37 -0
- data/lib/mml/v4/mphantom.rb +27 -0
- data/lib/mml/v4/mprescripts.rb +22 -0
- data/lib/mml/v4/mroot.rb +27 -0
- data/lib/mml/v4/mrow.rb +31 -0
- data/lib/mml/v4/ms.rb +45 -0
- data/lib/mml/v4/mscarries.rb +31 -0
- data/lib/mml/v4/mscarry.rb +27 -0
- data/lib/mml/v4/msgroup.rb +29 -0
- data/lib/mml/v4/msline.rb +32 -0
- data/lib/mml/v4/mspace.rb +60 -0
- data/lib/mml/v4/msqrt.rb +27 -0
- data/lib/mml/v4/msrow.rb +29 -0
- data/lib/mml/v4/mstack.rb +35 -0
- data/lib/mml/v4/mstyle.rb +197 -0
- data/lib/mml/v4/msub.rb +29 -0
- data/lib/mml/v4/msubsup.rb +31 -0
- data/lib/mml/v4/msup.rb +29 -0
- data/lib/mml/v4/mtable.rb +66 -0
- data/lib/mml/v4/mtd.rb +31 -0
- data/lib/mml/v4/mtext.rb +40 -0
- data/lib/mml/v4/mtr.rb +36 -0
- data/lib/mml/v4/munder.rb +33 -0
- data/lib/mml/v4/munderover.rb +33 -0
- data/lib/mml/v4/namespace.rb +10 -0
- data/lib/mml/v4/none.rb +22 -0
- data/lib/mml/v4/opal_setup.rb.erb +6 -0
- data/lib/mml/v4/semantics.rb +23 -0
- data/lib/mml/v4/version.rb +7 -0
- data/lib/mml/v4.rb +81 -0
- data/lib/mml/version.rb +1 -1
- data/lib/mml.rb +25 -43
- data/mml.gemspec +1 -1
- metadata +105 -53
- data/lib/mml/common_attributes.rb +0 -23
- data/lib/mml/configuration.rb +0 -104
- data/lib/mml/maction.rb +0 -19
- data/lib/mml/maligngroup.rb +0 -17
- data/lib/mml/malignmark.rb +0 -17
- data/lib/mml/math_with_namespace.rb +0 -14
- data/lib/mml/math_with_nil_namespace.rb +0 -13
- data/lib/mml/menclose.rb +0 -17
- data/lib/mml/merror.rb +0 -15
- data/lib/mml/mfenced.rb +0 -24
- data/lib/mml/mfrac.rb +0 -23
- data/lib/mml/mfraction.rb +0 -23
- data/lib/mml/mglyph.rb +0 -43
- data/lib/mml/mi.rb +0 -35
- data/lib/mml/mlabeledtr.rb +0 -27
- data/lib/mml/mlongdiv.rb +0 -21
- data/lib/mml/mmultiscripts.rb +0 -23
- data/lib/mml/mn.rb +0 -35
- data/lib/mml/mo.rb +0 -83
- data/lib/mml/mover.rb +0 -19
- data/lib/mml/mpadded.rb +0 -25
- data/lib/mml/mphantom.rb +0 -15
- data/lib/mml/mprescripts.rb +0 -15
- data/lib/mml/mroot.rb +0 -15
- data/lib/mml/mrow.rb +0 -21
- data/lib/mml/ms.rb +0 -39
- data/lib/mml/mscarries.rb +0 -24
- data/lib/mml/mscarry.rb +0 -19
- data/lib/mml/msgroup.rb +0 -21
- data/lib/mml/msline.rb +0 -25
- data/lib/mml/mspace.rb +0 -55
- data/lib/mml/msqrt.rb +0 -15
- data/lib/mml/msrow.rb +0 -17
- data/lib/mml/mstack.rb +0 -23
- data/lib/mml/mstyle.rb +0 -212
- data/lib/mml/msub.rb +0 -17
- data/lib/mml/msubsup.rb +0 -19
- data/lib/mml/msup.rb +0 -17
- data/lib/mml/mtable.rb +0 -57
- data/lib/mml/mtd.rb +0 -19
- data/lib/mml/mtext.rb +0 -35
- data/lib/mml/mtr.rb +0 -25
- data/lib/mml/munder.rb +0 -21
- data/lib/mml/munderover.rb +0 -21
- data/lib/mml/none.rb +0 -15
- data/lib/mml/semantics.rb +0 -15
- /data/lib/mml/{opal_setup.rb.erb → v3/opal_setup.rb.erb} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: efbc2e4b8156916d34e524d2f7b6456168f8ef4a0c0c2ade8fbfb2b02bdc2efb
|
|
4
|
+
data.tar.gz: 8f826d13adfc7f0b556aa5ab6f32f8e8390bf06002a76570845605af7282058a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 694df3fcc6b3611d6bac5b5c380b420b91823e697b219ba93a5d9ec22c70d910f8ecef6fef6c419b1acf80660d726259056717380faf8e77d235879b056e3c85
|
|
7
|
+
data.tar.gz: 72b8f2d1960adec6a3777e43c792cf3d1d3aa4658be47e5bdbf9f7e5cd428ac1dbd3990d7c1685ae4f6ed1a90566b80932046c15424bf4b6a94efa4e39360a29
|
|
@@ -2,20 +2,26 @@
|
|
|
2
2
|
# See https://github.com/metanorma/cimas
|
|
3
3
|
name: release
|
|
4
4
|
|
|
5
|
+
permissions:
|
|
6
|
+
contents: write
|
|
7
|
+
packages: write
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
5
10
|
on:
|
|
6
11
|
workflow_dispatch:
|
|
7
12
|
inputs:
|
|
8
13
|
next_version:
|
|
9
14
|
description: |
|
|
10
|
-
Next release version. Possible values: x.y.z, major, minor, patch or pre|rc|etc
|
|
15
|
+
Next release version. Possible values: x.y.z, major, minor, patch (or pre|rc|etc).
|
|
16
|
+
Also, you can pass 'skip' to skip 'git tag' and do 'gem push' for the current version
|
|
11
17
|
required: true
|
|
12
18
|
default: 'skip'
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
repository_dispatch:
|
|
20
|
+
types: [ do-release ]
|
|
15
21
|
|
|
16
22
|
jobs:
|
|
17
23
|
release:
|
|
18
|
-
uses:
|
|
24
|
+
uses: relaton/support/.github/workflows/release.yml@main
|
|
19
25
|
with:
|
|
20
26
|
next_version: ${{ github.event.inputs.next_version }}
|
|
21
27
|
secrets:
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
|
@@ -1,115 +1,44 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on
|
|
3
|
+
# on 2026-03-31 03:44:08 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:
|
|
9
|
+
# Offense count: 3
|
|
10
10
|
# This cop supports safe autocorrection (--autocorrect).
|
|
11
|
-
# Configuration parameters:
|
|
12
|
-
# Include: **/*.gemspec
|
|
13
|
-
Gemspec/AddRuntimeDependency:
|
|
14
|
-
Exclude:
|
|
15
|
-
- 'mml.gemspec'
|
|
16
|
-
|
|
17
|
-
# Offense count: 1
|
|
18
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
19
|
-
# Configuration parameters: Severity, Include.
|
|
20
|
-
# Include: **/*.gemspec
|
|
21
|
-
Gemspec/DeprecatedAttributeAssignment:
|
|
22
|
-
Exclude:
|
|
23
|
-
- 'mml.gemspec'
|
|
24
|
-
|
|
25
|
-
# Offense count: 1
|
|
26
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
27
|
-
# Configuration parameters: Severity, Include.
|
|
28
|
-
# Include: **/*.gemspec
|
|
29
|
-
Gemspec/RequireMFA:
|
|
30
|
-
Exclude:
|
|
31
|
-
- 'mml.gemspec'
|
|
32
|
-
|
|
33
|
-
# Offense count: 1
|
|
34
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
35
|
-
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
36
|
-
# SupportedStyles: with_first_argument, with_fixed_indentation
|
|
37
|
-
Layout/ArgumentAlignment:
|
|
38
|
-
Exclude:
|
|
39
|
-
- 'lib/mml/common_attributes.rb'
|
|
40
|
-
|
|
41
|
-
# Offense count: 6
|
|
42
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
43
|
-
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
|
44
|
-
# SupportedHashRocketStyles: key, separator, table
|
|
45
|
-
# SupportedColonStyles: key, separator, table
|
|
46
|
-
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
|
47
|
-
Layout/HashAlignment:
|
|
48
|
-
Exclude:
|
|
49
|
-
- 'lib/mml/mscarries.rb'
|
|
50
|
-
- 'lib/mml/mstyle.rb'
|
|
51
|
-
|
|
52
|
-
# Offense count: 1
|
|
53
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
54
|
-
# Configuration parameters: EnforcedStyle.
|
|
55
|
-
# SupportedStyles: normal, indented_internal_methods
|
|
56
|
-
Layout/IndentationConsistency:
|
|
57
|
-
Exclude:
|
|
58
|
-
- 'mml.gemspec'
|
|
59
|
-
|
|
60
|
-
# Offense count: 8
|
|
61
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
62
|
-
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
|
11
|
+
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
63
12
|
# URISchemes: http, https
|
|
64
13
|
Layout/LineLength:
|
|
65
14
|
Exclude:
|
|
66
|
-
- 'lib/mml/common_attributes.rb'
|
|
67
|
-
- 'lib/mml/mscarries.rb'
|
|
68
|
-
- 'lib/mml/mstyle.rb'
|
|
69
15
|
- 'mml.gemspec'
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
73
|
-
# Configuration parameters: AllowInHeredoc.
|
|
74
|
-
Layout/TrailingWhitespace:
|
|
75
|
-
Exclude:
|
|
76
|
-
- 'lib/mml/common_attributes.rb'
|
|
77
|
-
- 'lib/mml/mscarries.rb'
|
|
78
|
-
- 'lib/mml/mstyle.rb'
|
|
16
|
+
- 'spec/mml_spec.rb'
|
|
17
|
+
- 'spec/spec_helper.rb'
|
|
79
18
|
|
|
80
19
|
# Offense count: 1
|
|
20
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
|
21
|
+
# AllowedMethods: refine
|
|
22
|
+
Metrics/BlockLength:
|
|
23
|
+
Max: 27
|
|
24
|
+
|
|
25
|
+
# Offense count: 3
|
|
81
26
|
# Configuration parameters: Prefixes, AllowedPatterns.
|
|
82
27
|
# Prefixes: when, with, without
|
|
83
28
|
RSpec/ContextWording:
|
|
84
29
|
Exclude:
|
|
30
|
+
- 'spec/mml4_spec.rb'
|
|
85
31
|
- 'spec/mml_spec.rb'
|
|
86
32
|
|
|
87
|
-
# Offense count:
|
|
88
|
-
|
|
89
|
-
# Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants.
|
|
90
|
-
# SupportedStyles: described_class, explicit
|
|
91
|
-
RSpec/DescribedClass:
|
|
92
|
-
Exclude:
|
|
93
|
-
- 'spec/mml_spec.rb'
|
|
94
|
-
|
|
95
|
-
# Offense count: 2
|
|
96
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
97
|
-
Style/FileRead:
|
|
33
|
+
# Offense count: 1
|
|
34
|
+
RSpec/MultipleDescribes:
|
|
98
35
|
Exclude:
|
|
99
36
|
- 'spec/mml_spec.rb'
|
|
100
37
|
|
|
101
|
-
# Offense count:
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
|
|
105
|
-
Style/StringLiterals:
|
|
106
|
-
Exclude:
|
|
107
|
-
- 'mml.gemspec'
|
|
108
|
-
|
|
109
|
-
# Offense count: 2
|
|
110
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
111
|
-
# Configuration parameters: EnforcedStyle.
|
|
112
|
-
# SupportedStyles: single_quotes, double_quotes
|
|
113
|
-
Style/StringLiteralsInInterpolation:
|
|
38
|
+
# Offense count: 1
|
|
39
|
+
# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
|
|
40
|
+
# SupportedInflectors: default, active_support
|
|
41
|
+
RSpec/SpecFilePathFormat:
|
|
114
42
|
Exclude:
|
|
115
|
-
- 'spec/
|
|
43
|
+
- '**/spec/routing/**/*'
|
|
44
|
+
- 'spec/mml4_spec.rb'
|
data/Gemfile
CHANGED
|
@@ -5,7 +5,8 @@ source "https://rubygems.org"
|
|
|
5
5
|
gemspec
|
|
6
6
|
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
7
7
|
|
|
8
|
-
gem "
|
|
8
|
+
gem "canon"
|
|
9
|
+
gem "lutaml-model", github: "lutaml/lutaml-model", branch: "main"
|
|
9
10
|
gem "ox"
|
|
10
11
|
gem "pry"
|
|
11
12
|
gem "rake", "~> 12.0"
|
data/README.adoc
CHANGED
|
@@ -1,9 +1,370 @@
|
|
|
1
|
-
=
|
|
1
|
+
= Mml: MathML parser and builder
|
|
2
|
+
|
|
3
|
+
:toc:
|
|
4
|
+
:toclevels: 2
|
|
2
5
|
|
|
3
6
|
== Purpose
|
|
4
7
|
|
|
5
|
-
Mml
|
|
8
|
+
Mml provides MathML 3 and MathML 4 XML parsing and serialization for Ruby. It maps
|
|
9
|
+
the full MathML element set into Ruby model classes using the
|
|
10
|
+
https://github.com/lutaml/lutaml-model[lutaml-model] framework and is used by
|
|
11
|
+
https://github.com/plurimath/plurimath[Plurimath] for mathematical formula
|
|
12
|
+
representation.
|
|
13
|
+
|
|
14
|
+
Key features:
|
|
15
|
+
|
|
16
|
+
* **Dual MathML version support**: Separate class hierarchies for MathML 3 and
|
|
17
|
+
MathML 4 with explicit version selection
|
|
18
|
+
* **Round-trip fidelity**: Parse XML to an object graph, modify, and serialize back
|
|
19
|
+
* **Namespace handling**: Default `xmlns`, prefixed `mml:`, and namespace-less input
|
|
20
|
+
* **Opal support**: Runs in the browser via Ruby-to-JavaScript compilation
|
|
21
|
+
|
|
22
|
+
== Installation
|
|
23
|
+
|
|
24
|
+
[source,ruby]
|
|
25
|
+
----
|
|
26
|
+
gem 'mml'
|
|
27
|
+
----
|
|
28
|
+
|
|
29
|
+
[source,bash]
|
|
30
|
+
----
|
|
31
|
+
$ bundle install
|
|
32
|
+
# or
|
|
33
|
+
$ gem install mml
|
|
34
|
+
----
|
|
35
|
+
|
|
36
|
+
== Quick start
|
|
37
|
+
|
|
38
|
+
[source,ruby]
|
|
39
|
+
----
|
|
40
|
+
require "mml"
|
|
41
|
+
|
|
42
|
+
# Parse MathML (defaults to MathML 3)
|
|
43
|
+
math = Mml.parse('<math xmlns="http://www.w3.org/1998/Math/MathML"><mi>x</mi></math>')
|
|
44
|
+
|
|
45
|
+
# Serialize back to XML
|
|
46
|
+
math.to_xml
|
|
47
|
+
# => "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>x</mi></math>"
|
|
48
|
+
|
|
49
|
+
# Parse with explicit version
|
|
50
|
+
math4 = Mml.parse(input, version: 4)
|
|
51
|
+
----
|
|
52
|
+
|
|
53
|
+
== MathML version architecture
|
|
54
|
+
|
|
55
|
+
Mml maintains two parallel class hierarchies under `Mml::V3` and `Mml::V4`.
|
|
56
|
+
Both versions share the same namespace URI (`http://www.w3.org/1998/Math/MathML`)
|
|
57
|
+
for backward compatibility.
|
|
58
|
+
|
|
59
|
+
[source]
|
|
60
|
+
----
|
|
61
|
+
┌───────────────────────────────────────────┐
|
|
62
|
+
│ Mml │
|
|
63
|
+
│ (aliases Mml::V3 for backward compat) │
|
|
64
|
+
└────────────────────┬──────────────────────┘
|
|
65
|
+
│
|
|
66
|
+
┌───────────────────┴────────────────────┐
|
|
67
|
+
│ │
|
|
68
|
+
┌────┴────┐ ┌────┴────┐
|
|
69
|
+
│ Mml::V3 │ │ Mml::V4 │
|
|
70
|
+
└────┬────┘ └────┬────┘
|
|
71
|
+
│ │
|
|
72
|
+
┌───────────────┼─────────────────────┐ ┌───────────────┼───────────────┐
|
|
73
|
+
│ ┌────────────┴───────────────┐ │ │ ┌────────────┴────────────┐ │
|
|
74
|
+
│ │ Element classes │ │ │ │ Element classes │ │
|
|
75
|
+
│ │ (Mi, Mn, Mo, Mrow, ...) │ │ │ │ (Mi, Mn, Mo, Mrow, ...) │ │
|
|
76
|
+
│ │ │ │ │ │ + intent, arg, │ │
|
|
77
|
+
│ │ Inherits from │ │ │ │ displaystyle, │ │
|
|
78
|
+
│ │ Lutaml::Model::Serializable│ │ │ │ scriptlevel │ │
|
|
79
|
+
│ └────────────┬───────────────┘ │ │ │ + <a> element │ │
|
|
80
|
+
│ │ │ │ └────────────┬────────────┘ │
|
|
81
|
+
│ ┌────────────┴────────────┐ │ │ ┌────────────┴────────────┐ │
|
|
82
|
+
│ │ CommonAttributes │ │ │ │ CommonAttributes │ │
|
|
83
|
+
│ │ (child element mixin) │ │ │ │ (v4 version) │ │
|
|
84
|
+
│ └─────────────────────────┘ │ | └─────────────────────────┘ |
|
|
85
|
+
└─────────────────────────────────────┘ └───────────────────────────────┘
|
|
86
|
+
│
|
|
87
|
+
┌──────────────────┴──────────────────────┐
|
|
88
|
+
│ Lutaml::Model::Serializable │
|
|
89
|
+
│ (XML mapping framework) │
|
|
90
|
+
└─────────────────────────────────────────┘
|
|
91
|
+
----
|
|
92
|
+
|
|
93
|
+
=== Version selection
|
|
94
|
+
|
|
95
|
+
[source,ruby]
|
|
96
|
+
----
|
|
97
|
+
Mml.parse(input) # Default: MathML 3 (Mml::V3)
|
|
98
|
+
Mml.parse(input, version: 3) # Explicit MathML 3
|
|
99
|
+
Mml.parse(input, version: 4) # MathML 4 with intent/arg attributes
|
|
100
|
+
Mml::V4.parse(input) # Direct v4 parsing (no default fallback)
|
|
101
|
+
----
|
|
102
|
+
|
|
103
|
+
=== Key differences between MathML 3 and MathML 4
|
|
104
|
+
|
|
105
|
+
[cols="1,2",options="header"]
|
|
106
|
+
|===
|
|
107
|
+
|Feature |MathML 4 additions
|
|
108
|
+
|Universal attributes |`intent`, `arg`, `displaystyle`, `scriptlevel` available on all presentation elements
|
|
109
|
+
|New element |`<a>` hyperlink element with `href`, `hreflang`
|
|
110
|
+
|Deprecated (not serialized) a|
|
|
111
|
+
* `fontfamily`, `fontweight`, `fontstyle`, `fontsize`, `color`, `background` on `mstyle`, `mglyph`, `mspace`
|
|
112
|
+
* `groupalign` on `mtable`, `mtr`, `mlabeledtr`
|
|
113
|
+
* `fence`, `separator` on `mo`
|
|
114
|
+
|Deprecated (recognized but hidden) |`<mlabeledtr>`, `<none>` removed from `CommonAttributes` but classes still exist
|
|
115
|
+
|===
|
|
116
|
+
|
|
117
|
+
=== Migration from MathML 3 to MathML 4
|
|
118
|
+
|
|
119
|
+
==== For gem users (upgrading parsing)
|
|
120
|
+
|
|
121
|
+
If you currently parse MathML and want to use MathML 4 features:
|
|
122
|
+
|
|
123
|
+
[source,ruby]
|
|
124
|
+
----
|
|
125
|
+
# Change this:
|
|
126
|
+
math = Mml.parse(input)
|
|
127
|
+
|
|
128
|
+
# To this:
|
|
129
|
+
math = Mml.parse(input, version: 4)
|
|
130
|
+
----
|
|
131
|
+
|
|
132
|
+
==== For gem users (upgrading serialized output)
|
|
133
|
+
|
|
134
|
+
If you serialize MathML 4 documents and want to ensure compatibility:
|
|
135
|
+
|
|
136
|
+
[source,ruby]
|
|
137
|
+
----
|
|
138
|
+
# MathML 4 serialization removes deprecated attributes from XML output
|
|
139
|
+
math = Mml.parse(input, version: 4)
|
|
140
|
+
math.to_xml # No fontfamily, fontweight, color, groupalign, etc. in output
|
|
141
|
+
----
|
|
142
|
+
|
|
143
|
+
==== For gem extenders (adding custom elements)
|
|
144
|
+
|
|
145
|
+
Custom elements registered via `Configuration.custom_models` are version-specific:
|
|
146
|
+
|
|
147
|
+
[source,ruby]
|
|
148
|
+
----
|
|
149
|
+
# Register a custom element for MathML 4 only
|
|
150
|
+
Mml::V4::Configuration.custom_models = { Mi => MyCustomMiV4 }
|
|
151
|
+
----
|
|
152
|
+
|
|
153
|
+
CommonAttributes is version-specific. Elements that exist only in v4 (like `<a>`)
|
|
154
|
+
are automatically handled:
|
|
155
|
+
|
|
156
|
+
[source,ruby]
|
|
157
|
+
----
|
|
158
|
+
# The <a> element is only in v4 CommonAttributes
|
|
159
|
+
Mml::V4::Mrow.new(a_value: [Mml::V4::A.new(href: "https://...")])
|
|
160
|
+
----
|
|
161
|
+
|
|
162
|
+
== Parsing and serialization
|
|
163
|
+
|
|
164
|
+
=== Parsing
|
|
165
|
+
|
|
166
|
+
[source,ruby]
|
|
167
|
+
----
|
|
168
|
+
# Default namespace
|
|
169
|
+
Mml.parse('<math xmlns="http://www.w3.org/1998/Math/MathML"><mi>x</mi></math>')
|
|
170
|
+
|
|
171
|
+
# Prefixed namespace
|
|
172
|
+
Mml.parse('<mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML"><mml:mi>x</mml:mi></mml:math>')
|
|
173
|
+
|
|
174
|
+
# No namespace (namespace injected internally)
|
|
175
|
+
Mml.parse("<math><mi>x</mi></math>", namespace_exist: false)
|
|
176
|
+
----
|
|
177
|
+
|
|
178
|
+
=== Serialization
|
|
179
|
+
|
|
180
|
+
[source,ruby]
|
|
181
|
+
----
|
|
182
|
+
math.to_xml
|
|
183
|
+
# => "<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><mi>x</mi></math>"
|
|
184
|
+
|
|
185
|
+
math.to_xml(prefix: true)
|
|
186
|
+
# => "<mml:math xmlns:mml=\"http://www.w3.org/1998/Math/MathML\"><mml:mi>x</mml:mi></mml:math>"
|
|
187
|
+
|
|
188
|
+
math.to_xml(declaration: false)
|
|
189
|
+
# => "<math xmlns=\"...\"><mi>x</mi></math>"
|
|
190
|
+
----
|
|
191
|
+
|
|
192
|
+
=== Round-trip (parse, modify, serialize)
|
|
193
|
+
|
|
194
|
+
[source,ruby]
|
|
195
|
+
----
|
|
196
|
+
math = Mml.parse('<math xmlns="http://www.w3.org/1998/Math/MathML"><mi>x</mi></math>')
|
|
197
|
+
math.display = "block"
|
|
198
|
+
math.to_xml
|
|
199
|
+
# => "<math xmlns=\"http://www.w3.org/1998/Math/MathML\" display=\"block\"><mi>x</mi></math>"
|
|
200
|
+
----
|
|
201
|
+
|
|
202
|
+
== Element reference
|
|
203
|
+
|
|
204
|
+
=== Element types
|
|
205
|
+
|
|
206
|
+
*Token elements*: `mi`, `mn`, `mo`, `ms`, `mtext`, `mspace`, `mglyph`
|
|
207
|
+
|
|
208
|
+
*General layout*: `mrow`, `mfrac`, `msqrt`, `mroot`, `mstyle`, `merror`, `mpadded`, `mphantom`, `mfenced`, `menclose`, `maction`
|
|
209
|
+
|
|
210
|
+
*Script elements*: `msub`, `msup`, `msubsup`, `munder`, `mover`, `munderover`, `mmultiscripts`, `mprescripts`
|
|
211
|
+
|
|
212
|
+
*Table elements*: `mtable`, `mtr`, `mtd`
|
|
213
|
+
|
|
214
|
+
*Row and stack elements*: `mstack`, `msrow`, `mscarries`, `mscarry`, `msline`, `msgroup`, `mlongdiv`
|
|
215
|
+
|
|
216
|
+
*Semantic elements*: `mfraction`, `semantics`
|
|
217
|
+
|
|
218
|
+
*v4 only*: `a` (hyperlink)
|
|
219
|
+
|
|
220
|
+
*Deprecated*: `mlabeledtr`, `none` (classes exist but hidden from CommonAttributes in v4)
|
|
221
|
+
|
|
222
|
+
=== Token elements (leaf nodes)
|
|
223
|
+
|
|
224
|
+
Token elements hold text content in the `value` attribute:
|
|
225
|
+
|
|
226
|
+
[source,ruby]
|
|
227
|
+
----
|
|
228
|
+
Mml::Mi.new(value: "x")
|
|
229
|
+
Mml::Mn.new(value: "42")
|
|
230
|
+
Mml::Mo.new(value: "+")
|
|
231
|
+
Mml::Ms.new(value: "text")
|
|
232
|
+
Mml::Mtext.new(value: "label")
|
|
233
|
+
Mml::Mspace.new(width: "1em")
|
|
234
|
+
Mml::Mglyph.new(alt: "symbol")
|
|
235
|
+
----
|
|
236
|
+
|
|
237
|
+
=== Container elements
|
|
238
|
+
|
|
239
|
+
Container elements hold child elements via `#{tag}_value` collection attributes:
|
|
240
|
+
|
|
241
|
+
[source,ruby]
|
|
242
|
+
----
|
|
243
|
+
Mml::Mrow.new(
|
|
244
|
+
mi_value: [Mml::Mi.new(value: "x")],
|
|
245
|
+
mo_value: [Mml::Mo.new(value: "+")],
|
|
246
|
+
mn_value: [Mml::Mn.new(value: "1")],
|
|
247
|
+
)
|
|
248
|
+
# => <mrow><mi>x</mi><mo>+</mo><mn>1</mn></mrow>
|
|
249
|
+
----
|
|
250
|
+
|
|
251
|
+
=== Composing expressions
|
|
252
|
+
|
|
253
|
+
Build an expression tree by nesting elements:
|
|
254
|
+
|
|
255
|
+
[source,ruby]
|
|
256
|
+
----
|
|
257
|
+
Mml::Math.new(
|
|
258
|
+
mfrac_value: [
|
|
259
|
+
Mml::Mfrac.new(
|
|
260
|
+
mi_value: [Mml::Mi.new(value: "a"), Mml::Mi.new(value: "b")],
|
|
261
|
+
),
|
|
262
|
+
],
|
|
263
|
+
)
|
|
264
|
+
# => <math><mfrac><mi>a</mi><mi>b</mi></mfrac></math>
|
|
265
|
+
----
|
|
266
|
+
|
|
267
|
+
=== Tables
|
|
268
|
+
|
|
269
|
+
[source,ruby]
|
|
270
|
+
----
|
|
271
|
+
Mml::Mtable.new(
|
|
272
|
+
mtr_value: [
|
|
273
|
+
Mml::Mtr.new(
|
|
274
|
+
mtd_value: [
|
|
275
|
+
Mml::Mtd.new(mi_value: [Mml::Mi.new(value: "a")]),
|
|
276
|
+
Mml::Mtd.new(mi_value: [Mml::Mi.new(value: "b")]),
|
|
277
|
+
],
|
|
278
|
+
),
|
|
279
|
+
],
|
|
280
|
+
)
|
|
281
|
+
----
|
|
282
|
+
|
|
283
|
+
=== Hyperlinks (MathML 4 only)
|
|
284
|
+
|
|
285
|
+
[source,ruby]
|
|
286
|
+
----
|
|
287
|
+
Mml::V4::A.new(
|
|
288
|
+
href: "https://example.com",
|
|
289
|
+
hreflang: "en",
|
|
290
|
+
mi_value: [Mml::V4::Mi.new(value: "click")]
|
|
291
|
+
)
|
|
292
|
+
# => <a href="https://example.com" hreflang="en"><mi>click</mi></a>
|
|
293
|
+
----
|
|
294
|
+
|
|
295
|
+
== Internal architecture
|
|
296
|
+
|
|
297
|
+
=== Element class patterns
|
|
298
|
+
|
|
299
|
+
All element classes inherit from `Lutaml::Model::Serializable`:
|
|
300
|
+
|
|
301
|
+
* *Leaf elements*: use `map_content to: :value` for text content
|
|
302
|
+
* *Container elements*: use `mixed_content` for child elements
|
|
303
|
+
|
|
304
|
+
[source,ruby]
|
|
305
|
+
----
|
|
306
|
+
# Leaf — text content
|
|
307
|
+
class Mi < Lutaml::Model::Serializable
|
|
308
|
+
attribute :value, :string
|
|
309
|
+
xml do
|
|
310
|
+
element "mi"
|
|
311
|
+
map_content to: :value
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Container — child elements
|
|
316
|
+
class Mrow < Lutaml::Model::Serializable
|
|
317
|
+
xml do
|
|
318
|
+
element "mrow"
|
|
319
|
+
mixed_content
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
----
|
|
323
|
+
|
|
324
|
+
=== CommonAttributes
|
|
325
|
+
|
|
326
|
+
Container elements that accept arbitrary MathML children import `CommonAttributes`,
|
|
327
|
+
which defines `#{tag}_value` collection attributes for all supported child elements.
|
|
328
|
+
The list of classes that receive this mixin is in
|
|
329
|
+
`Configuration::COMMON_ATTRIBUTES_CLASSES`.
|
|
330
|
+
|
|
331
|
+
=== Namespace
|
|
332
|
+
|
|
333
|
+
All elements use the MathML namespace URI (`http://www.w3.org/1998/Math/MathML`).
|
|
334
|
+
Three input forms are supported:
|
|
335
|
+
|
|
336
|
+
* Default namespace: `<math xmlns="http://www.w3.org/1998/Math/MathML">`
|
|
337
|
+
* Prefixed: `<mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML">`
|
|
338
|
+
* No namespace: namespace is injected before parsing when `namespace_exist: false`
|
|
339
|
+
|
|
340
|
+
== Configuration
|
|
341
|
+
|
|
342
|
+
[source,ruby]
|
|
343
|
+
----
|
|
344
|
+
# Switch XML adapter (default: :ox, also supports :nokogiri)
|
|
345
|
+
Mml::Configuration.adapter = :nokogiri
|
|
346
|
+
|
|
347
|
+
# Register custom model replacements
|
|
348
|
+
Mml::Configuration.custom_models = { Mi => MyCustomMi }
|
|
349
|
+
----
|
|
350
|
+
|
|
351
|
+
== Development
|
|
352
|
+
|
|
353
|
+
[source,bash]
|
|
354
|
+
----
|
|
355
|
+
rake # Run specs + rubocop
|
|
356
|
+
bundle exec rspec # Run tests
|
|
357
|
+
bundle exec rubocop # Lint
|
|
358
|
+
bin/console # Interactive IRB
|
|
359
|
+
----
|
|
360
|
+
|
|
361
|
+
== Contributing
|
|
362
|
+
|
|
363
|
+
Bug reports and pull requests are welcome on GitHub at
|
|
364
|
+
https://github.com/plurimath/mml.
|
|
365
|
+
|
|
366
|
+
== Copyright and license
|
|
6
367
|
|
|
7
|
-
|
|
368
|
+
Copyright Ribose Inc.
|
|
8
369
|
|
|
9
|
-
|
|
370
|
+
https://opensource.org/licenses/BSD-2-Clause[BSD-2-Clause License].
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mml
|
|
4
|
+
module V3
|
|
5
|
+
Mml::V3::Configuration::SUPPORTED_TAGS.each do |tag|
|
|
6
|
+
autoload(tag.to_s.capitalize.to_sym, "mml/v3/#{tag}.rb")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class CommonAttributes < Lutaml::Model::Serializable
|
|
10
|
+
Mml::V3::Configuration::SUPPORTED_TAGS.each do |tag|
|
|
11
|
+
attribute :"#{tag}_value", Mml::V3.const_get(tag.to_s.capitalize),
|
|
12
|
+
collection: true
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
xml do
|
|
16
|
+
Mml::V3::Configuration::SUPPORTED_TAGS.each do |tag|
|
|
17
|
+
map_element tag, to: :"#{tag}_value"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|