plurimath 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.rspec +3 -0
  4. data/.rspec-opal +11 -0
  5. data/Gemfile +4 -0
  6. data/Rakefile +11 -0
  7. data/lib/plurimath/asciimath/parse.rb +3 -2
  8. data/lib/plurimath/asciimath/transform.rb +47 -5
  9. data/lib/plurimath/latex/constants.rb +5 -1
  10. data/lib/plurimath/latex/parse.rb +20 -11
  11. data/lib/plurimath/latex/transform.rb +32 -14
  12. data/lib/plurimath/math/core.rb +212 -10
  13. data/lib/plurimath/math/formula.rb +154 -40
  14. data/lib/plurimath/math/function/abs.rb +28 -15
  15. data/lib/plurimath/math/function/bar.rb +5 -0
  16. data/lib/plurimath/math/function/base.rb +22 -2
  17. data/lib/plurimath/math/function/binary_function.rb +38 -12
  18. data/lib/plurimath/math/function/ceil.rb +24 -9
  19. data/lib/plurimath/math/function/color.rb +14 -0
  20. data/lib/plurimath/math/function/ddot.rb +6 -1
  21. data/lib/plurimath/math/function/deg.rb +4 -1
  22. data/lib/plurimath/math/function/det.rb +4 -1
  23. data/lib/plurimath/math/function/dim.rb +4 -1
  24. data/lib/plurimath/math/function/dot.rb +5 -0
  25. data/lib/plurimath/math/function/exp.rb +4 -1
  26. data/lib/plurimath/math/function/fenced.rb +51 -15
  27. data/lib/plurimath/math/function/floor.rb +24 -14
  28. data/lib/plurimath/math/function/font_style.rb +63 -8
  29. data/lib/plurimath/math/function/frac.rb +38 -18
  30. data/lib/plurimath/math/function/gcd.rb +4 -1
  31. data/lib/plurimath/math/function/glb.rb +8 -1
  32. data/lib/plurimath/math/function/hat.rb +16 -5
  33. data/lib/plurimath/math/function/hom.rb +4 -1
  34. data/lib/plurimath/math/function/inf.rb +16 -0
  35. data/lib/plurimath/math/function/int.rb +35 -9
  36. data/lib/plurimath/math/function/ker.rb +4 -1
  37. data/lib/plurimath/math/function/lcm.rb +17 -1
  38. data/lib/plurimath/math/function/left.rb +20 -2
  39. data/lib/plurimath/math/function/lg.rb +4 -1
  40. data/lib/plurimath/math/function/lim.rb +16 -0
  41. data/lib/plurimath/math/function/liminf.rb +4 -1
  42. data/lib/plurimath/math/function/limits.rb +29 -9
  43. data/lib/plurimath/math/function/limsup.rb +4 -1
  44. data/lib/plurimath/math/function/linebreak.rb +95 -0
  45. data/lib/plurimath/math/function/ln.rb +4 -1
  46. data/lib/plurimath/math/function/log.rb +27 -12
  47. data/lib/plurimath/math/function/longdiv.rb +19 -0
  48. data/lib/plurimath/math/function/lub.rb +4 -1
  49. data/lib/plurimath/math/function/max.rb +4 -1
  50. data/lib/plurimath/math/function/mbox.rb +8 -7
  51. data/lib/plurimath/math/function/menclose.rb +6 -0
  52. data/lib/plurimath/math/function/merror.rb +12 -3
  53. data/lib/plurimath/math/function/min.rb +4 -1
  54. data/lib/plurimath/math/function/mod.rb +48 -15
  55. data/lib/plurimath/math/function/msgroup.rb +32 -0
  56. data/lib/plurimath/math/function/msline.rb +10 -0
  57. data/lib/plurimath/math/function/multiscript.rb +27 -0
  58. data/lib/plurimath/math/function/nary.rb +128 -0
  59. data/lib/plurimath/math/function/norm.rb +24 -15
  60. data/lib/plurimath/math/function/obrace.rb +5 -0
  61. data/lib/plurimath/math/function/oint.rb +48 -20
  62. data/lib/plurimath/math/function/over.rb +29 -10
  63. data/lib/plurimath/math/function/overset.rb +19 -10
  64. data/lib/plurimath/math/function/phantom.rb +24 -6
  65. data/lib/plurimath/math/function/power.rb +19 -4
  66. data/lib/plurimath/math/function/power_base.rb +34 -33
  67. data/lib/plurimath/math/function/prod.rb +43 -23
  68. data/lib/plurimath/math/function/right.rb +20 -2
  69. data/lib/plurimath/math/function/root.rb +6 -0
  70. data/lib/plurimath/math/function/rule.rb +8 -1
  71. data/lib/plurimath/math/function/scarries.rb +14 -0
  72. data/lib/plurimath/math/function/semantics.rb +15 -0
  73. data/lib/plurimath/math/function/sqrt.rb +5 -0
  74. data/lib/plurimath/math/function/stackrel.rb +14 -0
  75. data/lib/plurimath/math/function/substack.rb +18 -51
  76. data/lib/plurimath/math/function/sum.rb +36 -12
  77. data/lib/plurimath/math/function/sup.rb +11 -2
  78. data/lib/plurimath/math/function/table/array.rb +1 -1
  79. data/lib/plurimath/math/function/table/matrix.rb +4 -0
  80. data/lib/plurimath/math/function/table.rb +62 -26
  81. data/lib/plurimath/math/function/td.rb +42 -4
  82. data/lib/plurimath/math/function/ternary_function.rb +48 -10
  83. data/lib/plurimath/math/function/text.rb +25 -3
  84. data/lib/plurimath/math/function/tilde.rb +5 -0
  85. data/lib/plurimath/math/function/tr.rb +29 -1
  86. data/lib/plurimath/math/function/ubrace.rb +5 -0
  87. data/lib/plurimath/math/function/unary_function.rb +115 -29
  88. data/lib/plurimath/math/function/underover.rb +27 -58
  89. data/lib/plurimath/math/function/underset.rb +25 -9
  90. data/lib/plurimath/math/function/vec.rb +45 -0
  91. data/lib/plurimath/math/function.rb +7 -5
  92. data/lib/plurimath/math/number.rb +12 -8
  93. data/lib/plurimath/math/symbol.rb +25 -13
  94. data/lib/plurimath/math.rb +1 -3
  95. data/lib/plurimath/mathml/parser.rb +6 -4
  96. data/lib/plurimath/mathml/transform.rb +26 -19
  97. data/lib/plurimath/omml/parser.rb +3 -3
  98. data/lib/plurimath/omml/transform.rb +34 -21
  99. data/lib/plurimath/setup/oga.rb +5 -0
  100. data/lib/plurimath/setup/opal.rb.erb +8 -0
  101. data/lib/plurimath/setup/ox.rb +5 -0
  102. data/lib/plurimath/unitsml.rb +2 -1
  103. data/lib/plurimath/utility.rb +77 -41
  104. data/lib/plurimath/version.rb +1 -1
  105. data/lib/plurimath/xml_engine/oga.rb +246 -0
  106. data/lib/plurimath/xml_engine/ox.rb +29 -0
  107. data/lib/plurimath/xml_engine.rb +6 -0
  108. data/lib/plurimath.rb +12 -2
  109. metadata +12 -3
  110. data/lib/plurimath/math/function/scarry.rb +0 -12
