plurimath 0.2.1 → 0.2.2

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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +13 -0
  3. data/.github/workflows/release.yml +22 -0
  4. data/.hound.yml +5 -0
  5. data/.rubocop.yml +8 -0
  6. data/AsciiMath-Supported-Data.adoc +1994 -274
  7. data/Gemfile +2 -0
  8. data/Latex-Supported-Data.adoc +1875 -1868
  9. data/MathML-Supported-Data.adoc +280 -263
  10. data/README.adoc +22 -20
  11. data/lib/plurimath/asciimath/constants.rb +186 -141
  12. data/lib/plurimath/asciimath/parse.rb +104 -39
  13. data/lib/plurimath/asciimath/parser.rb +3 -1
  14. data/lib/plurimath/asciimath/transform.rb +1074 -238
  15. data/lib/plurimath/html/parse.rb +1 -1
  16. data/lib/plurimath/latex/constants.rb +3228 -1432
  17. data/lib/plurimath/latex/parse.rb +106 -83
  18. data/lib/plurimath/latex/parser.rb +11 -4
  19. data/lib/plurimath/latex/transform.rb +354 -99
  20. data/lib/plurimath/math/base.rb +15 -0
  21. data/lib/plurimath/math/formula.rb +90 -13
  22. data/lib/plurimath/math/function/bar.rb +35 -1
  23. data/lib/plurimath/math/function/base.rb +25 -4
  24. data/lib/plurimath/math/function/binary_function.rb +101 -19
  25. data/lib/plurimath/math/function/cancel.rb +8 -0
  26. data/lib/plurimath/math/function/ceil.rb +3 -0
  27. data/lib/plurimath/math/function/color.rb +15 -5
  28. data/lib/plurimath/math/function/f.rb +8 -0
  29. data/lib/plurimath/math/function/fenced.rb +95 -8
  30. data/lib/plurimath/math/function/floor.rb +15 -0
  31. data/lib/plurimath/math/function/font_style/bold.rb +19 -0
  32. data/lib/plurimath/math/function/font_style/double_struck.rb +19 -0
  33. data/lib/plurimath/math/function/font_style/fraktur.rb +19 -0
  34. data/lib/plurimath/math/function/font_style/italic.rb +37 -0
  35. data/lib/plurimath/math/function/font_style/monospace.rb +19 -0
  36. data/lib/plurimath/math/function/font_style/normal.rb +37 -0
  37. data/lib/plurimath/math/function/font_style/sans-serif.rb +19 -0
  38. data/lib/plurimath/math/function/font_style/script.rb +19 -0
  39. data/lib/plurimath/math/function/font_style.rb +18 -5
  40. data/lib/plurimath/math/function/frac.rb +33 -3
  41. data/lib/plurimath/math/function/g.rb +7 -0
  42. data/lib/plurimath/math/function/hat.rb +12 -0
  43. data/lib/plurimath/math/function/inf.rb +21 -0
  44. data/lib/plurimath/math/function/int.rb +23 -2
  45. data/lib/plurimath/math/function/left.rb +25 -1
  46. data/lib/plurimath/math/function/lim.rb +40 -2
  47. data/lib/plurimath/math/function/limits.rb +9 -0
  48. data/lib/plurimath/math/function/log.rb +55 -4
  49. data/lib/plurimath/math/function/longdiv.rb +12 -0
  50. data/lib/plurimath/math/function/mbox.rb +31 -0
  51. data/lib/plurimath/math/function/menclose.rb +46 -0
  52. data/lib/plurimath/math/function/merror.rb +12 -0
  53. data/lib/plurimath/math/function/mod.rb +19 -4
  54. data/lib/plurimath/math/function/msgroup.rb +37 -0
  55. data/lib/plurimath/math/function/msline.rb +12 -0
  56. data/lib/plurimath/math/function/multiscript.rb +19 -0
  57. data/lib/plurimath/math/function/norm.rb +17 -1
  58. data/lib/plurimath/math/function/obrace.rb +17 -0
  59. data/lib/plurimath/math/function/oint.rb +2 -2
  60. data/lib/plurimath/math/function/over.rb +12 -5
  61. data/lib/plurimath/math/function/overset.rb +34 -5
  62. data/lib/plurimath/math/function/phantom.rb +28 -0
  63. data/lib/plurimath/math/function/power.rb +27 -9
  64. data/lib/plurimath/math/function/power_base.rb +109 -11
  65. data/lib/plurimath/math/function/prod.rb +25 -4
  66. data/lib/plurimath/math/function/right.rb +22 -2
  67. data/lib/plurimath/math/function/root.rb +23 -1
  68. data/lib/plurimath/math/function/rule.rb +33 -0
  69. data/lib/plurimath/math/function/scarries.rb +12 -0
  70. data/lib/plurimath/math/function/scarry.rb +12 -0
  71. data/lib/plurimath/math/function/sqrt.rb +23 -1
  72. data/lib/plurimath/math/function/stackrel.rb +27 -0
  73. data/lib/plurimath/math/function/substack.rb +7 -0
  74. data/lib/plurimath/math/function/sum.rb +50 -2
  75. data/lib/plurimath/math/function/sup.rb +3 -0
  76. data/lib/plurimath/math/function/table/align.rb +5 -5
  77. data/lib/plurimath/math/function/table/array.rb +25 -6
  78. data/lib/plurimath/math/function/table/bmatrix.rb +18 -7
  79. data/lib/plurimath/math/function/table/matrix.rb +13 -5
  80. data/lib/plurimath/math/function/table/multline.rb +5 -5
  81. data/lib/plurimath/math/function/table/pmatrix.rb +5 -5
  82. data/lib/plurimath/math/function/table/split.rb +5 -5
  83. data/lib/plurimath/math/function/table/vmatrix.rb +5 -6
  84. data/lib/plurimath/math/function/table.rb +185 -27
  85. data/lib/plurimath/math/function/td.rb +22 -9
  86. data/lib/plurimath/math/function/ternary_function.rb +74 -9
  87. data/lib/plurimath/math/function/text.rb +36 -11
  88. data/lib/plurimath/math/function/tr.rb +23 -4
  89. data/lib/plurimath/math/function/ubrace.rb +17 -0
  90. data/lib/plurimath/math/function/ul.rb +29 -0
  91. data/lib/plurimath/math/function/unary_function.rb +81 -8
  92. data/lib/plurimath/math/function/underline.rb +12 -0
  93. data/lib/plurimath/math/function/underover.rb +107 -0
  94. data/lib/plurimath/math/function/underset.rb +39 -0
  95. data/lib/plurimath/math/function/vec.rb +7 -1
  96. data/lib/plurimath/math/number.rb +5 -5
  97. data/lib/plurimath/math/symbol.rb +51 -12
  98. data/lib/plurimath/math/unicode.rb +11 -0
  99. data/lib/plurimath/math.rb +7 -3
  100. data/lib/plurimath/mathml/constants.rb +224 -147
  101. data/lib/plurimath/mathml/parser.rb +24 -8
  102. data/lib/plurimath/mathml/transform.rb +249 -153
  103. data/lib/plurimath/omml/parser.rb +24 -4
  104. data/lib/plurimath/omml/transform.rb +219 -157
  105. data/lib/plurimath/utility.rb +342 -20
  106. data/lib/plurimath/version.rb +1 -1
  107. metadata +21 -6
  108. data/.github/workflows/test.yml +0 -33
  109. data/lib/plurimath/mathml/parse.rb +0 -68
  110. data/lib/plurimath/omml/constants.rb +0 -154
