plurimath 0.2.0 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +13 -0
- data/.github/workflows/release.yml +22 -0
- data/.gitignore +1 -0
- data/.hound.yml +5 -0
- data/.rubocop.yml +8 -0
- data/AsciiMath-Supported-Data.adoc +2000 -0
- data/Gemfile +3 -0
- data/Latex-Supported-Data.adoc +1879 -0
- data/MathML-Supported-Data.adoc +287 -0
- data/README.adoc +96 -0
- data/lib/plurimath/asciimath/constants.rb +267 -229
- data/lib/plurimath/asciimath/parse.rb +125 -26
- data/lib/plurimath/asciimath/parser.rb +6 -3
- data/lib/plurimath/asciimath/transform.rb +1135 -208
- data/lib/plurimath/asciimath.rb +1 -1
- data/lib/plurimath/html/constants.rb +50 -0
- data/lib/plurimath/html/parse.rb +149 -0
- data/lib/plurimath/html/parser.rb +26 -0
- data/lib/plurimath/html/transform.rb +363 -0
- data/lib/plurimath/html.rb +1 -1
- data/lib/plurimath/latex/constants.rb +3729 -1906
- data/lib/plurimath/latex/parse.rb +167 -51
- data/lib/plurimath/latex/parser.rb +12 -4
- data/lib/plurimath/latex/transform.rb +598 -183
- data/lib/plurimath/math/base.rb +15 -0
- data/lib/plurimath/math/formula.rb +96 -11
- data/lib/plurimath/math/function/bar.rb +34 -0
- data/lib/plurimath/math/function/base.rb +32 -5
- data/lib/plurimath/math/function/binary_function.rb +104 -17
- data/lib/plurimath/math/function/cancel.rb +8 -0
- data/lib/plurimath/math/function/ceil.rb +3 -0
- data/lib/plurimath/math/function/color.rb +16 -6
- data/lib/plurimath/math/function/f.rb +8 -0
- data/lib/plurimath/math/function/fenced.rb +95 -3
- data/lib/plurimath/math/function/floor.rb +15 -0
- data/lib/plurimath/math/function/font_style/bold.rb +37 -0
- data/lib/plurimath/math/function/font_style/double_struck.rb +37 -0
- data/lib/plurimath/math/function/font_style/fraktur.rb +37 -0
- data/lib/plurimath/math/function/font_style/italic.rb +37 -0
- data/lib/plurimath/math/function/font_style/monospace.rb +37 -0
- data/lib/plurimath/math/function/font_style/normal.rb +37 -0
- data/lib/plurimath/math/function/font_style/sans-serif.rb +37 -0
- data/lib/plurimath/math/function/font_style/script.rb +37 -0
- data/lib/plurimath/math/function/font_style.rb +18 -25
- data/lib/plurimath/math/function/frac.rb +35 -5
- data/lib/plurimath/math/function/g.rb +7 -0
- data/lib/plurimath/math/function/hat.rb +12 -0
- data/lib/plurimath/math/function/inf.rb +21 -1
- data/lib/plurimath/math/function/int.rb +23 -2
- data/lib/plurimath/math/function/left.rb +25 -4
- data/lib/plurimath/math/function/lim.rb +40 -2
- data/lib/plurimath/math/function/limits.rb +8 -0
- data/lib/plurimath/math/function/log.rb +61 -4
- data/lib/plurimath/math/function/longdiv.rb +12 -0
- data/lib/plurimath/math/function/mbox.rb +31 -0
- data/lib/plurimath/math/function/menclose.rb +46 -0
- data/lib/plurimath/math/function/merror.rb +12 -0
- data/lib/plurimath/math/function/mod.rb +25 -4
- data/lib/plurimath/math/function/msgroup.rb +37 -0
- data/lib/plurimath/math/function/msline.rb +12 -0
- data/lib/plurimath/math/function/multiscript.rb +30 -0
- data/lib/plurimath/math/function/norm.rb +18 -1
- data/lib/plurimath/math/function/obrace.rb +17 -0
- data/lib/plurimath/math/function/oint.rb +2 -2
- data/lib/plurimath/math/function/over.rb +36 -0
- data/lib/plurimath/math/function/overset.rb +36 -7
- data/lib/plurimath/math/function/phantom.rb +28 -0
- data/lib/plurimath/math/function/power.rb +33 -9
- data/lib/plurimath/math/function/power_base.rb +110 -5
- data/lib/plurimath/math/function/prod.rb +29 -2
- data/lib/plurimath/math/function/right.rb +44 -0
- data/lib/plurimath/math/function/root.rb +27 -4
- data/lib/plurimath/math/function/rule.rb +33 -0
- data/lib/plurimath/math/function/scarries.rb +12 -0
- data/lib/plurimath/math/function/scarry.rb +12 -0
- data/lib/plurimath/math/function/sqrt.rb +24 -2
- data/lib/plurimath/math/function/stackrel.rb +27 -0
- data/lib/plurimath/math/function/substack.rb +7 -1
- data/lib/plurimath/math/function/sum.rb +56 -2
- data/lib/plurimath/math/function/sup.rb +3 -0
- data/lib/plurimath/math/function/table/align.rb +24 -0
- data/lib/plurimath/math/function/table/array.rb +44 -0
- data/lib/plurimath/math/function/table/bmatrix.rb +37 -0
- data/lib/plurimath/math/function/table/matrix.rb +32 -0
- data/lib/plurimath/math/function/table/multline.rb +24 -0
- data/lib/plurimath/math/function/table/pmatrix.rb +24 -0
- data/lib/plurimath/math/function/table/split.rb +24 -0
- data/lib/plurimath/math/function/table/vmatrix.rb +24 -0
- data/lib/plurimath/math/function/table.rb +190 -20
- data/lib/plurimath/math/function/td.rb +27 -9
- data/lib/plurimath/math/function/ternary_function.rb +83 -8
- data/lib/plurimath/math/function/text.rb +45 -8
- data/lib/plurimath/math/function/tr.rb +28 -4
- data/lib/plurimath/math/function/ubrace.rb +17 -0
- data/lib/plurimath/math/function/ul.rb +29 -0
- data/lib/plurimath/math/function/unary_function.rb +85 -7
- data/lib/plurimath/math/function/underline.rb +12 -0
- data/lib/plurimath/math/function/underover.rb +107 -0
- data/lib/plurimath/math/function/underset.rb +39 -0
- data/lib/plurimath/math/function/vec.rb +10 -0
- data/lib/plurimath/math/function.rb +13 -2
- data/lib/plurimath/math/number.rb +11 -3
- data/lib/plurimath/math/symbol.rb +57 -9
- data/lib/plurimath/math/unicode.rb +11 -0
- data/lib/plurimath/math.rb +15 -6
- data/lib/plurimath/mathml/constants.rb +224 -179
- data/lib/plurimath/mathml/parser.rb +24 -7
- data/lib/plurimath/mathml/transform.rb +249 -148
- data/lib/plurimath/mathml.rb +1 -1
- data/lib/plurimath/omml/parser.rb +42 -0
- data/lib/plurimath/omml/transform.rb +278 -0
- data/lib/plurimath/omml.rb +1 -1
- data/lib/plurimath/unitsml.rb +4 -0
- data/lib/plurimath/utility.rb +395 -0
- data/lib/plurimath/version.rb +1 -1
- data/plurimath.gemspec +1 -0
- metadata +66 -9
- data/.github/workflows/test.yml +0 -36
- data/README.md +0 -40
- data/lib/plurimath/mathml/parse.rb +0 -63
@@ -0,0 +1,278 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "parslet"
|
4
|
+
module Plurimath
|
5
|
+
class Omml
|
6
|
+
class Transform < Parslet::Transform
|
7
|
+
rule(t: simple(:t)) { Utility.text_classes(t) }
|
8
|
+
rule(e: subtree(:e)) { e.flatten.compact }
|
9
|
+
rule(i: sequence(:i)) { i }
|
10
|
+
rule(e: sequence(:e)) { e.flatten.compact }
|
11
|
+
|
12
|
+
rule(val: simple(:val)) { val }
|
13
|
+
rule(dPr: subtree(:dpr)) { dpr }
|
14
|
+
rule(num: subtree(:num)) { num }
|
15
|
+
rule(den: subtree(:den)) { den }
|
16
|
+
rule(rPr: subtree(:rPr)) { nil }
|
17
|
+
rule(fPr: subtree(:fPr)) { nil }
|
18
|
+
rule(mpr: subtree(:mpr)) { nil }
|
19
|
+
rule(mPr: subtree(:mPr)) { nil }
|
20
|
+
rule(box: subtree(:box)) { box.flatten.compact }
|
21
|
+
rule(deg: sequence(:deg)) { Utility.filter_values(deg) }
|
22
|
+
rule(sub: sequence(:sub)) { Utility.filter_values(sub) }
|
23
|
+
rule(sup: sequence(:sup)) { Utility.filter_values(sup) }
|
24
|
+
rule(boxPr: subtree(:box)) { nil }
|
25
|
+
rule(argPr: subtree(:arg)) { nil }
|
26
|
+
rule(accPr: subtree(:acc)) { acc.flatten.compact }
|
27
|
+
|
28
|
+
rule(sSubPr: subtree(:arg)) { nil }
|
29
|
+
rule(space: simple(:space)) { space }
|
30
|
+
rule(radPr: subtree(:radpr)) { nil }
|
31
|
+
rule(barPr: subtree(:barpr)) { barpr }
|
32
|
+
rule(oMath: subtree(:omath)) { omath.flatten.compact }
|
33
|
+
rule(fName: subtree(:fname)) { fname }
|
34
|
+
rule(oMath: sequence(:omath)) { omath }
|
35
|
+
rule(limLoc: simple(:limLoc)) { limLoc }
|
36
|
+
rule(begChr: simple(:begChr)) { Math::Symbol.new(begChr) }
|
37
|
+
rule(endChr: simple(:endChr)) { Math::Symbol.new(endChr) }
|
38
|
+
|
39
|
+
rule(rFonts: subtree(:rFonts)) { nil }
|
40
|
+
rule(sSupPr: subtree(:ssuppr)) { nil }
|
41
|
+
rule(sPrePr: subtree(:sprepr)) { nil }
|
42
|
+
rule(funcPr: subtree(:funcpr)) { nil }
|
43
|
+
rule(naryPr: subtree(:narypr)) { narypr }
|
44
|
+
rule(subHide: simple(:subHide)) { nil }
|
45
|
+
rule(supHide: simple(:supHide)) { nil }
|
46
|
+
rule(degHide: simple(:degHide)) { nil }
|
47
|
+
rule(ctrlPr: sequence(:ctrlpr)) { ctrlpr }
|
48
|
+
rule(eqArrPr: subtree(:eqarrpr)) { eqarrpr.flatten.compact }
|
49
|
+
|
50
|
+
rule(sequence: subtree(:sequence)) { sequence.flatten.compact }
|
51
|
+
rule(limUppPr: subtree(:limUppPr)) { nil }
|
52
|
+
rule(limLowPr: subtree(:limLowpr)) { nil }
|
53
|
+
rule(sequence: sequence(:sequence)) { sequence }
|
54
|
+
rule(sSubSupPr: subtree(:sSubSuppr)) { nil }
|
55
|
+
|
56
|
+
rule(groupChrPr: subtree(:groupchrpr)) { groupchrpr }
|
57
|
+
rule(borderBoxPr: subtree(:borderBoxpr)) { nil }
|
58
|
+
rule(lastRenderedPageBreak: sequence(:break)) { nil }
|
59
|
+
|
60
|
+
rule(f: subtree(:f)) do
|
61
|
+
Math::Function::Frac.new(
|
62
|
+
Utility.filter_values(f[1]),
|
63
|
+
Utility.filter_values(f[2]),
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
rule(r: sequence(:r)) do
|
68
|
+
Math::Formula.new(
|
69
|
+
r.flatten.compact,
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
rule(m: sequence(:m)) do
|
74
|
+
Math::Function::Table.new(
|
75
|
+
m.flatten.compact,
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
rule(t: sequence(:t)) do
|
80
|
+
if t.empty?
|
81
|
+
Math::Function::Text.new
|
82
|
+
else
|
83
|
+
Utility.text_classes(t)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
rule(d: subtree(:data)) do
|
88
|
+
fenced = data.flatten.compact
|
89
|
+
open_paren = fenced.shift if fenced.first.class_name == "symbol"
|
90
|
+
close_paren = fenced.shift if fenced.first.class_name == "symbol"
|
91
|
+
fenced_value = fenced
|
92
|
+
Math::Function::Fenced.new(
|
93
|
+
open_paren,
|
94
|
+
fenced_value,
|
95
|
+
close_paren,
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
rule(mr: subtree(:mr)) do
|
100
|
+
row = []
|
101
|
+
mr.each do |td|
|
102
|
+
row << Math::Function::Td.new(
|
103
|
+
td.is_a?(Array) ? td : [td],
|
104
|
+
)
|
105
|
+
end
|
106
|
+
Math::Function::Tr.new(row)
|
107
|
+
end
|
108
|
+
|
109
|
+
rule(lim: sequence(:lim)) do
|
110
|
+
if lim.any?(String)
|
111
|
+
Utility.text_classes(lim)
|
112
|
+
else
|
113
|
+
Utility.filter_values(lim)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
rule(acc: subtree(:acc)) do
|
118
|
+
acc_value = acc.flatten.compact
|
119
|
+
chr = Utility.find_pos_chr(acc_value, :chr)
|
120
|
+
chr_value = chr ? chr[:chr] : "^"
|
121
|
+
Math::Function::Overset.new(
|
122
|
+
Math::Symbol.new(chr_value),
|
123
|
+
Utility.filter_values(acc.last),
|
124
|
+
)
|
125
|
+
end
|
126
|
+
|
127
|
+
rule(func: subtree(:func)) do
|
128
|
+
func_name = func.flatten.compact
|
129
|
+
class_object = Utility.find_class_name(func_name.first)
|
130
|
+
if class_object
|
131
|
+
class_object.new(func_name.last)
|
132
|
+
else
|
133
|
+
Math::Formula.new(
|
134
|
+
func_name,
|
135
|
+
)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
rule(nary: subtree(:nary)) do
|
140
|
+
Math::Formula.new(
|
141
|
+
[
|
142
|
+
Utility.nary_fonts(nary),
|
143
|
+
Utility.filter_values(nary[3]),
|
144
|
+
],
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
rule(groupChr: subtree(:groupchr)) do
|
149
|
+
chr_pos = groupchr.first
|
150
|
+
pos = Utility.find_pos_chr(chr_pos, :pos)
|
151
|
+
chr = Utility.find_pos_chr(chr_pos, :chr)
|
152
|
+
if pos&.value?("top")
|
153
|
+
Math::Function::Overset.new(
|
154
|
+
Math::Symbol.new(chr ? chr[:chr] : ""),
|
155
|
+
Utility.filter_values(groupchr[1]),
|
156
|
+
)
|
157
|
+
else
|
158
|
+
Math::Function::Underset.new(
|
159
|
+
Math::Symbol.new(chr ? chr[:chr] : "⏟"),
|
160
|
+
Utility.filter_values(groupchr[1]),
|
161
|
+
)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
rule(sSubSup: subtree(:sSubSup)) do
|
166
|
+
subsup = sSubSup.flatten.compact
|
167
|
+
subsup.each_with_index do |object, ind|
|
168
|
+
subsup[ind] = Utility.mathml_unary_classes([object]) if object.is_a?(String)
|
169
|
+
end
|
170
|
+
Math::Function::PowerBase.new(
|
171
|
+
subsup[0],
|
172
|
+
subsup[1],
|
173
|
+
subsup[2],
|
174
|
+
)
|
175
|
+
end
|
176
|
+
|
177
|
+
rule(sSup: subtree(:ssup)) do
|
178
|
+
sup = ssup.flatten.compact
|
179
|
+
Math::Function::Power.new(
|
180
|
+
sup[0],
|
181
|
+
sup[1],
|
182
|
+
)
|
183
|
+
end
|
184
|
+
|
185
|
+
rule(rad: subtree(:rad)) do
|
186
|
+
if rad[1].nil?
|
187
|
+
Math::Function::Sqrt.new(
|
188
|
+
Utility.filter_values(rad[2]),
|
189
|
+
)
|
190
|
+
else
|
191
|
+
Math::Function::Root.new(
|
192
|
+
Utility.filter_values(rad[2]),
|
193
|
+
rad[1],
|
194
|
+
)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
rule(sSub: subtree(:ssub)) do
|
199
|
+
sub = ssub.flatten.compact
|
200
|
+
Plurimath::Math::Function::Base.new(
|
201
|
+
sub[0],
|
202
|
+
sub[1],
|
203
|
+
)
|
204
|
+
end
|
205
|
+
|
206
|
+
rule(limUpp: subtree(:limUpp)) do
|
207
|
+
lim_values = limUpp.flatten.compact
|
208
|
+
first_value = lim_values[0]
|
209
|
+
Math::Function::Overset.new(
|
210
|
+
first_value,
|
211
|
+
lim_values[1],
|
212
|
+
)
|
213
|
+
end
|
214
|
+
|
215
|
+
rule(limLow: subtree(:lim)) do
|
216
|
+
Math::Function::Underset.new(
|
217
|
+
Utility.filter_values(lim[1]),
|
218
|
+
Utility.filter_values(lim[2]),
|
219
|
+
)
|
220
|
+
end
|
221
|
+
|
222
|
+
rule(borderBox: subtree(:box)) do
|
223
|
+
Math::Function::Menclose.new(
|
224
|
+
"longdiv",
|
225
|
+
Utility.filter_values(box[1]),
|
226
|
+
)
|
227
|
+
end
|
228
|
+
|
229
|
+
rule(bar: subtree(:bar)) do
|
230
|
+
barpr = bar&.flatten&.compact
|
231
|
+
pospr = Utility.find_pos_chr(bar.first, :pos)
|
232
|
+
class_name = if pospr&.value?("top")
|
233
|
+
Math::Function::Bar
|
234
|
+
else
|
235
|
+
Math::Function::Ul
|
236
|
+
end
|
237
|
+
class_name.new(barpr.last)
|
238
|
+
end
|
239
|
+
|
240
|
+
rule(sPre: subtree(:spre)) do
|
241
|
+
pre = spre.flatten.compact
|
242
|
+
Math::Function::Multiscript.new(
|
243
|
+
pre[2],
|
244
|
+
pre[0],
|
245
|
+
pre[1],
|
246
|
+
)
|
247
|
+
end
|
248
|
+
|
249
|
+
rule(eqArr: subtree(:eqArr)) do
|
250
|
+
table_value = []
|
251
|
+
eqArr.delete_at(0)
|
252
|
+
eqArr.each do |value|
|
253
|
+
table_value << Math::Function::Tr.new(
|
254
|
+
[
|
255
|
+
Math::Function::Td.new(
|
256
|
+
value.is_a?(Array) ? value : [value],
|
257
|
+
),
|
258
|
+
],
|
259
|
+
)
|
260
|
+
end
|
261
|
+
Math::Function::Table.new(table_value)
|
262
|
+
end
|
263
|
+
|
264
|
+
rule(ascii: simple(:ascii),
|
265
|
+
hAnsi: simple(:hansi)) do
|
266
|
+
nil
|
267
|
+
end
|
268
|
+
|
269
|
+
rule(attributes: simple(:attributes), value: sequence(:value)) do
|
270
|
+
if value.any? || attributes == "preserve"
|
271
|
+
value.any? ? value : [" "]
|
272
|
+
else
|
273
|
+
attributes
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
data/lib/plurimath/omml.rb
CHANGED
data/lib/plurimath/unitsml.rb
CHANGED
@@ -0,0 +1,395 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Plurimath
|
4
|
+
class Utility
|
5
|
+
FONT_STYLES = {
|
6
|
+
"double-struck": Math::Function::FontStyle::DoubleStruck,
|
7
|
+
"sans-serif": Math::Function::FontStyle::SansSerif,
|
8
|
+
monospace: Math::Function::FontStyle::Monospace,
|
9
|
+
fraktur: Math::Function::FontStyle::Fraktur,
|
10
|
+
script: Math::Function::FontStyle::Script,
|
11
|
+
normal: Math::Function::FontStyle::Normal,
|
12
|
+
bold: Math::Function::FontStyle::Bold,
|
13
|
+
mathfrak: Math::Function::FontStyle::Fraktur,
|
14
|
+
mathcal: Math::Function::FontStyle::Script,
|
15
|
+
mathbb: Math::Function::FontStyle::DoubleStruck,
|
16
|
+
mathtt: Math::Function::FontStyle::Monospace,
|
17
|
+
mathsf: Math::Function::FontStyle::SansSerif,
|
18
|
+
mathrm: Math::Function::FontStyle::Normal,
|
19
|
+
textrm: Math::Function::FontStyle::Normal,
|
20
|
+
mathbf: Math::Function::FontStyle::Bold,
|
21
|
+
textbf: Math::Function::FontStyle::Bold,
|
22
|
+
bbb: Math::Function::FontStyle::DoubleStruck,
|
23
|
+
cal: Math::Function::FontStyle::Script,
|
24
|
+
bf: Math::Function::FontStyle::Bold,
|
25
|
+
sf: Math::Function::FontStyle::SansSerif,
|
26
|
+
tt: Math::Function::FontStyle::Monospace,
|
27
|
+
fr: Math::Function::FontStyle::Fraktur,
|
28
|
+
rm: Math::Function::FontStyle::Normal,
|
29
|
+
cc: Math::Function::FontStyle::Script,
|
30
|
+
ii: Math::Function::FontStyle::Italic,
|
31
|
+
bb: Math::Function::FontStyle::Bold,
|
32
|
+
}.freeze
|
33
|
+
ALIGNMENT_LETTERS = {
|
34
|
+
c: "center",
|
35
|
+
r: "right",
|
36
|
+
l: "left",
|
37
|
+
}.freeze
|
38
|
+
UNARY_CLASSES = %w[
|
39
|
+
arccos
|
40
|
+
arcsin
|
41
|
+
arctan
|
42
|
+
right
|
43
|
+
sech
|
44
|
+
sinh
|
45
|
+
tanh
|
46
|
+
cosh
|
47
|
+
coth
|
48
|
+
csch
|
49
|
+
left
|
50
|
+
max
|
51
|
+
min
|
52
|
+
sec
|
53
|
+
sin
|
54
|
+
deg
|
55
|
+
det
|
56
|
+
dim
|
57
|
+
exp
|
58
|
+
gcd
|
59
|
+
glb
|
60
|
+
lub
|
61
|
+
tan
|
62
|
+
cos
|
63
|
+
cot
|
64
|
+
csc
|
65
|
+
ln
|
66
|
+
lg
|
67
|
+
f
|
68
|
+
g
|
69
|
+
].freeze
|
70
|
+
|
71
|
+
class << self
|
72
|
+
def organize_table(array, column_align: nil, options: nil)
|
73
|
+
table = []
|
74
|
+
table_data = []
|
75
|
+
table_row = []
|
76
|
+
table_separators = ["&", "\\\\"].freeze
|
77
|
+
organize_options(array, column_align) if options
|
78
|
+
string_columns = column_align&.map(&:value)
|
79
|
+
array.each do |data|
|
80
|
+
if data.is_a?(Math::Symbol) && table_separators.include?(data.value)
|
81
|
+
table_row << Math::Function::Td.new(filter_table_data(table_data).compact)
|
82
|
+
table_data = []
|
83
|
+
if data.value == "\\\\"
|
84
|
+
organize_tds(table_row.flatten, string_columns.dup, options)
|
85
|
+
table << Math::Function::Tr.new(table_row)
|
86
|
+
table_row = []
|
87
|
+
end
|
88
|
+
next
|
89
|
+
end
|
90
|
+
table_data << data
|
91
|
+
end
|
92
|
+
table_row << Math::Function::Td.new(table_data.compact) if table_data
|
93
|
+
unless table_row.nil? || table_row.empty?
|
94
|
+
organize_tds(table_row.flatten, string_columns.dup, options)
|
95
|
+
table << Math::Function::Tr.new(table_row)
|
96
|
+
end
|
97
|
+
table_separator(string_columns, table, symbol: "|") unless column_align.nil? || column_align.empty?
|
98
|
+
table
|
99
|
+
end
|
100
|
+
|
101
|
+
def organize_options(table_data, column_align)
|
102
|
+
return column_align if column_align.length <= 1
|
103
|
+
|
104
|
+
align = [column_align&.shift]
|
105
|
+
table_data.insert(0, *column_align)
|
106
|
+
align
|
107
|
+
end
|
108
|
+
|
109
|
+
def table_options(table_data)
|
110
|
+
rowline = ""
|
111
|
+
table_data.map do |tr|
|
112
|
+
if symbol_value(tr&.parameter_one&.first&.parameter_one&.first, "⎯")
|
113
|
+
rowline += "solid "
|
114
|
+
else
|
115
|
+
rowline += "none "
|
116
|
+
end
|
117
|
+
end
|
118
|
+
options = { rowline: rowline.strip } if rowline.include?("solid")
|
119
|
+
options || {}
|
120
|
+
end
|
121
|
+
|
122
|
+
def organize_tds(tr_array, column_align, options)
|
123
|
+
return tr_array if column_align.nil? || column_align.empty?
|
124
|
+
|
125
|
+
column_align.reject! { |string| string == "|" }
|
126
|
+
column_align = column_align * tr_array.length if options
|
127
|
+
tr_array.map.with_index do |td, ind|
|
128
|
+
columnalign = ALIGNMENT_LETTERS[column_align[ind]&.to_sym]
|
129
|
+
td.parameter_two = { columnalign: columnalign } if columnalign
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def filter_table_data(table_data)
|
134
|
+
table_data.each_with_index do |object, ind|
|
135
|
+
if symbol_value(object, "-")
|
136
|
+
table_data[ind] = Math::Formula.new(
|
137
|
+
[object, table_data.delete_at(ind.next)],
|
138
|
+
)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
table_data
|
142
|
+
end
|
143
|
+
|
144
|
+
def get_table_class(text)
|
145
|
+
Object.const_get(
|
146
|
+
"Plurimath::Math::Function::Table::#{text.to_s.capitalize}",
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
def sub_sup_method?(sub_sup)
|
151
|
+
if sub_sup.methods.include?(:class_name)
|
152
|
+
Html::Constants::SUB_SUP_CLASSES.value?(sub_sup.class_name.to_sym)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def get_class(text)
|
157
|
+
text = text.to_s.split("_").map(&:capitalize).join
|
158
|
+
Object.const_get(
|
159
|
+
"Plurimath::Math::Function::#{text}",
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
def ox_element(node, attributes: [], namespace: "")
|
164
|
+
namespace = "#{namespace}:" unless namespace.empty?
|
165
|
+
|
166
|
+
element = Ox::Element.new("#{namespace}#{node}")
|
167
|
+
attributes&.each do |attr_key, attr_value|
|
168
|
+
element[attr_key] = attr_value
|
169
|
+
end
|
170
|
+
element
|
171
|
+
end
|
172
|
+
|
173
|
+
def rpr_element(wi_tag: false)
|
174
|
+
rpr_element = ox_element("rPr", namespace: "w")
|
175
|
+
attributes = { "w:ascii": "Cambria Math", "w:hAnsi": "Cambria Math" }
|
176
|
+
rpr_element << ox_element(
|
177
|
+
"rFonts",
|
178
|
+
namespace: "w",
|
179
|
+
attributes: attributes,
|
180
|
+
)
|
181
|
+
rpr_element << ox_element("i", namespace: "w") if wi_tag
|
182
|
+
rpr_element
|
183
|
+
end
|
184
|
+
|
185
|
+
def update_nodes(element, nodes)
|
186
|
+
nodes&.each { |node| element << node unless node.nil? }
|
187
|
+
element
|
188
|
+
end
|
189
|
+
|
190
|
+
def pr_element(main_tag, wi_tag, namespace: "")
|
191
|
+
tag_name = "#{main_tag}Pr"
|
192
|
+
ox_element(
|
193
|
+
tag_name,
|
194
|
+
namespace: namespace,
|
195
|
+
) << rpr_element(wi_tag: wi_tag)
|
196
|
+
end
|
197
|
+
|
198
|
+
def filter_values(array)
|
199
|
+
return array unless array.is_a?(Array)
|
200
|
+
|
201
|
+
array = array.flatten.compact
|
202
|
+
if array.length > 1
|
203
|
+
return Math::Formula.new(array)
|
204
|
+
end
|
205
|
+
|
206
|
+
array.first
|
207
|
+
end
|
208
|
+
|
209
|
+
def text_classes(text)
|
210
|
+
return nil if text.empty?
|
211
|
+
|
212
|
+
text = filter_values(text) unless text.is_a?(String)
|
213
|
+
if text.scan(/[[:digit:]]/).length == text.length
|
214
|
+
Math::Number.new(text)
|
215
|
+
elsif text.match?(/[a-zA-Z]/)
|
216
|
+
Math::Function::Text.new(text)
|
217
|
+
else
|
218
|
+
Math::Symbol.new(text)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def nary_fonts(nary)
|
223
|
+
narypr = nary.first.flatten.compact
|
224
|
+
subsup = narypr.any?("undOvr") ? "underover" : "power_base"
|
225
|
+
get_class(subsup).new(
|
226
|
+
Math::Symbol.new(narypr.any?(Hash) ? narypr.first[:chr] : "∫"),
|
227
|
+
nary[1],
|
228
|
+
nary[2],
|
229
|
+
)
|
230
|
+
end
|
231
|
+
|
232
|
+
def find_class_name(object)
|
233
|
+
new_object = object.value.first.parameter_one if object.is_a?(Math::Formula)
|
234
|
+
get_class(new_object) unless new_object.nil?
|
235
|
+
end
|
236
|
+
|
237
|
+
def find_pos_chr(fonts_array, key)
|
238
|
+
fonts_array.find { |d| d.is_a?(Hash) && d[key] }
|
239
|
+
end
|
240
|
+
|
241
|
+
def td_values(objects, slicer)
|
242
|
+
sliced = objects.slice_when { |object, _| symbol_value(object, slicer) }
|
243
|
+
tds = sliced.map do |slice|
|
244
|
+
Math::Function::Td.new(
|
245
|
+
slice.delete_if { |d| symbol_value(d, slicer) }.compact,
|
246
|
+
)
|
247
|
+
end
|
248
|
+
tds << Math::Function::Td.new([]) if symbol_value(objects.last, slicer)
|
249
|
+
tds
|
250
|
+
end
|
251
|
+
|
252
|
+
def symbol_value(object, value)
|
253
|
+
object.is_a?(Math::Symbol) && object.value.include?(value)
|
254
|
+
end
|
255
|
+
|
256
|
+
def td_value(td_object)
|
257
|
+
if td_object.is_a?(String) && td_object.empty?
|
258
|
+
return Math::Function::Text.new(nil)
|
259
|
+
end
|
260
|
+
|
261
|
+
td_object
|
262
|
+
end
|
263
|
+
|
264
|
+
def mathml_unary_classes(text_array)
|
265
|
+
return [] if text_array.empty?
|
266
|
+
|
267
|
+
compacted = text_array.compact
|
268
|
+
string = if compacted.count == 1
|
269
|
+
compacted.first
|
270
|
+
else
|
271
|
+
compacted.join
|
272
|
+
end
|
273
|
+
return string unless string.is_a?(String)
|
274
|
+
|
275
|
+
classes = Mathml::Constants::CLASSES
|
276
|
+
unicode = string_to_html_entity(string)
|
277
|
+
symbol = Mathml::Constants::UNICODE_SYMBOLS[unicode.strip.to_sym]
|
278
|
+
if classes.include?(symbol&.strip)
|
279
|
+
get_class(symbol.strip).new
|
280
|
+
elsif classes.any?(string&.strip)
|
281
|
+
get_class(string.strip).new
|
282
|
+
else
|
283
|
+
Math::Symbol.new(unicode)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def string_to_html_entity(string)
|
288
|
+
entities = HTMLEntities.new
|
289
|
+
entities.encode(string, :hexadecimal)
|
290
|
+
end
|
291
|
+
|
292
|
+
def table_separator(separator, value, symbol: "solid")
|
293
|
+
sep_symbol = Math::Function::Td.new([Math::Symbol.new("|")])
|
294
|
+
separator&.each_with_index do |sep, ind|
|
295
|
+
next unless sep == symbol
|
296
|
+
|
297
|
+
value.map do |val|
|
298
|
+
val.parameter_one.insert((ind + 1), sep_symbol) if symbol == "solid"
|
299
|
+
val.parameter_one.insert(ind, sep_symbol) if symbol == "|"
|
300
|
+
(val.parameter_one[val.parameter_one.index(nil)] = Math::Function::Td.new([])) rescue nil
|
301
|
+
val
|
302
|
+
end
|
303
|
+
end
|
304
|
+
value
|
305
|
+
end
|
306
|
+
|
307
|
+
def join_attr_value(attrs, value)
|
308
|
+
if value.any?(String)
|
309
|
+
new_value = mathml_unary_classes(value)
|
310
|
+
array_value = Array(new_value)
|
311
|
+
attrs.nil? ? array_value : join_attr_value(attrs, array_value)
|
312
|
+
elsif attrs.nil?
|
313
|
+
value
|
314
|
+
elsif attrs.is_a?(Math::Function::Menclose)
|
315
|
+
attrs.parameter_two = filter_values(value)
|
316
|
+
attrs
|
317
|
+
elsif attrs.is_a?(Math::Function::Fenced)
|
318
|
+
attrs.parameter_two = value
|
319
|
+
attrs
|
320
|
+
elsif attrs.is_a?(Math::Function::FontStyle)
|
321
|
+
attrs.parameter_one = filter_values(value)
|
322
|
+
attrs
|
323
|
+
elsif attrs.is_a?(Math::Function::Color)
|
324
|
+
color_value = filter_values(value)
|
325
|
+
if attrs.parameter_two
|
326
|
+
attrs.parameter_two.parameter_one = color_value
|
327
|
+
else
|
328
|
+
attrs.parameter_two = color_value
|
329
|
+
end
|
330
|
+
attrs
|
331
|
+
elsif ["solid", "none"].include?(attrs.split.first.downcase)
|
332
|
+
table_separator(attrs.split, value)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
def multiscript(values)
|
337
|
+
values.slice_before("mprescripts").map do |value|
|
338
|
+
base_value = value.shift
|
339
|
+
part_val = value.partition.with_index { |_, i| i.even? }
|
340
|
+
first_value = part_val[0].empty? ? nil : filter_values(part_val[0])
|
341
|
+
second_value = part_val[1].empty? ? nil : filter_values(part_val[1])
|
342
|
+
if base_value.to_s.include?("mprescripts")
|
343
|
+
[first_value, second_value]
|
344
|
+
else
|
345
|
+
Math::Function::PowerBase.new(
|
346
|
+
base_value,
|
347
|
+
first_value,
|
348
|
+
second_value,
|
349
|
+
)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
def unfenced_value(object)
|
355
|
+
case object
|
356
|
+
when Math::Function::Fenced
|
357
|
+
value = filter_values(object.parameter_two)
|
358
|
+
unfenced_value(value)
|
359
|
+
when Array
|
360
|
+
filter_values(object)
|
361
|
+
else
|
362
|
+
object
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def frac_values(object)
|
367
|
+
case object
|
368
|
+
when Math::Formula
|
369
|
+
object.value.any? { |d| symbol_value(d, ",") }
|
370
|
+
when Array
|
371
|
+
object.any? { |d| symbol_value(d, ",") }
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
def table_td(object)
|
376
|
+
new_object = case object
|
377
|
+
when Math::Function::Td
|
378
|
+
object
|
379
|
+
else
|
380
|
+
Math::Function::Td.new([object])
|
381
|
+
end
|
382
|
+
Array(new_object)
|
383
|
+
end
|
384
|
+
|
385
|
+
def symbol_object(value)
|
386
|
+
value = case value
|
387
|
+
when "ℒ" then "{:"
|
388
|
+
when "ℛ" then ":}"
|
389
|
+
else value
|
390
|
+
end
|
391
|
+
Math::Symbol.new(value)
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
data/lib/plurimath/version.rb
CHANGED