plurimath 0.8.17 → 0.8.19

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/lib/plurimath/asciimath/parse.rb +1 -0
  3. data/lib/plurimath/asciimath/transform.rb +12 -0
  4. data/lib/plurimath/math/core.rb +63 -4
  5. data/lib/plurimath/math/formula/mrow.rb +193 -0
  6. data/lib/plurimath/math/formula/mstyle.rb +17 -0
  7. data/lib/plurimath/math/formula.rb +311 -32
  8. data/lib/plurimath/math/function/base.rb +4 -0
  9. data/lib/plurimath/math/function/color.rb +17 -4
  10. data/lib/plurimath/math/function/fenced.rb +219 -0
  11. data/lib/plurimath/math/function/frac.rb +4 -0
  12. data/lib/plurimath/math/function/linebreak.rb +2 -2
  13. data/lib/plurimath/math/function/longdiv.rb +3 -0
  14. data/lib/plurimath/math/function/menclose.rb +3 -0
  15. data/lib/plurimath/math/function/merror.rb +5 -2
  16. data/lib/plurimath/math/function/mglyph.rb +27 -0
  17. data/lib/plurimath/math/function/mlabeledtr.rb +19 -0
  18. data/lib/plurimath/math/function/mpadded.rb +28 -1
  19. data/lib/plurimath/math/function/ms.rb +80 -0
  20. data/lib/plurimath/math/function/msgroup.rb +15 -0
  21. data/lib/plurimath/math/function/msline.rb +5 -2
  22. data/lib/plurimath/math/function/multiscript.rb +14 -0
  23. data/lib/plurimath/math/function/over.rb +3 -0
  24. data/lib/plurimath/math/function/overset.rb +11 -0
  25. data/lib/plurimath/math/function/phantom.rb +3 -0
  26. data/lib/plurimath/math/function/power.rb +3 -0
  27. data/lib/plurimath/math/function/power_base.rb +3 -0
  28. data/lib/plurimath/math/function/root.rb +3 -0
  29. data/lib/plurimath/math/function/scarries.rb +3 -0
  30. data/lib/plurimath/math/function/semantics.rb +14 -0
  31. data/lib/plurimath/math/function/sqrt.rb +3 -0
  32. data/lib/plurimath/math/function/stackrel.rb +3 -0
  33. data/lib/plurimath/math/function/table.rb +53 -0
  34. data/lib/plurimath/math/function/td.rb +4 -1
  35. data/lib/plurimath/math/function/text.rb +22 -2
  36. data/lib/plurimath/math/function/tr.rb +13 -0
  37. data/lib/plurimath/math/function/underover.rb +3 -0
  38. data/lib/plurimath/math/function/underset.rb +44 -0
  39. data/lib/plurimath/math/number.rb +10 -1
  40. data/lib/plurimath/math/symbols/gg.rb +4 -4
  41. data/lib/plurimath/math/symbols/ll.rb +4 -4
  42. data/lib/plurimath/math/symbols/minus.rb +1 -1
  43. data/lib/plurimath/math/symbols/symbol.rb +12 -4
  44. data/lib/plurimath/math.rb +2 -0
  45. data/lib/plurimath/mathml/parser.rb +45 -86
  46. data/lib/plurimath/mathml/utility/empty_defined_methods.rb +477 -0
  47. data/lib/plurimath/mathml/utility/formula_transformation.rb +472 -0
  48. data/lib/plurimath/mathml/utility.rb +363 -0
  49. data/lib/plurimath/mathml.rb +1 -0
  50. data/lib/plurimath/unicode_math/transform.rb +2 -2
  51. data/lib/plurimath/utility.rb +5 -23
  52. data/lib/plurimath/version.rb +1 -1
  53. data/lib/plurimath.rb +9 -0
  54. data/plurimath.gemspec +4 -2
  55. metadata +37 -5
  56. data/lib/plurimath/mathml/transform.rb +0 -413