@@ -3,198 +3,294 @@
3
3
  module Plurimath
4
4
  class Mathml
5
5
  class Transform < Parslet::Transform
6
- rule(tag: simple(:tag)) { tag }
7
- rule(tag: sequence(:tag)) { tag }
8
- rule(text: simple(:text)) { Math::Symbol.new(text) }
9
- rule(class: simple(:string)) { Utility.get_class(string).new }
10
- rule(number: simple(:number)) { Math::Number.new(number) }
6
+ rule(mi: simple(:mi)) { mi }
7
+ rule(mo: simple(:mo)) { mo }
8
+ rule(mo: sequence(:mo)) { Utility.mathml_unary_classes(mo) }
9
+ rule(xref: simple(:xref)) { nil }
10
+ rule(mtd: sequence(:mtd)) { Math::Function::Td.new(mtd) }
11
+ rule(mtr: sequence(:mtr)) { Math::Function::Tr.new(mtr) }
12
+ rule(accent: simple(:acc)) { nil }
13
+ rule(none: sequence(:none)) { nil }
14
+ rule(maxsize: simple(:att)) { nil }
15
+ rule(minsize: simple(:att)) { nil }
16
+ rule(notation: simple(:att)) { Math::Function::Menclose.new(att) }
17
+ rule(mtable: simple(:table)) { table }
18
+ rule(msqrt: sequence(:sqrt)) { Math::Function::Sqrt.new(sqrt.first) }
19
+ rule(mstyle: simple(:mstyle)) { mstyle }
20
+ rule(msline: sequence(:line)) { Math::Function::Msline.new }
21
+ rule(value: sequence(:value)) { Utility.filter_values(value) }
11
22
 
