plurimath 0.11.6 → 0.11.7

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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/lib/plurimath/asciimath/utility.rb +50 -0
  3. data/lib/plurimath/asciimath.rb +1 -0
  4. data/lib/plurimath/formatter/numbers/mathml_renderer.rb +15 -15
  5. data/lib/plurimath/formatter/numbers/omml_renderer.rb +19 -19
  6. data/lib/plurimath/html/utility.rb +18 -0
  7. data/lib/plurimath/html.rb +1 -0
  8. data/lib/plurimath/latex/utility.rb +118 -0
  9. data/lib/plurimath/latex.rb +1 -0
  10. data/lib/plurimath/math/core.rb +12 -12
  11. data/lib/plurimath/math/formula.rb +10 -10
  12. data/lib/plurimath/math/function/abs.rb +3 -3
  13. data/lib/plurimath/math/function/bar.rb +14 -14
  14. data/lib/plurimath/math/function/base.rb +15 -7
  15. data/lib/plurimath/math/function/binary_function.rb +7 -7
  16. data/lib/plurimath/math/function/cancel.rb +2 -2
  17. data/lib/plurimath/math/function/ceil.rb +1 -1
  18. data/lib/plurimath/math/function/color.rb +2 -2
  19. data/lib/plurimath/math/function/ddot.rb +3 -3
  20. data/lib/plurimath/math/function/dot.rb +8 -8
  21. data/lib/plurimath/math/function/fenced.rb +8 -8
  22. data/lib/plurimath/math/function/floor.rb +1 -1
  23. data/lib/plurimath/math/function/font_style/bold.rb +2 -2
  24. data/lib/plurimath/math/function/font_style/double_struck.rb +2 -2
  25. data/lib/plurimath/math/function/font_style/fraktur.rb +2 -2
  26. data/lib/plurimath/math/function/font_style/italic.rb +2 -2
  27. data/lib/plurimath/math/function/font_style/monospace.rb +2 -2
  28. data/lib/plurimath/math/function/font_style/normal.rb +2 -2
  29. data/lib/plurimath/math/function/font_style/sans-serif.rb +2 -2
  30. data/lib/plurimath/math/function/font_style/script.rb +2 -2
  31. data/lib/plurimath/math/function/font_style.rb +16 -15
  32. data/lib/plurimath/math/function/frac.rb +7 -7
  33. data/lib/plurimath/math/function/hat.rb +8 -8
  34. data/lib/plurimath/math/function/inf.rb +2 -2
  35. data/lib/plurimath/math/function/int.rb +8 -8
  36. data/lib/plurimath/math/function/left.rb +5 -5
  37. data/lib/plurimath/math/function/lim.rb +3 -3
  38. data/lib/plurimath/math/function/limits.rb +2 -2
  39. data/lib/plurimath/math/function/linebreak.rb +2 -2
  40. data/lib/plurimath/math/function/log.rb +10 -10
  41. data/lib/plurimath/math/function/longdiv.rb +1 -1
  42. data/lib/plurimath/math/function/menclose.rb +2 -2
  43. data/lib/plurimath/math/function/merror.rb +2 -2
  44. data/lib/plurimath/math/function/mod.rb +1 -1
  45. data/lib/plurimath/math/function/mpadded.rb +2 -2
  46. data/lib/plurimath/math/function/ms.rb +2 -2
  47. data/lib/plurimath/math/function/msgroup.rb +2 -2
  48. data/lib/plurimath/math/function/multiscript.rb +2 -2
  49. data/lib/plurimath/math/function/nary.rb +15 -15
  50. data/lib/plurimath/math/function/none.rb +1 -1
  51. data/lib/plurimath/math/function/norm.rb +1 -1
  52. data/lib/plurimath/math/function/obrace.rb +8 -8
  53. data/lib/plurimath/math/function/oint.rb +6 -6
  54. data/lib/plurimath/math/function/over.rb +5 -5
  55. data/lib/plurimath/math/function/overleftrightarrow.rb +7 -7
  56. data/lib/plurimath/math/function/overset.rb +5 -5
  57. data/lib/plurimath/math/function/phantom.rb +9 -9
  58. data/lib/plurimath/math/function/power.rb +5 -5
  59. data/lib/plurimath/math/function/power_base.rb +5 -5
  60. data/lib/plurimath/math/function/prod.rb +4 -4
  61. data/lib/plurimath/math/function/right.rb +5 -5
  62. data/lib/plurimath/math/function/root.rb +7 -7
  63. data/lib/plurimath/math/function/rule.rb +2 -2
  64. data/lib/plurimath/math/function/scarries.rb +1 -1
  65. data/lib/plurimath/math/function/semantics.rb +4 -4
  66. data/lib/plurimath/math/function/sqrt.rb +7 -7
  67. data/lib/plurimath/math/function/stackrel.rb +5 -5
  68. data/lib/plurimath/math/function/substack.rb +1 -1
  69. data/lib/plurimath/math/function/sum.rb +4 -4
  70. data/lib/plurimath/math/function/sup.rb +1 -1
  71. data/lib/plurimath/math/function/table/array.rb +1 -1
  72. data/lib/plurimath/math/function/table/bmatrix.rb +2 -2
  73. data/lib/plurimath/math/function/table/matrix.rb +2 -2
  74. data/lib/plurimath/math/function/table.rb +29 -29
  75. data/lib/plurimath/math/function/td.rb +3 -3
  76. data/lib/plurimath/math/function/ternary_function.rb +13 -13
  77. data/lib/plurimath/math/function/text.rb +4 -4
  78. data/lib/plurimath/math/function/tilde.rb +6 -6
  79. data/lib/plurimath/math/function/tr.rb +4 -4
  80. data/lib/plurimath/math/function/ubrace.rb +1 -1
  81. data/lib/plurimath/math/function/ul.rb +9 -9
  82. data/lib/plurimath/math/function/unary_function.rb +14 -14
  83. data/lib/plurimath/math/function/underover.rb +1 -1
  84. data/lib/plurimath/math/function/underset.rb +12 -12
  85. data/lib/plurimath/math/function/unitsml.rb +1 -1
  86. data/lib/plurimath/math/function/vec.rb +7 -7
  87. data/lib/plurimath/math/model_helper.rb +103 -0
  88. data/lib/plurimath/math/number.rb +2 -2
  89. data/lib/plurimath/math/symbols/symbol.rb +2 -2
  90. data/lib/plurimath/math/symbols/tilde.rb +1 -1
  91. data/lib/plurimath/math.rb +1 -0
  92. data/lib/plurimath/mathml/constants.rb +29 -155
  93. data/lib/plurimath/mathml/formula_transformation.rb +2 -5
  94. data/lib/plurimath/mathml/translator.rb +6 -0
  95. data/lib/plurimath/mathml/utility.rb +53 -0
  96. data/lib/plurimath/mathml.rb +1 -0
  97. data/lib/plurimath/omml/formula_transformation.rb +5 -5
  98. data/lib/plurimath/omml/translator.rb +8 -5
  99. data/lib/plurimath/omml/utility.rb +109 -0
  100. data/lib/plurimath/omml.rb +1 -0
  101. data/lib/plurimath/unicode_math/transform.rb +5 -1
  102. data/lib/plurimath/unicode_math/utility.rb +256 -0
  103. data/lib/plurimath/unicode_math.rb +1 -0
  104. data/lib/plurimath/utility/intent_encoding.rb +4 -4
  105. data/lib/plurimath/utility.rb +6 -815
  106. data/lib/plurimath/version.rb +1 -1
  107. data/lib/plurimath/xml_engine/oga/dumper.rb +8 -1
  108. data/lib/plurimath/xml_engine/ox_engine.rb +4 -1
  109. data/lib/plurimath/xml_helper.rb +47 -0
  110. data/lib/plurimath.rb +1 -0
  111. metadata +10 -2