@@ -5,12 +5,12 @@ module Plurimath
5
5
  class Symbol < Core
6
6
  attr_accessor :value
7
7
 
8
- def initialize(sym)
8
+ def initialize(sym = nil)
9
9
  @value = sym.is_a?(Parslet::Slice) ? sym.to_s : sym
10
10
  end
11
11
 
12
12
  def ==(object)
13
- object.value == value
13
+ object.respond_to?(:value) && object.value == value
14
14
  end
15
15
 
16
16
  def to_asciimath
@@ -29,11 +29,9 @@ module Plurimath
29
29
  mi_tag = Utility.ox_element("mi")
30
30
  return mi_tag if ["{:", ":}"].include?(value)
31
31
 
32
- unicodes = Mathml::Constants::UNICODE_SYMBOLS
33
- unicode = unicodes.invert[value]
32
+ unicode = Mathml::Constants::UNICODE_SYMBOLS.invert[value]
34
33
  if operator?(unicode) || unicode || explicit_checks(unicode)
35
- mo_value = (unicodes[value] || unicode || value).to_s
36
- return Utility.ox_element("mo") << mo_value
34
+ return Utility.ox_element("mo") << (unicode || value).to_s
37
35
  end
38
36
 
39
37
  mi_tag << value
@@ -58,14 +56,12 @@ module Plurimath
58
56
  value
