mml 2.2.1 → 2.3.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.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +14 -4
  3. data/CLAUDE.md +79 -0
  4. data/README.adoc +166 -43
  5. data/lib/mml/base/deprecated_font_attributes.rb +31 -0
  6. data/lib/mml/base/maction.rb +28 -0
  7. data/lib/mml/base/maligngroup.rb +26 -0
  8. data/lib/mml/base/malignmark.rb +26 -0
  9. data/lib/mml/base/math.rb +23 -0
  10. data/lib/mml/base/menclose.rb +27 -0
  11. data/lib/mml/base/merror.rb +25 -0
  12. data/lib/mml/base/mfenced.rb +34 -0
  13. data/lib/mml/base/mfrac.rb +33 -0
  14. data/lib/mml/base/mfraction.rb +33 -0
  15. data/lib/mml/base/mglyph.rb +42 -0
  16. data/lib/mml/base/mi.rb +32 -0
  17. data/lib/mml/base/mlabeledtr.rb +37 -0
  18. data/lib/mml/base/mlongdiv.rb +31 -0
  19. data/lib/mml/base/mmultiscripts.rb +31 -0
  20. data/lib/mml/base/mn.rb +32 -0
  21. data/lib/mml/base/mo.rb +76 -0
  22. data/lib/mml/base/mover.rb +29 -0
  23. data/lib/mml/base/mpadded.rb +35 -0
  24. data/lib/mml/base/mphantom.rb +25 -0
  25. data/lib/mml/base/mprescripts.rb +24 -0
  26. data/lib/mml/base/mroot.rb +25 -0
  27. data/lib/mml/base/mrow.rb +29 -0
  28. data/lib/mml/base/ms.rb +37 -0
  29. data/lib/mml/base/mscarries.rb +33 -0
  30. data/lib/mml/base/mscarry.rb +29 -0
  31. data/lib/mml/base/msgroup.rb +31 -0
  32. data/lib/mml/base/msline.rb +34 -0
  33. data/lib/mml/base/mspace.rb +52 -0
  34. data/lib/mml/base/msqrt.rb +25 -0
  35. data/lib/mml/base/msrow.rb +27 -0
  36. data/lib/mml/base/mstack.rb +33 -0
  37. data/lib/mml/base/mstyle.rb +189 -0
  38. data/lib/mml/base/msub.rb +27 -0
  39. data/lib/mml/base/msubsup.rb +29 -0
  40. data/lib/mml/base/msup.rb +27 -0
  41. data/lib/mml/base/mtable.rb +57 -0
  42. data/lib/mml/base/mtd.rb +29 -0
  43. data/lib/mml/base/mtext.rb +32 -0
  44. data/lib/mml/base/mtr.rb +35 -0
  45. data/lib/mml/base/munder.rb +31 -0
  46. data/lib/mml/base/munderover.rb +31 -0
  47. data/lib/mml/base/none.rb +24 -0
  48. data/lib/mml/base/semantics.rb +23 -0
  49. data/lib/mml/base/v3_only/operator_attrs.rb +24 -0
  50. data/lib/mml/base/v3_only/style_attrs.rb +31 -0
  51. data/lib/mml/base/v3_only/table_attrs.rb +28 -0
  52. data/lib/mml/base/v3_only.rb +11 -0
  53. data/lib/mml/base/v4_attributes.rb +30 -0
  54. data/lib/mml/base.rb +51 -0
  55. data/lib/mml/common_elements.rb +85 -0
  56. data/lib/mml/context_configuration.rb +118 -0
  57. data/lib/mml/context_options.rb +64 -0
  58. data/lib/mml/namespace.rb +10 -0
  59. data/lib/mml/v3/common_elements.rb +8 -0
  60. data/lib/mml/v3/configuration.rb +4 -96
  61. data/lib/mml/v3/maction.rb +2 -14
  62. data/lib/mml/v3/maligngroup.rb +2 -12
  63. data/lib/mml/v3/malignmark.rb +2 -12
  64. data/lib/mml/v3/math.rb +3 -10
  65. data/lib/mml/v3/menclose.rb +3 -14
  66. data/lib/mml/v3/merror.rb +3 -12
  67. data/lib/mml/v3/mfenced.rb +3 -21
  68. data/lib/mml/v3/mfrac.rb +3 -20
  69. data/lib/mml/v3/mfraction.rb +3 -20
  70. data/lib/mml/v3/mglyph.rb +3 -38
  71. data/lib/mml/v3/mi.rb +3 -30
  72. data/lib/mml/v3/mlabeledtr.rb +2 -23
  73. data/lib/mml/v3/mlongdiv.rb +3 -18
  74. data/lib/mml/v3/mmultiscripts.rb +3 -20
  75. data/lib/mml/v3/mn.rb +3 -30
  76. data/lib/mml/v3/mo.rb +4 -78
  77. data/lib/mml/v3/mover.rb +3 -16
  78. data/lib/mml/v3/mpadded.rb +3 -22
  79. data/lib/mml/v3/mphantom.rb +3 -12
  80. data/lib/mml/v3/mprescripts.rb +2 -10
  81. data/lib/mml/v3/mroot.rb +3 -12
  82. data/lib/mml/v3/mrow.rb +3 -18
  83. data/lib/mml/v3/ms.rb +4 -36
  84. data/lib/mml/v3/mscarries.rb +3 -20
  85. data/lib/mml/v3/mscarry.rb +3 -16
  86. data/lib/mml/v3/msgroup.rb +3 -18
  87. data/lib/mml/v3/msline.rb +2 -20
  88. data/lib/mml/v3/mspace.rb +3 -50
  89. data/lib/mml/v3/msqrt.rb +3 -12
  90. data/lib/mml/v3/msrow.rb +3 -14
  91. data/lib/mml/v3/mstack.rb +3 -20
  92. data/lib/mml/v3/mstyle.rb +5 -204
  93. data/lib/mml/v3/msub.rb +3 -14
  94. data/lib/mml/v3/msubsup.rb +3 -16
  95. data/lib/mml/v3/msup.rb +3 -14
  96. data/lib/mml/v3/mtable.rb +3 -53
  97. data/lib/mml/v3/mtd.rb +3 -16
  98. data/lib/mml/v3/mtext.rb +3 -30
  99. data/lib/mml/v3/mtr.rb +2 -21
  100. data/lib/mml/v3/munder.rb +3 -18
  101. data/lib/mml/v3/munderover.rb +3 -18
  102. data/lib/mml/v3/namespace.rb +1 -4
  103. data/lib/mml/v3/none.rb +2 -10
  104. data/lib/mml/v3/semantics.rb +3 -12
  105. data/lib/mml/v3.rb +51 -77
  106. data/lib/mml/v4/a.rb +4 -13
  107. data/lib/mml/v4/common_elements.rb +13 -0
  108. data/lib/mml/v4/configuration.rb +4 -97
  109. data/lib/mml/v4/maction.rb +4 -19
  110. data/lib/mml/v4/maligngroup.rb +4 -17
  111. data/lib/mml/v4/malignmark.rb +4 -17
  112. data/lib/mml/v4/math.rb +4 -14
  113. data/lib/mml/v4/menclose.rb +4 -18
  114. data/lib/mml/v4/merror.rb +4 -16
  115. data/lib/mml/v4/mfenced.rb +4 -25
  116. data/lib/mml/v4/mfrac.rb +4 -24
  117. data/lib/mml/v4/mfraction.rb +4 -20
  118. data/lib/mml/v4/mglyph.rb +4 -35
  119. data/lib/mml/v4/mi.rb +4 -30
  120. data/lib/mml/v4/mlabeledtr.rb +6 -23
  121. data/lib/mml/v4/mlongdiv.rb +4 -18
  122. data/lib/mml/v4/mmultiscripts.rb +4 -24
  123. data/lib/mml/v4/mn.rb +4 -29
  124. data/lib/mml/v4/mo.rb +4 -75
  125. data/lib/mml/v4/mover.rb +4 -20
  126. data/lib/mml/v4/mpadded.rb +4 -26
  127. data/lib/mml/v4/mphantom.rb +4 -16
  128. data/lib/mml/v4/mprescripts.rb +4 -11
  129. data/lib/mml/v4/mroot.rb +4 -16
  130. data/lib/mml/v4/mrow.rb +4 -20
  131. data/lib/mml/v4/ms.rb +4 -34
  132. data/lib/mml/v4/mscarries.rb +4 -20
  133. data/lib/mml/v4/mscarry.rb +4 -16
  134. data/lib/mml/v4/msgroup.rb +4 -18
  135. data/lib/mml/v4/msline.rb +4 -21
  136. data/lib/mml/v4/mspace.rb +4 -49
  137. data/lib/mml/v4/msqrt.rb +4 -16
  138. data/lib/mml/v4/msrow.rb +4 -18
  139. data/lib/mml/v4/mstack.rb +4 -24
  140. data/lib/mml/v4/mstyle.rb +4 -186
  141. data/lib/mml/v4/msub.rb +4 -18
  142. data/lib/mml/v4/msubsup.rb +4 -20
  143. data/lib/mml/v4/msup.rb +4 -18
  144. data/lib/mml/v4/mtable.rb +4 -55
  145. data/lib/mml/v4/mtd.rb +4 -20
  146. data/lib/mml/v4/mtext.rb +4 -29
  147. data/lib/mml/v4/mtr.rb +4 -25
  148. data/lib/mml/v4/munder.rb +4 -22
  149. data/lib/mml/v4/munderover.rb +4 -22
  150. data/lib/mml/v4/namespace.rb +1 -4
  151. data/lib/mml/v4/none.rb +6 -11
  152. data/lib/mml/v4/semantics.rb +4 -12
  153. data/lib/mml/v4.rb +52 -74
  154. data/lib/mml/version.rb +1 -1
  155. data/lib/mml/versioned_parser.rb +46 -0
  156. data/lib/mml.rb +34 -6
  157. metadata +60 -4
  158. data/lib/mml/v3/common_attributes.rb +0 -22
  159. data/lib/mml/v4/common_attributes.rb +0 -26
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mml
4
+ module Base
5
+ module None
6
+ # NOTE: class_eval resolves constants in module's lexical scope.
7
+ # Use fully qualified names (e.g., Mml::Namespace).
8
+ def self.included(klass)
9
+ klass.class_eval do
10
+ attribute :mathcolor, :string
11
+ attribute :mathbackground, :string
12
+
13
+ xml do
14
+ namespace Mml::Namespace
15
+ element "none"
16
+
17
+ map_attribute "mathcolor", to: :mathcolor
18
+ map_attribute "mathbackground", to: :mathbackground
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mml
4
+ module Base
5
+ module Semantics
6
+ # NOTE: class_eval resolves constants in module's lexical scope.
7
+ # Use fully qualified names (e.g., Mml::Namespace).
8
+ def self.included(klass)
9
+ klass.class_eval do
10
+ attribute :annotation, :mi, collection: true
11
+
12
+ xml do
13
+ namespace Mml::Namespace
14
+ element "semantics"
15
+ mixed_content
16
+
17
+ map_element :annotation, to: :annotation
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mml
4
+ module Base
5
+ module V3Only
6
+ # Operator attributes removed in MathML 4: fence, separator.
7
+ # These are valid in mathml4-legacy schema only.
8
+ module OperatorAttributes
9
+ def self.included(klass)
10
+ klass.class_eval do
11
+ attribute :fence, :string
12
+ attribute :separator, :string
13
+
14
+ xml do
15
+ namespace Mml::Namespace
16
+ map_attribute "fence", to: :fence
17
+ map_attribute "separator", to: :separator
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mml
4
+ module Base
5
+ module V3Only
6
+ # Style attributes removed in MathML 4.
7
+ # fence, separator: removed from <mo> default schema.
8
+ # groupalign, side, minlabelspacing: removed with mlabeledtr.
9
+ module StyleAttributes
10
+ def self.included(klass)
11
+ klass.class_eval do
12
+ attribute :fence, :string
13
+ attribute :groupalign, :string
14
+ attribute :separator, :string
15
+ attribute :side, :string
16
+ attribute :minlabelspacing, :string
17
+
18
+ xml do
19
+ namespace Mml::Namespace
20
+ map_attribute "fence", to: :fence
21
+ map_attribute "groupalign", to: :groupalign
22
+ map_attribute "separator", to: :separator
23
+ map_attribute "side", to: :side
24
+ map_attribute "minlabelspacing", to: :minlabelspacing
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mml
4
+ module Base
5
+ module V3Only
6
+ # Table attributes removed in MathML 4: groupalign, side, minlabelspacing.
7
+ # groupalign: no longer supported per spec.
8
+ # side, minlabelspacing: removed with mlabeledtr per spec.
9
+ # These are valid in mathml4-legacy schema only.
10
+ module TableAttributes
11
+ def self.included(klass)
12
+ klass.class_eval do
13
+ attribute :groupalign, :string
14
+ attribute :side, :string
15
+ attribute :minlabelspacing, :string
16
+
17
+ xml do
18
+ namespace Mml::Namespace
19
+ map_attribute "groupalign", to: :groupalign
20
+ map_attribute "side", to: :side
21
+ map_attribute "minlabelspacing", to: :minlabelspacing
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mml
4
+ module Base
5
+ module V3Only
6
+ autoload :OperatorAttributes, "#{__dir__}/v3_only/operator_attrs"
7
+ autoload :TableAttributes, "#{__dir__}/v3_only/table_attrs"
8
+ autoload :StyleAttributes, "#{__dir__}/v3_only/style_attrs"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mml
4
+ module Base
5
+ # Universal MathML 4 attributes (V4-only, not in V3).
6
+ # intent, arg, displaystyle, scriptlevel, mathcolor, mathbackground.
7
+ module V4Attributes
8
+ def self.included(klass)
9
+ klass.class_eval do
10
+ attribute :intent, :string
11
+ attribute :arg, :string
12
+ attribute :displaystyle, :string
13
+ attribute :scriptlevel, :integer
14
+ attribute :mathcolor, :string
15
+ attribute :mathbackground, :string
16
+
17
+ xml do
18
+ namespace Mml::Namespace
19
+ map_attribute "intent", to: :intent
20
+ map_attribute "arg", to: :arg
21
+ map_attribute "displaystyle", to: :displaystyle
22
+ map_attribute "scriptlevel", to: :scriptlevel
23
+ map_attribute "mathcolor", to: :mathcolor
24
+ map_attribute "mathbackground", to: :mathbackground
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
data/lib/mml/base.rb ADDED
@@ -0,0 +1,51 @@
1
+ module Mml
2
+ module Base
3
+ autoload :Maction, "#{__dir__}/base/maction"
4
+ autoload :Maligngroup, "#{__dir__}/base/maligngroup"
5
+ autoload :Malignmark, "#{__dir__}/base/malignmark"
6
+ autoload :Math, "#{__dir__}/base/math"
7
+ autoload :Menclose, "#{__dir__}/base/menclose"
8
+ autoload :Merror, "#{__dir__}/base/merror"
9
+ autoload :Mfenced, "#{__dir__}/base/mfenced"
10
+ autoload :Mfrac, "#{__dir__}/base/mfrac"
11
+ autoload :Mfraction, "#{__dir__}/base/mfraction"
12
+ autoload :Mglyph, "#{__dir__}/base/mglyph"
13
+ autoload :Mi, "#{__dir__}/base/mi"
14
+ autoload :Mlabeledtr, "#{__dir__}/base/mlabeledtr"
15
+ autoload :Mlongdiv, "#{__dir__}/base/mlongdiv"
16
+ autoload :Mmultiscripts, "#{__dir__}/base/mmultiscripts"
17
+ autoload :Mn, "#{__dir__}/base/mn"
18
+ autoload :Mo, "#{__dir__}/base/mo"
19
+ autoload :Mover, "#{__dir__}/base/mover"
20
+ autoload :Mpadded, "#{__dir__}/base/mpadded"
21
+ autoload :Mphantom, "#{__dir__}/base/mphantom"
22
+ autoload :Mprescripts, "#{__dir__}/base/mprescripts"
23
+ autoload :Mroot, "#{__dir__}/base/mroot"
24
+ autoload :Mrow, "#{__dir__}/base/mrow"
25
+ autoload :Ms, "#{__dir__}/base/ms"
26
+ autoload :Mscarries, "#{__dir__}/base/mscarries"
27
+ autoload :Mscarry, "#{__dir__}/base/mscarry"
28
+ autoload :Msgroup, "#{__dir__}/base/msgroup"
29
+ autoload :Msline, "#{__dir__}/base/msline"
30
+ autoload :Mspace, "#{__dir__}/base/mspace"
31
+ autoload :Msqrt, "#{__dir__}/base/msqrt"
32
+ autoload :Msrow, "#{__dir__}/base/msrow"
33
+ autoload :Mstack, "#{__dir__}/base/mstack"
34
+ autoload :Mstyle, "#{__dir__}/base/mstyle"
35
+ autoload :Msub, "#{__dir__}/base/msub"
36
+ autoload :Msubsup, "#{__dir__}/base/msubsup"
37
+ autoload :Msup, "#{__dir__}/base/msup"
38
+ autoload :Mtable, "#{__dir__}/base/mtable"
39
+ autoload :Mtd, "#{__dir__}/base/mtd"
40
+ autoload :Mtext, "#{__dir__}/base/mtext"
41
+ autoload :Mtr, "#{__dir__}/base/mtr"
42
+ autoload :Munder, "#{__dir__}/base/munder"
43
+ autoload :Munderover, "#{__dir__}/base/munderover"
44
+ autoload :None, "#{__dir__}/base/none"
45
+ autoload :Semantics, "#{__dir__}/base/semantics"
46
+ autoload :V4Attributes, "#{__dir__}/base/v4_attributes"
47
+ autoload :DeprecatedFontAttributes,
48
+ "#{__dir__}/base/deprecated_font_attributes"
49
+ autoload :V3Only, "#{__dir__}/base/v3_only"
50
+ end
51
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Mml
6
+ class CommonElements < Lutaml::Model::Serializable
7
+ attribute :mmultiscripts_value, :mmultiscripts, collection: true
8
+ attribute :maligngroup_value, :maligngroup, collection: true
9
+ attribute :malignmark_value, :malignmark, collection: true
10
+ attribute :munderover_value, :munderover, collection: true
11
+ attribute :semantics_value, :semantics, collection: true
12
+ attribute :mscarries_value, :mscarries, collection: true
13
+ attribute :mfraction_value, :mfraction, collection: true
14
+ attribute :mphantom_value, :mphantom, collection: true
15
+ attribute :menclose_value, :menclose, collection: true
16
+ attribute :mlongdiv_value, :mlongdiv, collection: true
17
+ attribute :mpadded_value, :mpadded, collection: true
18
+ attribute :msubsup_value, :msubsup, collection: true
19
+ attribute :mscarry_value, :mscarry, collection: true
20
+ attribute :mfenced_value, :mfenced, collection: true
21
+ attribute :msgroup_value, :msgroup, collection: true
22
+ attribute :mglyph_value, :mglyph, collection: true
23
+ attribute :mstack_value, :mstack, collection: true
24
+ attribute :munder_value, :munder, collection: true
25
+ attribute :mtable_value, :mtable, collection: true
26
+ attribute :mstyle_value, :mstyle, collection: true
27
+ attribute :mspace_value, :mspace, collection: true
28
+ attribute :msline_value, :msline, collection: true
29
+ attribute :merror_value, :merror, collection: true
30
+ attribute :msrow_value, :msrow, collection: true
31
+ attribute :mfrac_value, :mfrac, collection: true
32
+ attribute :mover_value, :mover, collection: true
33
+ attribute :mroot_value, :mroot, collection: true
34
+ attribute :mtext_value, :mtext, collection: true
35
+ attribute :msqrt_value, :msqrt, collection: true
36
+ attribute :none_value, :none, collection: true
37
+ attribute :mrow_value, :mrow, collection: true
38
+ attribute :msub_value, :msub, collection: true
39
+ attribute :msup_value, :msup, collection: true
40
+ attribute :mi_value, :mi, collection: true
41
+ attribute :mo_value, :mo, collection: true
42
+ attribute :mn_value, :mn, collection: true
43
+ attribute :ms_value, :ms, collection: true
44
+
45
+ xml do
46
+ map_element "mmultiscripts", to: :mmultiscripts_value
47
+ map_element "maligngroup", to: :maligngroup_value
48
+ map_element "malignmark", to: :malignmark_value
49
+ map_element "munderover", to: :munderover_value
50
+ map_element "semantics", to: :semantics_value
51
+ map_element "mscarries", to: :mscarries_value
52
+ map_element "mfraction", to: :mfraction_value
53
+ map_element "mphantom", to: :mphantom_value
54
+ map_element "menclose", to: :menclose_value
55
+ map_element "mlongdiv", to: :mlongdiv_value
56
+ map_element "mpadded", to: :mpadded_value
57
+ map_element "msubsup", to: :msubsup_value
58
+ map_element "mscarry", to: :mscarry_value
59
+ map_element "mfenced", to: :mfenced_value
60
+ map_element "msgroup", to: :msgroup_value
61
+ map_element "mglyph", to: :mglyph_value
62
+ map_element "mstack", to: :mstack_value
63
+ map_element "munder", to: :munder_value
64
+ map_element "mtable", to: :mtable_value
65
+ map_element "mstyle", to: :mstyle_value
66
+ map_element "mspace", to: :mspace_value
67
+ map_element "msline", to: :msline_value
68
+ map_element "merror", to: :merror_value
69
+ map_element "msrow", to: :msrow_value
70
+ map_element "mfrac", to: :mfrac_value
71
+ map_element "mover", to: :mover_value
72
+ map_element "mroot", to: :mroot_value
73
+ map_element "mtext", to: :mtext_value
74
+ map_element "msqrt", to: :msqrt_value
75
+ map_element "none", to: :none_value
76
+ map_element "mrow", to: :mrow_value
77
+ map_element "msub", to: :msub_value
78
+ map_element "msup", to: :msup_value
79
+ map_element "mi", to: :mi_value
80
+ map_element "mo", to: :mo_value
81
+ map_element "mn", to: :mn_value
82
+ map_element "ms", to: :ms_value
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mml
4
+ module ContextConfiguration
5
+ def context_id
6
+ self::CONTEXT_ID
7
+ end
8
+
9
+ # Expose the version's built-in context without mutating global state.
10
+ def context
11
+ Lutaml::Model::GlobalContext.context(context_id)
12
+ end
13
+
14
+ # Create the built-in context or a derived context with substitutions.
15
+ def create_context(
16
+ id:,
17
+ registry: nil,
18
+ fallback_to: [context_id],
19
+ substitutions: []
20
+ )
21
+ normalized_id = Mml::ContextOptions.normalize_context_reference(id)
22
+
23
+ return populate_context! if normalized_id == context_id
24
+
25
+ Lutaml::Model::GlobalContext.unregister_context(normalized_id) if Lutaml::Model::GlobalContext.context(normalized_id)
26
+ create_type_context(
27
+ id: normalized_id,
28
+ registry: registry || Lutaml::Model::TypeRegistry.new,
29
+ fallback_to: normalize_fallbacks(fallback_to),
30
+ substitutions: substitutions,
31
+ )
32
+ end
33
+
34
+ # Explicitly rebuild the built-in version context.
35
+ def populate_context!
36
+ Lutaml::Model::GlobalContext.unregister_context(context_id) if context
37
+ register_models_in(base_type_context)
38
+ end
39
+
40
+ # Register a model now and remember it for later rebuilds.
41
+ def register_model(klass, id:)
42
+ normalized_id = id.to_sym
43
+ registered_models[normalized_id] = klass
44
+ (context || populate_base_context).registry.register(normalized_id, klass)
45
+ clear_cache(klass)
46
+ klass
47
+ end
48
+
49
+ def register
50
+ Mml::ContextOptions.warn_register_deprecation("#{name}.register")
51
+ @deprecated_register_context_id || context_id
52
+ end
53
+
54
+ def register=(value)
55
+ Mml::ContextOptions.warn_register_deprecation("#{name}.register=")
56
+ @deprecated_register_context_id =
57
+ Mml::ContextOptions.normalize_context_reference(value)
58
+ create_context(id: @deprecated_register_context_id) unless Lutaml::Model::GlobalContext.context(@deprecated_register_context_id)
59
+ end
60
+
61
+ def adapter
62
+ Lutaml::Model::Config.xml_adapter_type
63
+ end
64
+
65
+ def adapter=(adapter)
66
+ Lutaml::Model::Config.xml_adapter_type = adapter
67
+ end
68
+
69
+ private
70
+
71
+ def populate_base_context
72
+ base_type_context
73
+ end
74
+
75
+ def create_type_context(id:, registry:, fallback_to:, substitutions: [])
76
+ Lutaml::Model::GlobalContext.create_context(
77
+ id: id,
78
+ registry: registry,
79
+ fallback_to: fallback_to,
80
+ substitutions: substitutions,
81
+ ).tap do
82
+ Lutaml::Model::GlobalContext.clear_caches
83
+ end
84
+ end
85
+
86
+ def base_type_context
87
+ create_type_context(
88
+ id: context_id,
89
+ registry: Lutaml::Model::TypeRegistry.new,
90
+ fallback_to: [:default],
91
+ )
92
+ end
93
+
94
+ def register_models_in(type_context)
95
+ registered_models.each do |model_id, klass|
96
+ type_context.registry.register(model_id, klass)
97
+ clear_cache(klass)
98
+ end
99
+
100
+ Lutaml::Model::GlobalContext.clear_caches
101
+ type_context
102
+ end
103
+
104
+ def normalize_fallbacks(fallback_to)
105
+ Array(fallback_to).map do |fallback|
106
+ Mml::ContextOptions.normalize_context_reference(fallback)
107
+ end
108
+ end
109
+
110
+ def registered_models
111
+ @registered_models ||= {}
112
+ end
113
+
114
+ def clear_cache(klass)
115
+ klass.clear_cache(context_id) if klass.respond_to?(:clear_cache)
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mml
4
+ module ContextOptions
5
+ extend self
6
+
7
+ # Normalize the public `context:` / `register:` options into one context id.
8
+ def normalize_context_option(
9
+ context:,
10
+ register:,
11
+ default_context:,
12
+ warning_source:
13
+ )
14
+ raise_if_conflicting_context_options!(context, register)
15
+
16
+ if register
17
+ return normalize_register_option(
18
+ register,
19
+ default_context,
20
+ warning_source,
21
+ )
22
+ end
23
+
24
+ return default_context unless context_specified?(context)
25
+
26
+ normalize_context_reference(context) || default_context
27
+ end
28
+
29
+ # Collapse supported references to the symbol id MML uses internally.
30
+ def normalize_context_reference(reference)
31
+ return nil if reference.nil?
32
+ return reference if reference.is_a?(Symbol)
33
+ return reference.to_sym if reference.is_a?(String)
34
+ return reference.id.to_sym if reference.respond_to?(:id)
35
+
36
+ raise ArgumentError,
37
+ "Unsupported context/register reference: #{reference.inspect}"
38
+ end
39
+
40
+ # Centralize the compatibility warning for parse/configuration callers.
41
+ def warn_register_deprecation(source)
42
+ warn "[Mml] `register` is deprecated in #{source}; use `context` instead."
43
+ end
44
+
45
+ private
46
+
47
+ def context_specified?(context)
48
+ !context.equal?(Mml::UNSPECIFIED_CONTEXT)
49
+ end
50
+
51
+ # MML accepts the old `register:` alias, but never both inputs at once.
52
+ def raise_if_conflicting_context_options!(context, register)
53
+ return unless context_specified?(context) && register
54
+
55
+ raise ArgumentError, "Use either `context` or `register`, not both"
56
+ end
57
+
58
+ # Keep the compatibility path in one place.
59
+ def normalize_register_option(register, default_context, warning_source)
60
+ warn_register_deprecation(warning_source)
61
+ normalize_context_reference(register) || default_context
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Mml
6
+ class Namespace < Lutaml::Xml::Namespace
7
+ uri "http://www.w3.org/1998/Math/MathML"
8
+ prefix_default "mml"
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mml
4
+ module V3
5
+ class CommonElements < Mml::CommonElements
6
+ end
7
+ end
8
+ end
@@ -1,105 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../context_configuration"
4
+
3
5
  module Mml