@@ -0,0 +1,256 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plurimath
4
+ class UnicodeMath
5
+ # UnicodeMath-specific helpers extracted from Plurimath::Utility (code-quality
6
+ # refactor). Subclasses Utility so that bareword `Utility.<generic>` calls inside
7
+ # UnicodeMath files keep resolving here and inherit the generic helpers.
8
+ class Utility < Plurimath::Utility
9
+ class << self
10
+ def unicode_accents(accents, lang: :unicodemath)
11
+ if accents.is_a?(Math::Function::BinaryFunction)
12
+ accents
13
+ elsif accents.any? { |acc| acc&.dig(:first_value)&.is_a?(Array) }
14
+ accent_value = accents.first[:first_value].pop
15
+ first_value = accents.first[:first_value]
16
+ accents.first[:first_value] = accent_value
17
+ Math::Formula.new(
18
+ first_value + [transform_accents(accents, lang: lang)],
19
+ )
20
+ else
21
+ transform_accents(accents, lang: lang)
22
+ end
23
+ end
24
+
25
+ def transform_accents(accents, lang:)
26
+ accents.reduce do |function, accent|
27
+ if function.is_a?(Hash)
28
+ if function[:prime_accent_symbols]
29
+ Math::Function::Power.new(
30
+ unfenced_value(
31
+ accent_value(function, lang: lang), paren_specific: true
32
+ ),
33
+ accent_value(accent, lang: lang),
34
+ )
35
+ else
36
+ Math::Function::Overset.new(
37
+ accent_value(accent, lang: lang),
38
+ unfenced_value(
39
+ accent_value(function, lang: lang), paren_specific: true
40
+ ),
41
+ { accent: true },
42
+ )
43
+ end
44
+ elsif accent[:prime_accent_symbols]
45
+ Math::Function::Power.new(
46
+ unfenced_value(function, paren_specific: true),
47
+ accent_value(accent, lang: lang),
48
+ )
49
+ else
50
+ Math::Function::Overset.new(
51
+ accent_value(accent, lang: lang),
52
+ unfenced_value(function, paren_specific: true),
53
+ { accent: true },
54
+ )
55
+ end
56
+ end
57
+ end
58
+
59
+ def accent_value(accent, lang:)
60
+ if accent[:accent_symbols]
61
+ symbols_class(
62
+ UnicodeMath::Constants::ACCENT_SYMBOLS[accent[:accent_symbols].to_sym] || accent[:accent_symbols], lang: lang
63
+ )
64
+ else
65
+ accent[:first_value] || updated_primes(accent[:prime_accent_symbols])
66
+ end
67
+ end
68
+
69
+ def unicode_fractions(fractions)
70
+ frac_arr = UnicodeMath::Constants::UNICODE_FRACTIONS[fractions.to_sym]
71
+ Math::Function::Frac.new(
72
+ Math::Number.new(frac_arr.first.to_s),
73
+ Math::Number.new(frac_arr.last.to_s),
74
+ { displaystyle: false, unicodemath_fraction: true },
75
+ )
76
+ end
77
+
78
+ def updated_primes(prime)
79
+ filter_values(
80
+ prime.to_s.scan(Plurimath::Utility::UNICODE_REGEX).map do |str|
81
+ symbols_class(str, lang: :unicodemath)
82
+ end,
83
+ )
84
+ end
85
+
86
+ def fractions(numerator, denominator, options = nil)
87
+ frac_class = Math::Function::Frac
88
+ if denominator.is_a?(frac_class)
89
+ if denominator.parameter_one.is_a?(frac_class)
90
+ recursion_fraction(denominator, numerator, options)
91
+ else
92
+ denominator.parameter_one = frac_class.new(
93
+ unfenced_value(numerator, paren_specific: true),
94
+ unfenced_value(denominator.parameter_one, paren_specific: true),
95
+ options,
96
+ )
97
+ end
98
+ denominator
99
+ else
100
+ frac_class.new(
101
+ unfenced_value(numerator, paren_specific: true),
102
+ unfenced_value(denominator, paren_specific: true),
103
+ options,
104
+ )
105
+ end
106
+ end
107
+
108
+ def recursion_fraction(frac, numerator, options)
109
+ frac_class = Math::Function::Frac
110
+ new_numerator = frac.parameter_one
111
+ if new_numerator.is_a?(frac_class)
112
+ recursion_fraction(new_numerator, numerator, options)
113
+ else
114
+ frac.parameter_one = frac_class.new(
115
+ unfenced_value(numerator, paren_specific: true),
116
+ unfenced_value(frac.parameter_one, paren_specific: true),
117
+ options,
118
+ )
119
+ frac
120
+ end
121
+ end
122
+
123
+ def recursive_sub(sub_script, sub_recursion)
124
+ base_class = Math::Function::Base
125
+ if sub_recursion.is_a?(base_class)
126
+ if sub_recursion.parameter_one.is_a?(base_class)
127
+ base_recursion(sub_script, sub_recursion)
128
+ else
129
+ sub_recursion.parameter_one = base_class.new(sub_script,
130
+ sub_recursion.parameter_one)
131
+ end
132
+ sub_recursion
133
+ else
134
+ base_class.new(
135
+ sub_script,
136
+ sub_recursion,
137
+ )
138
+ end
139
+ end
140
+
141
+ def base_recursion(sub_script, sub_recursion)
142
+ base_class = Math::Function::Base
143
+ new_sub = sub_recursion.parameter_one
144
+ if new_sub.is_a?(base_class)
145
+ base_recursion(sub_script, new_sub)
146
+ else
147
+ sub_recursion.parameter_one = base_class.new(sub_script, new_sub)
148
+ end
149
+ sub_recursion
150
+ end
151
+
152
+ def recursive_sup(sup_script, sup_recursion)
153
+ power_class = Math::Function::Power
154
+ if sup_recursion.is_a?(power_class)
155
+ if sup_recursion.parameter_one.is_a?(power_class)
156
+ sup_recursion(sup_script, sup_recursion)
157
+ else
158
+ sup_recursion.parameter_one = power_class.new(sup_script,
159
+ sup_recursion.parameter_one)
160
+ end
161
+ sup_recursion
162
+ else
163
+ power_class.new(
164
+ sup_script,
165
+ sup_recursion,
166
+ )
167
+ end
168
+ end
169
+
170
+ def sup_recursion(sup_script, sup_recursion)
171
+ power_class = Math::Function::Power
172
+ new_sup = sup_recursion.parameter_one
173
+ if new_sup.is_a?(power_class)
174
+ sup_recursion(sup_script, new_sup)
175
+ else
176
+ sup_recursion.parameter_one = power_class.new(sup_script, new_sup)
177
+ end
178
+ sup_recursion
179
+ end
180
+
181
+ def base_is_prime?(base)
182
+ symbol_prime?(base.parameter_two) ||
183
+ primes_constants.key(base.parameter_two.value)
184
+ end
185
+
186
+ def symbol_prime?(obj)
187
+ obj&.class&.const_defined?(:INPUT) &&
188
+ primes_constants&.key(hexcode_in_input(obj))
189
+ end
190
+
191
+ def base_is_sub_or_sup?(base)
192
+ case base
193
+ when Math::Formula
194
+ base_is_sub_or_sup?(base.value.first)
195
+ when Math::Function::Fenced
196
+ base_is_sub_or_sup?(base.parameter_two.first)
197
+ when Math::Symbols::Symbol, Math::Number
198
+ base.mini_sub_sized || base.mini_sup_sized
199
+ end
200
+ end
201
+
202
+ def identity_matrix(size)
203
+ matrix = Array.new(size) { Array.new(size, 0) }
204
+ size.times { |i| matrix[i][i] = 1 }
205
+ matrix.map do |tr|
206
+ tr.map.with_index do |td, i|
207
+ tr[i] = Math::Function::Td.new([Math::Number.new(td.to_s)])
208
+ end
209
+ Math::Function::Tr.new(tr)
210
+ end
211
+ end
212
+
213
+ def enclosure_attrs(mask)
214
+ raise "enclosure mask is not between 0 and 255" if mask.nil? || mask.negative? || mask > 255
215
+
216
+ ret = ""
217
+ unless mask.nil?
218
+ mask ^= 15
219
+ bin_mask = mask.to_s(2).reverse
220
+ classes = bin_mask.chars.each_with_index.filter_map do |bit, i|
221
+ Plurimath::Utility::MASK_CLASSES[2**i] if bit == "1"
222
+ end
223
+ ret = classes.join(" ")
224
+ end
225
+ ret
226
+ end
227
+
228
+ def slashed_values(value)
229
+ decoded = HTMLEntities.new.decode(value)
230
+ if decoded.to_s.match?(/^\w+/)
231
+ Math::Function::Text.new("\\#{decoded}")
232
+ else
233
+ Math::Symbols::Symbol.new(decoded, true)
234
+ end
235
+ end
236
+
237
+ def sequence_slashed_values(values, lang:)
238
+ values.each.with_index do |value, index|
239
+ decoded = HTMLEntities.new.decode(value.value)
240
+ slashed = if index.zero?
241
+ slashed_values(value.value)
242
+ elsif decoded.match?(/[0-9]/)
243
+ Math::Number.new(decoded)
244
+ else
245
+ symbols_class(
246
+ decoded, lang: lang
247
+ )
248
+ end
249
+ values[index] = slashed
250
+ end
251
+ values
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end
@@ -7,6 +7,7 @@ module Plurimath
7
7
  autoload :Parser, "#{__dir__}/unicode_math/parser"