59
57
  end
60
58
 
61
- def to_omml_without_math_tag(_display_style)
59
+ def to_omml_without_math_tag(_, _)
62
60
  value
63
61
  end
64
62
 
65
- def insert_t_tag(_display_style)
66
- r_tag = Utility.ox_element("r", namespace: "m")
67
- r_tag << (Utility.ox_element("t", namespace: "m") << value)
68
- [r_tag]
63
+ def insert_t_tag(_)
64
+ [(Utility.ox_element("r", namespace: "m") << t_tag)]
69
65
  end
70
66
 
71
67
  def tag_name
@@ -80,8 +76,8 @@ module Plurimath
80
76
  "subSup"
81
77
  end
82
78
 
83
- def font_style_t_tag(_display_style)
84
- Utility.ox_element("t", namespace: "m") << value
79
+ def font_style_t_tag(_)
80
+ t_tag
85
81
  end
86
82
 
87
83
  def nary_attr_value
@@ -92,6 +88,22 @@ module Plurimath
92
88
  false
93
89
  end
94
90
 
91
+ def omml_nodes(_)
92
+ Array(t_tag)
93
+ end
94
+
95
+ def t_tag
96
+ Utility.ox_element("t", namespace: "m") << value
97
+ end
98
+
99
+ def separate_table
100
+ ["&", "\\\\"].include?(value)
101
+ end
102
+
103
+ def linebreak
104
+ value == "\\\\"
105
+ end
106
+
95
107
  private
96
108
 
97
109
  def operator?(unicode)
@@ -19,9 +19,7 @@ require_relative "latex/parser"
19
19
  require_relative "html/parser"
20
20
  require_relative "omml/parser"
21
21
  require_relative "utility"
22
- require "ox"
23
22
  require "yaml"
24
- Ox.default_options = { encoding: "UTF-8" }
25
23
 
26
24
  module Plurimath
27
25
  module Math
@@ -72,7 +70,7 @@ module Plurimath
72
70
 
73
71
  def type_error!
74
72
  raise InvalidTypeError.new(
75
- "`type` must be one of: `#{VALID_TYPES.keys.join('`, `')}`"
73
+ "`type` must be one of: `#{VALID_TYPES.keys.join('`, `')}`",
76
74
  )
77
75
  end
78
76
 
@@ -8,9 +8,11 @@ module Plurimath
8
8
  attr_accessor :text
9
9
 