4
6
  module V3
5
7
  module Configuration
6
- SUPPORTED_TAGS = %i[
7
- mmultiscripts
8
- maligngroup
9
- malignmark
10
- munderover
11
- semantics
12
- mscarries
13
- mfraction
14
- mphantom
15
- menclose
16
- mlongdiv
17
- mpadded
18
- msubsup
19
- mscarry
20
- mfenced
21
- msgroup
22
- mglyph
23
- mstack
24
- munder
25
- mtable
26
- mstyle
27
- mspace
28
- msline
29
- merror
30
- msrow
31
- mfrac
32
- mover
33
- mroot
34
- mtext
35
- msqrt
36
- none
37
- mrow
38
- msub
39
- msup
40
- mi
41
- mo
42
- mn
43
- ms
44
- ].freeze
45
-
46
- COMMON_ATTRIBUTES_CLASSES = %w[
47
- Math
48
- Mmultiscripts
49
- Munderover
50
- Semantics
51
- Mscarries
52
- Mfraction
53
- Mlongdiv
54
- Mphantom
55
- Menclose
56
- Mfenced
57
- Mpadded
58
- Msubsup
59
- Msgroup
60
- Mscarry
61
- Munder
62
- Mstyle
63
- Mstack
64
- Merror
65
- Mover
66
- Mfrac
67
- Msrow
68
- Mroot
69
- Msqrt
70
- Mrow
71
- Msub
72
- Msup
73
- Mtd
74
- Ms
75
- ].freeze
76
-
77
- module_function
78
-
79
- def config
80
- @config ||= {}
81
- end
82
-
83
- def config=(config)
84
- self.config.merge!(config)
85
- end
86
-
87
- def custom_models=(models_hash)
88
- # { Mi => CustomMiClass, Mo => CustomMoClass }
89
- models_hash.each { |klass, model| klass.model(model) }
90
- end
91
-
92
- def adapter
93
- Lutaml::Model::Config.xml_adapter
94
- end
95
-
96
- def adapter=(adapter)
97
- Lutaml::Model::Config.xml_adapter_type = adapter
98
- end
8
+ extend Mml::ContextConfiguration
99
9
 