12
- rule(tag: sequence(:tag), sequence: simple(:sequence)) do
13
- tag + [sequence]
23
+ rule(mspace: sequence(:space)) { nil }
24
+ rule(mstyle: sequence(:mstyle)) { Utility.filter_values(mstyle) }
25
+ rule(mfenced: simple(:mfenced)) { mfenced }
26
+ rule(mtable: sequence(:mtable)) { Math::Function::Table.new(mtable) }
27
+ rule(mscarry: sequence(:scarry)) { nil }
28
+ rule(displaystyle: simple(:att)) { nil }
29
+ rule(menclose: simple(:enclose)) { enclose }
30
+ rule(mlabeledtr: sequence(:mtr)) { Math::Function::Tr.new(mtr) }
31
+ rule(mpadded: sequence(:padded)) { Utility.filter_values(padded) }
32
+ rule(malignmark: sequence(:mark)) { nil }
33
+ rule(maligngroup: sequence(:att)) { nil }
34
+ rule(mprescripts: sequence(:att)) { "mprescripts" }
35
+ rule(columnlines: simple(:lines)) { lines }
36
+
37
+ rule(math: subtree(:math)) do
38
+ Utility.filter_values(
39
+ math.flatten.compact,
40
+ )
14
41
  end
15
42
 
16
- rule(tag: simple(:tag), sequence: sequence(:sequence)) do
17
- [tag] + sequence
43
+ rule(mphantom: sequence(:phantom)) do
44
+ Math::Function::Phantom.new(phantom)
18
45
  end
19
46
 
20
- rule(tag: sequence(:tag), sequence: sequence(:sequence)) do
21
- tag + sequence
47
+ rule(mn: sequence(:mn)) do
48
+ Math::Number.new(
49
+ Utility.string_to_html_entity(
50
+ mn.join,
51
+ ),
52
+ )
22
53
  end
23
54
 
24
- rule(quoted_text: simple(:quoted_text)) do
25
- text = quoted_text
26
- symbols = Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
27
- symbols.each do |code, string|
28
- text.gsub!(code, "unicode[:#{string}]")
55
+ rule(mathvariant: simple(:variant)) do
56
+ Utility::FONT_STYLES[variant.to_sym]&.new(nil, variant)
57
+ end
58
+
59
+ rule(mi: sequence(:mi)) do
60
+ mi.any?(String) ? Utility.mathml_unary_classes(mi) : mi
61
+ end
62
+
63
+ rule(open: simple(:lparen)) do
64
+ Math::Function::Fenced.new(Math::Symbol.new(lparen))
65
+ end
66
+
67
+ rule(msgroup: sequence(:group)) do
68
+ if group.any?(String)
69
+ group.each_with_index do |object, ind|
70
+ group[ind] = Utility.text_classes(object) if object.is_a?(String)
71
+ end
29
72
  end
30
- Math::Function::Text.new(text)
73
+ Math::Function::Msgroup.new(group.flatten.compact)
74
+ end
75
+
76
+ rule(mlongdiv: sequence(:long)) do
77
+ Math::Function::Longdiv.new(long.flatten.compact)
78
+ end
79
+
80
+ rule(menclose: sequence(:close)) do
81
+ Math::Function::Menclose.new(
82
+ nil,
83
+ Utility.filter_values(close),
84
+ )
31
85
  end
32
86
 
33
- rule(
34
- tag: sequence(:tag),
35
- sequence: sequence(:sequence),
36
- iteration: simple(:iteration),
37
- ) do
38
- new_arr = []
39
- new_arr = new_arr + tag unless tag.compact.empty?
40
- new_arr = new_arr + sequence unless sequence.compact.empty?
41
- new_arr << iteration unless iteration.to_s.empty?
42
- new_arr
87
+ rule(mroot: sequence(:mroot)) do
88
+ Math::Function::Root.new(
89
+ mroot[1],
90
+ mroot[0],
91
+ )
43
92
  end
44
93
 