@@ -1,413 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Plurimath
4
- class Mathml
5
- class Transform < Parslet::Transform
6
- rule(mi: simple(:mi)) { mi }
7
- rule(mo: simple(:mo)) { mo }
8
- rule(mo: sequence(:mo)) { Utility.mathml_unary_classes(mo, lang: :mathml) }
9
- rule(mtd: sequence(:mtd)) { Math::Function::Td.new(mtd) }
10
- rule(mtr: sequence(:mtr)) { Math::Function::Tr.new(mtr) }
11
- rule(math: subtree(:math)) { math.flatten.compact }
12
- rule(mfrac: simple(:mfrac)) { mfrac }
13
- rule(none: sequence(:none)) { nil }
14
- rule(mspace: simple(:space)) { space.is_a?(Math::Function::Mpadded) ? nil : space }
15
- rule(mtable: simple(:table)) { table }
16
- rule(mglyph: simple(:glyph)) { glyph }
17
- rule(mstyle: simple(:mstyle)) { mstyle }
18
- rule(msline: sequence(:line)) { Math::Function::Msline.new }
19
- rule(value: sequence(:value)) { Utility.filter_values(value) }
20
-
21
- rule(mpadded: simple(:padded)) { padded }
22
- rule(mspace: sequence(:space)) { nil }
23
- rule(mfenced: simple(:mfenced)) { mfenced }
24
- rule(mtable: sequence(:mtable)) { Math::Function::Table.new(mtable) }
25
- rule(mscarry: sequence(:scarry)) { nil }
26
- rule(menclose: simple(:enclose)) { enclose }
27
- rule(mlabeledtr: sequence(:mtr)) { Math::Function::Tr.new(mtr) }
28
- rule(malignmark: sequence(:mark)) { nil }
29
- rule(maligngroup: sequence(:att)) { nil }
30
- rule(mprescripts: sequence(:att)) { "mprescripts" }
31
- rule(columnlines: simple(:lines)) { lines }
32
-
33
- rule(mphantom: sequence(:phantom)) do
34
- Math::Function::Phantom.new(
35
- Utility.filter_values(phantom),
36
- )
37
- end
38
-
39
- rule(mn: sequence(:mn)) do
40
- Math::Number.new(
41
- Utility.string_to_html_entity(
42
- mn.join,
43
- ),
44
- )
45
- end
46
-
47
- rule(mathvariant: simple(:variant)) do
48
- Utility::FONT_STYLES[variant.to_sym]&.new(nil, variant)
49
- end
50
-
51
- rule(mi: sequence(:mi)) do
52
- mi.any?(String) ? Utility.mathml_unary_classes(mi, lang: :mathml) : mi
53
- end
54
-
55
- rule(open: simple(:lparen)) do
56
- Math::Function::Fenced.new(
57
- Utility.symbols_class(lparen, lang: :mathml),
58
- )
59
- end
60
-
61
- rule(msgroup: sequence(:group)) do
62
- if group.any?(String)
63
- group.each_with_index do |object, ind|
64
- group[ind] = Utility.text_classes(object, lang: :mathml) if object.is_a?(String)
65
- end
66
- end
67
- Math::Function::Msgroup.new(group.flatten.compact)
68
- end
69
-
70
- rule(mlongdiv: sequence(:long)) do
71
- Math::Function::Longdiv.new(long.flatten.compact)
72
- end
73
-
74
- rule(menclose: subtree(:close)) do
75
- options = close.find { |obj| obj.is_a?(Hash) and close.delete(obj) }
76
- Math::Function::Menclose.new(
77
- (options[:notation] if options),
78
- Utility.filter_values(close),
79
- )
80
- end
81
-
82
- rule(mroot: sequence(:mroot)) do
83
- Math::Function::Root.new(
84
- mroot[1],
85
- mroot[0],
86
- )
87
- end
88
-
89
- rule(merror: sequence(:merror)) do
90
- Math::Function::Merror.new(
91
- Utility.filter_values(merror),
92
- )
93
- end
94
-
95
- rule(msqrt: subtree(:sqrt)) do
96
- options = sqrt.find { |sqr| sqr.is_a?(Hash) and sqrt.delete(sqr) }
97
- sqrt_obj = Math::Function::Sqrt.new(
98
- Utility.filter_values(sqrt),
99
- )
100
- sqrt_obj.options = options
101
- sqrt_obj
102
- end
103
-
104
- rule(mfrac: sequence(:mfrac)) do
105
- Math::Function::Frac.new(
106
- mfrac[0],
107
- mfrac[1],
108
- )
109
- end
110
-
111
- rule(mfraction: sequence(:mfrac)) do
112
- Math::Function::Frac.new(
113
- mfrac[0],
114
- mfrac[1],
115
- )
116
- end
117
-
118
- rule(msub: sequence(:msub)) do
119
- Math::Function::Base.new(
120
- msub[0],
121
- msub[1],
122
- )
123
- end
124
-
125
- rule(msub: subtree(:msub)) do
126
- Math::Function::Base.new(
127
- Utility.filter_values(msub[0]),
128
- Utility.filter_values(msub[1]),
129
- )
130
- end
131
-
132
- rule(msup: subtree(:msup)) do
133
- Math::Function::Power.new(
134
- Utility.filter_values(msup[0]),
135
- Utility.filter_values(msup[1]),
136
- )
137
- end
138
-
139
- rule(msup: sequence(:msup)) do
140
- Math::Function::Power.new(
141
- msup[0],
142
- msup[1],
143
- )
144
- end
145
-
146
- rule(msubsup: sequence(:function)) do
147
- base = function[0].is_a?(Math::Formula) ? function[0].value : function
148
- base_object = base.first
149
- if base_object.is_a?(Math::Function::BinaryFunction) && !base_object.any_value_exist?
150
- base_object.parameter_one = function[1]
151
- base_object.parameter_two = function[2]
152
- base_object
153
- elsif base_object.is_a?(Math::Function::TernaryFunction) && !base_object.any_value_exist?
154
- base_object.parameter_one = function[1]
155
- base_object.parameter_two = function[2]
156
- base_object.parameter_three = function[3]
157
- base_object
158
- else
159
- Math::Function::PowerBase.new(
160
- function[0],
161
- function[1],
162
- function[2],
163
- )
164
- end
165
- end
166
-
167
- rule(munderover: sequence(:function)) do
168
- base = function[0].is_a?(Math::Formula) ? function[0].value : function
169
- base_object = base.first
170
- if base_object.is_a?(Math::Function::BinaryFunction) && !base_object.any_value_exist?
171
- base_object.parameter_one = function[1]
172
- base_object.parameter_two = function[2]
173
- base_object
174
- elsif base_object.is_a?(Math::Function::TernaryFunction) && !base_object.any_value_exist?
175
- base_object.parameter_one = function[1]
176
- base_object.parameter_two = function[2]
177
- base_object.parameter_three = function[3]
178
- base_object
179
- else
180
- Math::Function::Underover.new(
181
- function[0],
182
- function[1],
183
- function[2],
184
- )
185
- end
186
- end
187
-
188
- rule(mrow: subtree(:mrow)) do
189
- flatten_mrow = Utility.populate_function_classes(mrow, lang: :mathml)
190
- Utility.fenceable_classes(flatten_mrow)
191
- if flatten_mrow.length == 1
192
- flatten_mrow.first
193
- elsif flatten_mrow&.first&.is_nary_function? && flatten_mrow.length == 2
194
- nary_function = flatten_mrow.first
195
- if nary_function.is_ternary_function? && nary_function.all_values_exist?
196
- if nary_function.respond_to?(:new_nary_function)
197
- flatten_mrow[0] = nary_function.new_nary_function(flatten_mrow.delete_at(1))
198
- flatten_mrow
199
- else
200
- Utility.filter_values(flatten_mrow)
201
- end
202
- elsif nary_function.is_binary_function? && nary_function.any_value_exist?
203
- flatten_mrow[0] = nary_function.new_nary_function(flatten_mrow.delete_at(1))
204
- flatten_mrow
205
- else
206
- Math::Formula.new(
207
- flatten_mrow,
208
- Utility.mrow_left_right(flatten_mrow),
209
- )
210
- end
211
- else
212
- Math::Formula.new(
213
- flatten_mrow,
214
- Utility.mrow_left_right(flatten_mrow),
215
- )
216
- end
217
- end
218
-
219
- rule(mstyle: sequence(:mstyle)) do
220
- nary_function = mstyle.first
221
- if nary_function&.is_nary_function?
222
- if nary_function.is_ternary_function? && nary_function.parameter_three.nil?
223
- nary_function.parameter_three = mstyle.delete_at(1)
224
- elsif nary_function.is_binary_function?
225
- mstyle[0] = nary_function.new_nary_function(mstyle.delete_at(1))
226
- end
227
- end
228
- Utility.filter_values(mstyle)
229
- end
230
-
231
- rule(msrow: sequence(:msrow)) do
232
- Math::Formula.new(msrow.flatten.compact)
233
- end
234
-
235
- rule(mstack: sequence(:stack)) do
236
- Math::Function::Stackrel.new(
237
- Utility.filter_values(stack),
238
- )
239
- end
240
-
241
- rule(mover: subtree(:mover)) do
242
- if mover&.length == 1
243
- base_object = mover.first
244
- base_object.class_name == "underline" ? base_object.swap_class : base_object
245
- elsif Constants::CLASSES.any?(mover&.last&.class_name)
246
- mover.last.parameter_one = mover.shift if mover.length > 1
247
- mover.last
248
- elsif mover&.last&.class_name == "period" && mover.length == 2
249
- Math::Function::Dot.new(mover[0])
250
- else
251
- Math::Function::Overset.new(mover[1], mover[0])
252
- end
253
- end
254
-
255
- rule(munder: sequence(:munder)) do
256
- if munder.any?(String)
257
- munder.each_with_index do |object, ind|
258
- next unless object.is_a?(String)
259
-
260
- munder[ind] = Utility.mathml_unary_classes([object], lang: :mathml)
261
- end
262
- end
263
- if munder.length == 1
264
- munder.first.class_name == "bar" ? munder.first.swap_class : munder.last
265
- elsif ["ubrace", "obrace", "underline"].any?(munder.last.class_name)
266
- munder.last.parameter_one = munder.shift if munder.length > 1
267
- munder.last
268
- elsif Constants::CLASSES.include?(munder.first.class_name)
269
- munder.first.parameter_one = munder.delete_at(1)
270
- munder.first
271
- else
272
- Math::Function::Underset.new(
273
- munder[1],
274
- munder[0],
275
- )
276
- end
277
- end
278
-
279
- rule(mscarries: sequence(:scarries)) do
280
- Math::Function::Scarries.new(
281
- Utility.filter_values(scarries),
282
- )
283
- end
284
-
285
- rule(mpadded: sequence(:padded)) do
286
- Math::Function::Mpadded.new(
287
- Utility.filter_values(padded),
288
- )
289
- end
290
-
291
- rule(mtext: subtree(:mtext)) do
292
- entities = HTMLEntities.new
293
- symbols = Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
294
- text = entities.encode(mtext.flatten.join, :hexadecimal)
295
- symbols.each do |code, string|
296
- text = text.gsub(code.downcase, "unicode[:#{string}]")
297
- end
298
- Math::Function::Text.new(text)
299
- end
300
-
301
- rule(ms: sequence(:ms)) do
302
- Math::Function::Ms.new(
303
- ms.flatten.compact.join(" "),
304
- )
305
- end
306
-
307
- rule(mfenced: sequence(:fenced)) do
308
- Math::Function::Fenced.new(
309
- Math::Symbols::Paren::Lround.new,
310
- fenced.compact,
311
- Math::Symbols::Paren::Rround.new,
312
- )
313
- end
314
-
315
- rule(mmultiscripts: subtree(:script)) do
316
- multi = Utility.multiscript(script)
317
- prescripts = multi[1]
318
- Math::Function::Multiscript.new(
319
- multi[0],
320
- (prescripts[0] if prescripts),
321
- (prescripts[1] if prescripts),
322
- )
323
- end
324
-
325
- rule(mathcolor: simple(:color)) do
326
- Math::Function::Color.new(
327
- Math::Function::Text.new(color),
328
- )
329
- end
330
-
331
- rule(open: simple(:lparen),
332
- close: simple(:rparen)) do
333
- Math::Function::Fenced.new(
334
- Utility.symbols_class(lparen, lang: :mathml),
335
- nil,
336
- Utility.symbols_class(rparen, lang: :mathml),
337
- )
338
- end
339
-
340
- rule(mathcolor: simple(:color),
341
- mathvariant: simple(:variant)) do
342
- variant_class = Utility::FONT_STYLES[variant.to_sym]
343
- if variant_class
344
- Math::Function::Color.new(
345
- Math::Function::Text.new(
346
- color,
347
- ),
348
- variant_class.new(
349
- nil,
350
- variant,
351
- ),
352
- )
353
- else
354
- Math::Function::Color.new(
355
- Math::Function::Text.new(
356
- color,
357
- ),
358
- )
359
- end
360
- end
361
-
362
- rule(semantics: subtree(:value)) do
363
- Math::Function::Semantics.new(
364
- value.shift,
365
- value,
366
- )
367
- end
368
-
369
- rule(attributes: simple(:attrs),
370
- value: subtree(:value)) do
371
- Utility.join_attr_value(attrs, value&.flatten&.compact)
372
- end
373
-
374
- rule(attributes: subtree(:attrs),
375
- value: sequence(:value)) do
376
- approved = if attrs.is_a?(Hash)
377
- supported_attrs = %w[
378
- linethickness
379
- accentunder
380
- columnlines
381
- separators
382
- rowlines
383
- bevelled
384
- notation
385
- height
386
- accent
387
- height
388
- intent
389
- width
390
- index
391
- depth
392
- width
393
- frame
394
- alt
395
- src
396
- ]
397
- attrs if attrs.keys.any? do |k|
398
- supported_attrs.include?(k.to_s)
399
- end
400
- unicode_only = true if attrs.key?(:linebreak)
401
- attrs
402
- else
403
- attrs
404
- end
405
- Utility.join_attr_value(
406
- approved,
407
- value&.flatten&.compact,
408
- unicode_only: unicode_only,
409
- )
410
- end
411
- end
412
- end
413
- end