8
8
  autoload :ParsingRules, "#{__dir__}/unicode_math/parsing_rules"
9
9
  autoload :Transform, "#{__dir__}/unicode_math/transform"
10
+ autoload :Utility, "#{__dir__}/unicode_math/utility"
10
11
 
11
12
  attr_accessor :text
12
13
 
@@ -189,12 +189,12 @@ module Plurimath
189
189
 
190
190
  def insert_f_arg(node, nodes)
191
191
  if !nodes.empty? && !%w[msup msubsup].include?(node.name)
192
- mrow = ox_element("mrow", attributes: { arg: "$f" })
192
+ mrow = XmlHelper.ox_element("mrow", attributes: { arg: "$f" })
193
193
  Plurimath.xml_engine.replace_nodes(
194
194
  node,
195
195
  [
196
196
  node.nodes.first,
197
- update_nodes(mrow, nodes),
197
+ XmlHelper.update_nodes(mrow, nodes),
198
198
  ],
199
199
  )
200
200
  end
@@ -225,8 +225,8 @@ module Plurimath
225
225
  nodes = node&.nodes&.[](1..)
226
226
  return if nodes&.empty?
227
227
 
228
- mrow = ox_element("mrow", attributes: { arg: "n" })
229
- update_nodes(mrow, nodes)
228
+ mrow = XmlHelper.ox_element("mrow", attributes: { arg: "n" })
229
+ XmlHelper.update_nodes(mrow, nodes)
230
230
  replace_nodes = [node.nodes.first.xml_nodes, mrow.xml_nodes.nodes]
231
231
  Plurimath.xml_engine.replace_nodes(node, replace_nodes.flatten)
232
232
  node