10
10
  SUPPORTED_ATTRS = %w[
11
+ linebreakstyle
11
12
  columnlines
12
13
  mathvariant
13
14
  accentunder
15
+ linebreak
14
16
  mathcolor
15
17
  notation
16
18
  accent
@@ -23,8 +25,8 @@ module Plurimath
23
25
  end
24
26
 
25
27
  def parse
26
- ox_nodes = Ox.load(text, strip_namespace: true)
27
- display_style = ox_nodes&.locate("*/mstyle/@displaystyle")&.first
28
+ ox_nodes = Plurimath.xml_engine.load(text)
29
+ display_style = ox_nodes&.locate("mstyle/@displaystyle")&.first
28
30
  nodes = parse_nodes(ox_nodes.nodes)
29
31
  Math::Formula.new(
30
32
  Transform.new.apply(nodes).flatten.compact,
@@ -34,7 +36,7 @@ module Plurimath
34
36
 
35
37
  def parse_nodes(nodes)
36
38
  nodes.map do |node|
37
- next if node.is_a?(Ox::Comment)
39
+ next if Plurimath.xml_engine.is_xml_comment?(node)
38
40
 
39
41
  if node.is_a?(String)
40
42
  node
@@ -47,7 +49,7 @@ module Plurimath
47
49
  end
48
50
 
49
51
  def validate_attributes(attributes)
50
- attributes&.select! { |key, _| SUPPORTED_ATTRS.include?(key&.to_s) }
52
+ attributes&.select! { |key, _| SUPPORTED_ATTRS.include?(key.to_s) }
51
53
  attributes&.transform_keys(&:to_sym) if attributes&.any?
52
54
  end
53
55
 
@@ -9,6 +9,7 @@ module Plurimath
9
9
  rule(mtd: sequence(:mtd)) { Math::Function::Td.new(mtd) }
10
10
  rule(mtr: sequence(:mtr)) { Math::Function::Tr.new(mtr) }
11
11
  rule(none: sequence(:none)) { nil }
12
+ rule(mspace: simple(:space)) { nil }
12
13
  rule(notation: simple(:att)) { Math::Function::Menclose.new(att) }
13
14
  rule(mtable: simple(:table)) { table }
14
15
  rule(msqrt: sequence(:sqrt)) { Math::Function::Sqrt.new(sqrt.first) }
@@ -36,7 +37,9 @@ module Plurimath
36
37
  end
37
38
 
38
39
  rule(mphantom: sequence(:phantom)) do
39
- Math::Function::Phantom.new(phantom)
40
+ Math::Function::Phantom.new(
41
+ Utility.filter_values(phantom),
42
+ )
40
43
  end
41
44
 
42
45
  rule(mn: sequence(:mn)) do
@@ -88,8 +91,7 @@ module Plurimath
88
91
 
89
92
  rule(merror: sequence(:merror)) do
90
93
  Math::Function::Merror.new(
91
- merror[0],
92
- merror[1],
94
+ Utility.filter_values(merror),
93
95
  )
94
96
  end
95
97
 
@@ -247,7 +249,7 @@ module Plurimath
247
249
  symbols = Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
248
250
  text = entities.encode(mtext.flatten.join, :hexadecimal)
249
251
  symbols.each do |code, string|
250
- text.gsub!(code.downcase, "unicode[:#{string}]")
252
+ text = text.gsub(code.downcase, "unicode[:#{string}]")
251
253
  end
252
254
  Math::Function::Text.new(text)
253
255
  end
@@ -257,7 +259,7 @@ module Plurimath
257
259
  symbols = Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
258
260
  text = entities.encode(ms.first, :hexadecimal)
259
261
  symbols.each do |code, string|
260
- text.gsub!(code.downcase, "unicode[:#{string}]")
262
+ text = text.gsub(code.downcase, "unicode[:#{string}]")
261
263
  end
262
264
  Math::Function::Text.new(text)
263
265
  end
@@ -317,11 +319,6 @@ module Plurimath
317
319
  end
318
320
  end
319
321
 
320
- rule(attributes: simple(:attrs),
321
- value: subtree(:value)) do
322
- Utility.join_attr_value(attrs, value&.flatten&.compact)
323
- end
324
-
325
322
  rule(semantics: subtree(:value)) do
326
323
  Math::Function::Semantics.new(
327
324
  value.shift,
@@ -329,17 +326,27 @@ module Plurimath
329
326
  )
330
327
  end
331
328
 
329
+ rule(attributes: simple(:attrs),
330
+ value: subtree(:value)) do
331
+ Utility.join_attr_value(attrs, value&.flatten&.compact)
332
+ end
333
+
332
334
  rule(attributes: subtree(:attrs),
333
335
  value: sequence(:value)) do
334
- approved_attrs = if attrs.is_a?(Hash)
335
- supported_attrs = %w[accentunder accent]
336
- attrs if attrs.keys.any? do |k|
337
- supported_attrs.include?(k.to_s)
338
- end
339
- else
340
- attrs
341
- end
342
- Utility.join_attr_value(approved_attrs, value&.flatten&.compact)
336
+ approved = if attrs.is_a?(Hash)
337
+ supported = %w[accentunder accent linebreak]
338
+ if attrs.keys.any? { |k| supported.include?(k.to_s) }
339
+ unicode_only = true if attrs.key?(:linebreak)
340
+ attrs
341
+ end
342
+ else
343
+ attrs
344
+ end
345
+ Utility.join_attr_value(
346
+ approved,
347
+ value&.flatten&.compact,
348
+ unicode_only: unicode_only,
349
+ )
343
350
  end
344
351
  end
345
352
  end
@@ -33,7 +33,7 @@ module Plurimath
33
33
  end
34
34
 
35
35
  def parse
36
- nodes = Ox.load(text, strip_namespace: true)
36
+ nodes = Plurimath.xml_engine.load(text)
37
37
  @hash = { sequence: parse_nodes(nodes.nodes) }
38
38
  nodes = JSON.parse(@hash.to_json, symbolize_names: true)
39
39
  Math::Formula.new(
@@ -71,14 +71,14 @@ module Plurimath
71
71
  end
72
72
 
73
73
  def organize_table_td(node)
74
- node.locate("e/?").each do |child_node|
74
+ node.locate("e/*").each do |child_node|
75
75
  child_node.name = "mtd" if child_node.name == "r"
76
76
  end
77
77
  end
78
78
 
79
79
  def organize_fonts(node)
80
80
  attrs_arr = { val: [] }
81
- node.locate("rPr/?").each do |child|
81
+ node.locate("rPr/*").each do |child|
82
82
  attrs_arr[:val] << child.attributes["val"]
83
83
  end
84
84
  node.attributes.merge! attrs_arr
@@ -9,6 +9,7 @@ module Plurimath
9
9
  rule(i: sequence(:i)) { i }
10
10
  rule(e: sequence(:e)) { e.flatten.compact }
11
11
 
12
+ rule(br: sequence(:br)) { Math::Function::Linebreak.new }
12
13
  rule(val: simple(:val)) { val }
13
14
  rule(scr: simple(:scr)) { scr }
14
15
  rule(sty: simple(:sty)) { sty }
@@ -98,11 +99,17 @@ module Plurimath
98
99
  open_paren = fenced.shift if fenced&.first&.class_name == "symbol"
99
100
  close_paren = fenced.shift if fenced&.first&.class_name == "symbol"
100
101
  fenced_value = fenced.compact
101
- Math::Function::Fenced.new(
102
- open_paren,
103
- fenced_value,
104
- close_paren,
105
- )
102
+ if fenced_value.length == 1 && fenced_value.first.is_a?(Math::Function::Table)
103
+ fenced_value.first.open_paren = open_paren&.value
104
+ fenced_value.first.close_paren = close_paren&.value
105
+ fenced_value
106
+ else
107
+ Math::Function::Fenced.new(
108
+ open_paren,
109
+ fenced_value,
110
+ close_paren,
111
+ )
112
+ end
106
113
  end
107
114
 
108
115
  rule(dPr: subtree(:dpr)) do
@@ -176,12 +183,7 @@ module Plurimath
176
183
  ternary_class.parameter_three = Utility.filter_values(nary[3])
177
184
  ternary_class
178
185
  else
179
- Math::Formula.new(
180
- [
181
- Utility.nary_fonts(nary),
182
- Utility.filter_values(nary[3]),
183
- ],
184
- )
186
+ Utility.nary_fonts(nary)
185
187
  end
186
188
  end
187
189
 
@@ -209,7 +211,7 @@ module Plurimath
209
211
  end
210
212
  if Utility.valid_class(subsup[0])
211
213
  Utility.get_class(
212
- subsup[0].extract_class_from_text,
214
+ subsup[0].extract_class_name_from_text,
213
215
  ).new(
214
216
  subsup[1],
215
217
  subsup[2],
@@ -255,20 +257,31 @@ module Plurimath
255
257
  rule(limUpp: subtree(:lim)) do
256
258
  lim_values = lim.flatten.compact
257
259
  first_value = lim_values[0]
258
- Math::Function::Overset.new(
259
- first_value,
260
- lim_values[1],
261
- )
260
+ if lim.last.is_unary? && lim.last.value_nil?
261
+ function_class = lim.pop
262
+ function_class.parameter_one = Utility.filter_values(lim.flatten.compact)
263
+ function_class
264
+ else
265
+ Math::Function::Overset.new(
266
+ first_value,
267
+ lim_values[1],
268
+ )
269
+ end
262
270
  end
263
271
 
264
272
  rule(limLow: subtree(:lim)) do
265
273
  second_value = Utility.filter_values(lim[2])
266
- unicode = Mathml::Constants::UNICODE_SYMBOLS.invert[second_value.class_name]
274
+ unicode = Mathml::Constants::UNICODE_SYMBOLS.invert[second_value&.class_name]
267
275
  second_value = unicode ? Math::Symbol.new(unicode.to_s) : second_value
268
- Math::Function::Underset.new(
269
- Utility.filter_values(lim[1]),
270
- second_value,
271
- )
276
+ if second_value.is_unary? && second_value.value_nil?
277
+ second_value.parameter_one = Utility.filter_values(lim[1])
278
+ second_value
279
+ else
280
+ Math::Function::Underset.new(
281
+ Utility.filter_values(lim[1]),
282
+ second_value,
283
+ )
284
+ end
272
285
  end
273
286
 
274
287
  rule(borderBox: subtree(:box)) do
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "plurimath/xml_engine/oga"
4
+
5
+ Plurimath.xml_engine = Plurimath::XMLEngine::Oga
@@ -0,0 +1,8 @@
1
+ require 'plurimath/math/core'
2
+ require 'plurimath/math/function'
3
+ <% (
4
+ Dir[File.dirname(__dir__)+"/math/function/*.rb"] +
5
+ Dir[File.dirname(__dir__)+"/math/function/**/*.rb"]
6
+ ).each do |f| %>
7
+ require 'plurimath/<%= f.split("lib/plurimath").last.gsub(/.rb$/,'') %>'
8
+ <% end %>
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "plurimath/xml_engine/ox"
4
+
5
+ Plurimath.xml_engine = Plurimath::XMLEngine::Ox
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "unitsml"
3
4
  module Plurimath
4
5
  class Unitsml
5
6
  attr_accessor :text
@@ -9,7 +10,7 @@ module Plurimath
9
10
  end
10
11
 
11
12
  def to_formula
12
- # TODO: Will be implemented soon
13
+ ::Unitsml.parse(text).to_plurimath
13
14
  end
14
15
  end
15
16
  end
@@ -21,6 +21,7 @@ module Plurimath
21
21
  mathrm: Math::Function::FontStyle::Normal,
22
22
  textrm: Math::Function::FontStyle::Normal,
23
23
  italic: Math::Function::FontStyle::Italic,
24
+ mathit: Math::Function::FontStyle::Italic,
24
25
  mathbf: Math::Function::FontStyle::Bold,
25
26
  textbf: Math::Function::FontStyle::Bold,
26
27
  script: Math::Function::FontStyle::Script,
@@ -46,6 +47,8 @@ module Plurimath
46
47
  arccos
47
48
  arcsin
48
49
  arctan
50
+ liminf
51
+ limsup
49
52
  right
50
53
  sech
51
54
  sinh
@@ -58,6 +61,7 @@ module Plurimath
58
61
  min
59
62
  sec
60
63
  sin
64
+ sup
61
65
  deg
62
66
  det
63
67
  dim
@@ -65,6 +69,8 @@ module Plurimath
65
69
  gcd
66
70
  glb
67
71
  lub
72
+ lcm
73
+ ker
68
74
  tan
69
75
  cos
70
76
  cot
@@ -91,20 +97,25 @@ module Plurimath
91
97
  "{": "}",
92
98
  "[": "]",
93
99
  }.freeze
100
+ TEXT_CLASSES = %w[
101
+ unicode
102
+ symbol
103
+ number
104
+ text
105
+ ].freeze
94
106
 
95
107
  class << self
96
108
  def organize_table(array, column_align: nil, options: nil)
97
109
  table = []
98
110
  table_data = []
99
111
  table_row = []
100
- table_separators = ["&", "\\\\"].freeze
101
112
  organize_options(array, column_align) if options
102
113
  string_columns = column_align&.map(&:value)
103
114
  array.each do |data|
104
- if data.is_a?(Math::Symbol) && table_separators.include?(data.value)
115
+ if data&.separate_table
105
116
  table_row << Math::Function::Td.new(filter_table_data(table_data).compact)
106
117
  table_data = []
107
- if data.value == "\\\\"
118
+ if data.linebreak
108
119
  organize_tds(table_row.flatten, string_columns.dup, options)
109
120
  table << Math::Function::Tr.new(table_row)
110
121
  table_row = []
@@ -187,7 +198,7 @@ module Plurimath
187
198
  def ox_element(node, attributes: [], namespace: "")
188
199
  namespace = "#{namespace}:" unless namespace.empty?
189
200
 
190
- element = Ox::Element.new("#{namespace}#{node}")
201
+ element = Plurimath.xml_engine.new_element("#{namespace}#{node}")
191
202
  attributes&.each do |attr_key, attr_value|
192
203
  element[attr_key] = attr_value
193
204
  end
@@ -224,12 +235,10 @@ module Plurimath
224
235
  end
225
236
 
226
237
  def filter_values(array)
227
- return array unless array.is_a?(Array)
238
+ return array unless array.is_a?(Array) || array.is_a?(Math::Formula)
228
239
 
229
- array = array.flatten.compact
230
- if array.length > 1
231
- return Math::Formula.new(array)
232
- end
240
+ array = array.is_a?(Math::Formula) ? array.value : array.flatten.compact
241
+ return Math::Formula.new(array) if array.length > 1
233
242
 
234
243
  array.first
235
244
  end
@@ -249,20 +258,17 @@ module Plurimath
249
258
 
250
259
  def nary_fonts(nary)
251
260
  narypr = nary.first.flatten.compact
252
- subsup = narypr.any?("undOvr") ? "underover" : "power_base"
261
+ subsup = narypr.any?("undOvr") ? "undOvr" : "subSup"
253
262
  unicode = narypr.any?(Hash) ? narypr.first[:chr] : "∫"
254
- get_class(subsup).new(
263
+ Math::Function::Nary.new(
255
264
  Math::Symbol.new(string_to_html_entity(unicode)),
256
- nary[1],
257
- nary[2],
265
+ filter_values(nary[1]),
266
+ filter_values(nary[2]),
267
+ filter_values(nary[3]),
268
+ { type: subsup }
258
269
  )
259
270
  end
260
271
 
261
- def find_class_name(object)
262
- new_object = object.value.first.parameter_one if object.is_a?(Math::Formula)
263
- get_class(new_object) unless new_object.nil?
264
- end
265
-
266
272
  def find_pos_chr(fonts_array, key)
267
273
  fonts_array.find { |d| d.is_a?(Hash) && d[key] }
268
274
  end
@@ -279,31 +285,31 @@ module Plurimath
279
285
  end
280
286
 
281
287
  def symbol_value(object, value)
282
- object.is_a?(Math::Symbol) && object.value.include?(value)
288
+ (object.is_a?(Math::Symbol) && object.value.include?(value)) ||
289
+ (value == "\\\\" && object.is_a?(Math::Function::Linebreak))
283
290
  end
284
291
 
285
292
  def td_value(td_object)
286
- if td_object.is_a?(String) && td_object.empty?
293
+ str_classes = [String, Parslet::Slice]
294
+ if str_classes.include?(td_object.class) && td_object.to_s.empty?
287
295
  return Math::Function::Text.new(nil)
288
296
  end
289
297
 
290
298
  td_object
291
299
  end
292
300
 
293
- def mathml_unary_classes(text_array, omml: false)
301
+ def mathml_unary_classes(text_array, omml: false, unicode_only: false)
294
302
  return [] if text_array.empty?
295
303
 
296
304
  compacted = text_array.compact
297
- string = if compacted.count == 1
298
- compacted.first
299
- else
300
- compacted.join
301
- end
302
- return string unless string.is_a?(String)
305
+ return filter_values(compacted) unless compacted.any?(String)
303
306
 
307
+ string = compacted.join
304
308
  classes = Mathml::Constants::CLASSES
305
309
  unicode = string_to_html_entity(string)
306
- symbol = Mathml::Constants::UNICODE_SYMBOLS[unicode.strip.to_sym]
310
+ return Math::Symbol.new(unicode) if unicode_only && unicode
311
+
312
+ symbol = Mathml::Constants::UNICODE_SYMBOLS[unicode.strip.to_sym]
307
313
  if classes.include?(symbol&.strip)
308
314
  get_class(symbol.strip).new
309
315
  elsif classes.any?(string&.strip)
@@ -338,17 +344,21 @@ module Plurimath
338
344
  value
339
345
  end
340
346
 
341
- def join_attr_value(attrs, value)
347
+ def join_attr_value(attrs, value, unicode_only: false)
342
348
  if value.any?(String)
343
- new_value = mathml_unary_classes(value)
349
+ new_value = mathml_unary_classes(value, unicode_only: unicode_only)
344
350
  array_value = Array(new_value)
345
- attrs.nil? ? array_value : join_attr_value(attrs, array_value)
351
+ attrs.nil? ? array_value : join_attr_value(attrs, array_value, unicode_only: unicode_only)
346
352
  elsif attrs.nil?
347
353
  value
348
354
  elsif attrs.is_a?(String) && ["solid", "none"].include?(attrs.split.first.downcase)
349
355
  table_separator(attrs.split, value)
350
- elsif attrs.is_a?(Hash) && (attrs.key?(:accent) || attrs.key?(:accentunder))
351
- attr_is_accent(attrs, value)
356
+ elsif attrs.is_a?(Hash)
357
+ if (attrs.key?(:accent) || attrs.key?(:accentunder))
358
+ attr_is_accent(attrs, value)
359
+ elsif attrs.key?(:linebreak)
360
+ Math::Function::Linebreak.new(value.first, attrs)
361
+ end
352
362
  elsif attrs.is_a?(Math::Core)
353
363
  attr_is_function(attrs, value)
354
364
  end
@@ -452,7 +462,7 @@ module Plurimath
452
462
  end
453
463
 
454
464
  def left_right_objects(paren, function)
455
- paren = if paren.to_s.match?(/\\{|\\}/)
465
+ paren = if paren.to_s.match?(/\\\{|\\\}/)
456
466
  paren.to_s.gsub(/\\/, "")
457
467
  else
458
468
  Latex::Constants::LEFT_RIGHT_PARENTHESIS[paren.to_sym]
@@ -461,7 +471,7 @@ module Plurimath
461
471
  end
462
472
 
463
473
  def valid_class(object)
464
- text = object.extract_class_from_text
474
+ text = object.extract_class_name_from_text
465
475
  (object.extractable? && Asciimath::Constants::SUB_SUP_CLASSES.include?(text)) ||
466
476
  Latex::Constants::SYMBOLS[text.to_sym] == :power_base
467
477
  end
@@ -469,12 +479,7 @@ module Plurimath
469
479
  def mrow_left_right(mrow = [])
470
480
  object = mrow.first
471
481
  !(
472
- (
473
- (
474
- object.is_a?(Math::Function::TernaryFunction) && object.any_value_exist?
475
- ) &&
476
- (mrow.length <= 2)
477
- ) ||
482
+ ((object.is_a?(Math::Function::TernaryFunction) && object.any_value_exist?) && (mrow.length <= 2)) ||
478
483
  (object.is_a?(Math::Function::UnaryFunction) && mrow.length == 1)
479
484
  )
480
485
  end
@@ -564,6 +569,37 @@ module Plurimath
564
569
  end
565
570
  end
566
571
  end
572
+
573
+ def validate_math_zone(object)
574
+ return false unless object
575
+
576
+ if object.is_a?(Math::Formula)
577
+ filter_math_zone_values(object.value).find do |d|
578
+ !d.is_a?(Math::Function::Text)
579
+ end
580
+ else
581
+ !TEXT_CLASSES.include?(object.class_name)
582
+ end
583
+ end
584
+
585
+ def filter_math_zone_values(value)
586
+ return [] if value&.empty?
587
+
588
+ new_arr = []
589
+ temp_array = []
590
+ skip_index = nil
591
+ value.each_with_index do |obj, index|
592
+ object = obj.dup
593
+ next if index == skip_index
594
+ next temp_array << object.value if TEXT_CLASSES.include?(object.class_name)
595
+
596
+ new_arr << Math::Function::Text.new(temp_array.join(" ")) if temp_array.any?
597
+ temp_array = []
598
+ new_arr << object
599
+ end
600
+ new_arr << Math::Function::Text.new(temp_array.join(" ")) if temp_array.any?
601
+ new_arr
602
+ end
567
603
  end
568
604
  end
569
605
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plurimath
4
- VERSION = "0.5.0"
4
+ VERSION = "0.7.0"
5
5
  end