45
- rule(
46
- tag: sequence(:tag),
47
- sequence: simple(:sequence),
48
- iteration: simple(:iteration),
49
- ) do
50
- Math::Formula.new(tag + [sequence, iteration])
94
+ rule(merror: sequence(:merror)) do
95
+ Math::Function::Merror.new(
96
+ merror[0],
97
+ merror[1],
98
+ )
51
99
  end
52
100
 
53
- rule(
54
- tag: simple(:tag),
55
- sequence: simple(:sequence),
56
- iteration: simple(:iteration),
57
- ) do
58
- iteration.size.zero? ? [tag, sequence] : [tag, sequence, iteration]
101
+ rule(mfrac: sequence(:mfrac)) do
102
+ Math::Function::Frac.new(
103
+ mfrac[0],
104
+ mfrac[1],
105
+ )
59
106
  end
60
107
 
61
- rule(tag: sequence(:tag), iteration: simple(:iteration)) do
62
- new_arr = []
63
- new_arr = tag unless tag.compact.empty?
64
- new_arr << iteration unless iteration.to_s.empty?
65
- new_arr
108
+ rule(mfraction: sequence(:mfrac)) do
109
+ Math::Function::Frac.new(
110
+ mfrac[0],
111
+ mfrac[1],
112
+ )
66
113
  end
67
114
 
68
- rule(tag: simple(:tag), sequence: simple(:sequence)) do
69
- new_arr = []
70
- new_arr << tag unless tag.nil?
71
- new_arr << sequence unless sequence.nil?
72
- new_arr
115
+ rule(msub: sequence(:msub)) do
116
+ Math::Function::Base.new(
117
+ msub[0],
118
+ msub[1],
119
+ )
73
120
  end
74
121
 
75
- rule(tag: simple(:tag), iteration: simple(:iteration)) do
76
- new_arr = []
77
- new_arr << tag unless tag.to_s.empty?
78
- new_arr << iteration unless iteration.to_s.empty?
79
- new_arr
122
+ rule(msup: sequence(:msup)) do
123
+ Math::Function::Power.new(
124
+ msup[0],
125
+ msup[1],
126
+ )
80
127
  end
81
128
 
82
- rule(symbol: simple(:symbol)) do
83
- decoded_symbol = Constants::UNICODE_SYMBOLS[symbol.to_sym]
84
- if Constants::CLASSES.include?(decoded_symbol)
85
- [Utility.get_class(decoded_symbol).new]
86
- elsif decoded_symbol.nil? && Constants::SYMBOLS[symbol.to_sym]
87
- Math::Symbol.new(Constants::SYMBOLS[symbol.to_sym])
129
+ rule(msubsup: sequence(:msubsup)) do
130
+ Math::Function::PowerBase.new(
131
+ msubsup[0],
132
+ msubsup[1],
133
+ msubsup[2],
134
+ )
135
+ end
136
+
137
+ rule(munderover: sequence(:function)) do
138
+ binary_function = Plurimath::Math::Function::BinaryFunction
139
+ base_class = function[0]&.value&.first if function[0].is_a?(Math::Formula)
140
+ if base_class&.class&.ancestors&.include?(binary_function)
141
+ base_class.parameter_one = function[1]
142
+ base_class.parameter_two = function[2]
143
+ base_class
88
144
  else
89
- Math::Symbol.new(decoded_symbol)
145
+ Math::Function::Underover.new(
146
+ function[0],
147
+ function[1],
148
+ function[2],
149
+ )
90
150
  end
91
151
  end
92
152
 
93
- rule(name: simple(:name), value: simple(:value)) do
94
- if ["open", "close"].include?(name)
95
- Math::Symbol.new(value)
96
- elsif name == "mathcolor"
97
- Math::Function::Color.new(value)
98
- elsif name == "mathvariant"
99
- value
153
+ rule(mrow: subtree(:mrow)) do
154
+ if mrow.any?(String)
155
+ mrow.each_with_index do |object, ind|
156
+ mrow[ind] = Utility.mathml_unary_classes([object]) if object.is_a?(String)
157
+ end
100
158
  end
159
+ Math::Formula.new(mrow.flatten.compact)
101
160
  end
102
161
 