100
- def class_for(class_name)
101
- config[class_name]
102
- end
10
+ CONTEXT_ID = :mml_v3
103
11
  end
104
12
  end
105
13
  end
@@ -3,20 +3,8 @@
3
3
  module Mml
4
4
  module V3
5
5
  class Maction < Lutaml::Model::Serializable
6
- attribute :mathcolor, :string
7
- attribute :mathbackground, :string
8
- attribute :actiontype, :string
9
- attribute :selection, :string
10
-
11
- xml do
12
- namespace Namespace
13
- element "maction"
14
-
15
- map_attribute "mathcolor", to: :mathcolor
16
- map_attribute "mathbackground", to: :mathbackground
17
- map_attribute "actiontype", to: :actiontype
18
- map_attribute "selection", to: :selection
19
- end
6
+ include Base::Maction
20
7
  end
8
+ Configuration.register_model(Maction, id: :maction)
21
9
  end
22
10
  end
@@ -3,18 +3,8 @@
3
3
  module Mml
4
4
  module V3
5
5
  class Maligngroup < Lutaml::Model::Serializable
6
- attribute :mathcolor, :string
7
- attribute :mathbackground, :string
8
- attribute :groupalign, :string
9
-
10
- xml do
11
- namespace Namespace
12
- element "maligngroup"
13
-
14
- map_attribute "mathcolor", to: :mathcolor
15
- map_attribute "mathbackground", to: :mathbackground
16
- map_attribute "groupalign", to: :groupalign
17
- end
6
+ include Base::Maligngroup
18
7
  end
8
+ Configuration.register_model(Maligngroup, id: :maligngroup)
19
9
  end
20
10
  end