103
- rule(
104
- tag: simple(:tag),
105
- sequence: sequence(:sequence),
106
- iteration: simple(:iteration),
107
- ) do
108
- new_arr = sequence.compact
109
- new_arr = [tag] + new_arr unless tag.nil?
110
- new_arr << iteration unless iteration.to_s.empty?
111
- new_arr
112
- end
113
-
114
- rule(
115
- open: simple(:open_tag),
116
- attributes: sequence(:attributes),
117
- iteration: sequence(:iteration),
118
- close: simple(:close_tag),
119
- ) do
120
- Utility.raise_error!(open_tag, close_tag) unless open_tag == close_tag
121
-
122
- if open_tag == "mrow"
123
- Math::Formula.new(iteration)
124
- elsif open_tag == "munder"
125
- if iteration.last.class_name == "obrace"
126
- iteration.last.parameter_one = iteration.first
127
- iteration.last
128
- else
129
- Math::Function::Underset.new(iteration[1], iteration[0])
130
- end
131
- elsif open_tag == "munderover"
132
- Utility.get_class(open_tag.delete_prefix("m")).new(
133
- iteration[0],
134
- iteration[1],
135
- iteration[2],
136
- )
137
- elsif open_tag == "mover"
138
- if iteration.last.class_name == "ubrace"
139
- iteration.last.parameter_one = iteration.first
140
- iteration.last
141
- else
142
- Math::Function::Overset.new(iteration[1], iteration[0])
143
- end
144
- elsif ["msub", "msup"].include?(open_tag)
145
- tag = (open_tag == "msup" ? "power" : "base")
146
- Utility.get_class(tag).new(iteration[0], iteration[1])
147
- elsif open_tag == "msubsup"
148
- Math::Function::PowerBase.new(iteration[0],
149
- iteration[1],
150
- iteration[2])
151
- elsif open_tag == "mfrac"
152
- Math::Function::Frac.new(iteration.first, iteration.last)
153
- elsif open_tag == "msqrt"
154
- Math::Function::Sqrt.new(iteration.first)
155
- elsif open_tag == "mroot"
156
- Math::Function::Root.new(iteration[0], iteration[1])
157
- elsif open_tag == "mfenced"
158
- Math::Function::Fenced.new(
159
- attributes[0],
160
- iteration,
161
- attributes[1],
162
+ rule(msrow: sequence(:msrow)) do
163
+ Math::Formula.new(msrow.flatten.compact)
164
+ end
165
+
166
+ rule(mstack: sequence(:stack)) do
167
+ Math::Function::Stackrel.new(
168
+ Utility.filter_values(stack),
169
+ )
170
+ end
171
+
172
+ rule(mover: sequence(:mover)) do
173
+ if ["ubrace", "obrace"].any?(mover.last.class_name)
174
+ mover.last.parameter_one = mover.shift if mover.length > 1
175
+ mover.last
176
+ else
177
+ Math::Function::Overset.new(
178
+ mover[1],
179
+ mover[0],
162
180
  )
163
- elsif ["mtr", "mtd", "mtable"].include?(open_tag)
164
- tag = open_tag.delete_prefix("m")
165
- Utility.get_class(tag).new(iteration)
166
- elsif attributes.first.is_a?(Math::Function::Color)
167
- attributes.first.parameter_two = iteration.first
168
- attributes.first
169
- elsif open_tag == "mstyle" && !attributes.compact.empty?
170
- font_type = attributes.compact.last
171
- if Utility::FONT_STYLES.key?(font_type.to_sym)
172
- Utility::FONT_STYLES[font_type.to_sym].new(
173
- iteration.last,
174
- font_type,
175
- )
176
- else
177
- Math::Function::FontStyle.new(iteration.last, font_type)
181
+ end
182
+ end
183
+
184
+ rule(munder: sequence(:munder)) do
185
+ if munder.any?(String)
186
+ munder.each_with_index do |object, ind|
187
+ munder[ind] = Utility.mathml_unary_classes([object]) if object.is_a?(String)
178
188
  end
189
+ end
190
+ if ["ubrace", "obrace"].any?(munder.last.class_name)
191
+ munder.last.parameter_one = munder.shift if munder.length > 1
192
+ munder.last
179
193
  else
180
- iteration
194
+ Math::Function::Underset.new(
195
+ munder[1],
196
+ munder[0],
197
+ )
198
+ end
199
+ end
200
+
201
+ rule(mscarries: sequence(:scarries)) do
202
+ Math::Function::Scarries.new(
203
+ Utility.filter_values(scarries),
204
+ )
205
+ end
206
+
207
+ rule(mtext: sequence(:mtext)) do
208
+ entities = HTMLEntities.new
209
+ symbols = Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
210
+ text = entities.encode(mtext.first, :hexadecimal)
211
+ symbols.each do |code, string|
212
+ text.gsub!(code.downcase, "unicode[:#{string}]")
213
+ end
214
+ Math::Function::Text.new(text)
215
+ end
216
+
217
+ rule(ms: sequence(:ms)) do
218
+ entities = HTMLEntities.new
219
+ symbols = Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
220
+ text = entities.encode(ms.first, :hexadecimal)
221
+ symbols.each do |code, string|
222
+ text.gsub!(code.downcase, "unicode[:#{string}]")
181
223
  end
224
+ Math::Function::Text.new(text)
225
+ end
226
+
227
+ rule(mfenced: sequence(:fenced)) do
228
+ Math::Function::Fenced.new(
229
+ Math::Symbol.new("("),
230
+ fenced,
231
+ Math::Symbol.new(")"),
232
+ )
233
+ end
234
+
235
+ rule(mmultiscripts: subtree(:script)) do
236
+ multi = Utility.multiscript(script.compact)
237
+ prescripts = multi[1]
238
+ Math::Function::Multiscript.new(
239
+ multi[0],
240
+ (prescripts[0] if prescripts),
241
+ (prescripts[1] if prescripts),
242
+ )
243
+ end
244
+
245
+ rule(mathcolor: simple(:color)) do
246
+ Math::Function::Color.new(
247
+ Math::Function::Text.new(color),
248
+ )
182
249
  end
183
250
 
184
- rule(
185
- open: simple(:open_tag),
186
- attributes: sequence(:attributes),
187
- iteration: simple(:iteration),
188
- close: simple(:close_tag),
189
- ) do
190
- Utility.raise_error!(open_tag, close_tag) unless open_tag == close_tag
251
+ rule(open: simple(:lparen),
252
+ close: simple(:rparen)) do
253
+ Math::Function::Fenced.new(
254
+ Math::Symbol.new(lparen),
255
+ nil,
256
+ Math::Symbol.new(rparen),
257
+ )
258
+ end
191
259
 
192
- if iteration.to_s.include?("Function")
193
- iteration
260
+ rule(mathcolor: simple(:color),
261
+ mathvariant: simple(:variant)) do
262
+ variant_class = Utility::FONT_STYLES[variant.to_sym]
263
+ if variant_class
264
+ Math::Function::Color.new(
265
+ Math::Function::Text.new(
266
+ color,
267
+ ),
268
+ variant_class.new(
269
+ nil,
270
+ variant,
271
+ ),
272
+ )
194
273
  else
195
- [iteration.to_s.empty? ? nil : iteration]
274
+ Math::Function::Color.new(
275
+ Math::Function::Text.new(
276
+ color,
277
+ ),
278
+ )
196
279
  end
197
280
  end
281
+
282
+ rule(attributes: simple(:attrs),
283
+ value: subtree(:value)) do
284
+ Utility.join_attr_value(attrs, value.flatten)
285
+ end
286
+
287
+ rule(attributes: subtree(:attrs),
288
+ value: sequence(:value)) do
289
+ Utility.join_attr_value(
290
+ attrs.is_a?(Hash) ? nil : attrs,
291
+ value.flatten,
292
+ )
293
+ end
198
294
  end
199
295
  end
200
296
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "constants"
4
3
  require_relative "transform"
5
4
  module Plurimath
6
5
  class Omml
@@ -8,15 +7,36 @@ module Plurimath
8
7
  attr_accessor :text
9
8
 
10
9
  def initialize(text)
11
- @text = CGI.unescape(text)
10
+ @text = text
12
11
  end
13
12
 
14
13
  def parse
15
- nodes = Ox.load(text, mode: :hash, strip_namespace: true)
14
+ nodes = Ox.load(text, strip_namespace: true)
15
+ @hash = { sequence: parse_nodes(nodes.nodes) }
16
+ nodes = JSON.parse(@hash.to_json, symbolize_names: true)
16
17
  Math::Formula.new(
17
- Transform.new.apply(nodes),
18
+ Transform.new.apply(
19
+ nodes,
20
+ ),
18
21
  )
19
22
  end
23
+
24
+ def parse_nodes(nodes)
25
+ nodes.map do |node|
26
+ if node.is_a?(String)
27
+ node
28
+ elsif !node.attributes.empty?
29
+ {
30
+ node.name => {
31
+ attributes: node.attributes,
32
+ value: parse_nodes(node.nodes),
33
+ },
34
+ }
35
+ else
36
+ { node.name => parse_nodes(node.nodes) }
37
+ end
38
+ end
39
+ end
20
40
  end
21
41
  end
22
42
  end