plurimath 0.3.9 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/lib/plurimath/math/core.rb +16 -4
  3. data/lib/plurimath/math/formula.rb +24 -20
  4. data/lib/plurimath/math/function/abs.rb +2 -2
  5. data/lib/plurimath/math/function/bar.rb +43 -12
  6. data/lib/plurimath/math/function/base.rb +3 -3
  7. data/lib/plurimath/math/function/binary_function.rb +16 -10
  8. data/lib/plurimath/math/function/cancel.rb +2 -2
  9. data/lib/plurimath/math/function/ceil.rb +7 -2
  10. data/lib/plurimath/math/function/color.rb +2 -2
  11. data/lib/plurimath/math/function/ddot.rb +10 -12
  12. data/lib/plurimath/math/function/deg.rb +2 -2
  13. data/lib/plurimath/math/function/det.rb +2 -2
  14. data/lib/plurimath/math/function/dim.rb +2 -2
  15. data/lib/plurimath/math/function/dot.rb +21 -4
  16. data/lib/plurimath/math/function/exp.rb +2 -2
  17. data/lib/plurimath/math/function/fenced.rb +2 -1
  18. data/lib/plurimath/math/function/floor.rb +2 -2
  19. data/lib/plurimath/math/function/font_style/bold-fraktur.rb +17 -0
  20. data/lib/plurimath/math/function/font_style/bold-italic.rb +17 -0
  21. data/lib/plurimath/math/function/font_style/bold-sans-serif.rb +17 -0
  22. data/lib/plurimath/math/function/font_style/bold-script.rb +17 -0
  23. data/lib/plurimath/math/function/font_style/bold.rb +4 -0
  24. data/lib/plurimath/math/function/font_style/double_struck.rb +4 -0
  25. data/lib/plurimath/math/function/font_style/fraktur.rb +4 -0
  26. data/lib/plurimath/math/function/font_style/italic.rb +4 -0
  27. data/lib/plurimath/math/function/font_style/monospace.rb +4 -0
  28. data/lib/plurimath/math/function/font_style/normal.rb +4 -0
  29. data/lib/plurimath/math/function/font_style/sans-serif-bold-italic.rb +17 -0
  30. data/lib/plurimath/math/function/font_style/sans-serif-italic.rb +17 -0
  31. data/lib/plurimath/math/function/font_style/sans-serif.rb +4 -0
  32. data/lib/plurimath/math/function/font_style/script.rb +4 -0
  33. data/lib/plurimath/math/function/font_style.rb +22 -4
  34. data/lib/plurimath/math/function/frac.rb +3 -3
  35. data/lib/plurimath/math/function/gcd.rb +2 -2
  36. data/lib/plurimath/math/function/glb.rb +2 -2
  37. data/lib/plurimath/math/function/hat.rb +37 -11
  38. data/lib/plurimath/math/function/hom.rb +2 -2
  39. data/lib/plurimath/math/function/inf.rb +2 -2
  40. data/lib/plurimath/math/function/int.rb +4 -4
  41. data/lib/plurimath/math/function/ker.rb +2 -2
  42. data/lib/plurimath/math/function/lcm.rb +2 -2
  43. data/lib/plurimath/math/function/left.rb +1 -1
  44. data/lib/plurimath/math/function/lg.rb +2 -2
  45. data/lib/plurimath/math/function/lim.rb +2 -2
  46. data/lib/plurimath/math/function/liminf.rb +2 -2
  47. data/lib/plurimath/math/function/limits.rb +4 -4
  48. data/lib/plurimath/math/function/limsup.rb +2 -2
  49. data/lib/plurimath/math/function/ln.rb +2 -2
  50. data/lib/plurimath/math/function/log.rb +5 -3
  51. data/lib/plurimath/math/function/longdiv.rb +2 -2
  52. data/lib/plurimath/math/function/lub.rb +2 -2
  53. data/lib/plurimath/math/function/max.rb +2 -2
  54. data/lib/plurimath/math/function/mbox.rb +2 -2
  55. data/lib/plurimath/math/function/menclose.rb +2 -2
  56. data/lib/plurimath/math/function/merror.rb +1 -1
  57. data/lib/plurimath/math/function/min.rb +2 -2
  58. data/lib/plurimath/math/function/mod.rb +3 -3
  59. data/lib/plurimath/math/function/msgroup.rb +2 -2
  60. data/lib/plurimath/math/function/msline.rb +2 -2
  61. data/lib/plurimath/math/function/multiscript.rb +4 -4
  62. data/lib/plurimath/math/function/norm.rb +2 -2
  63. data/lib/plurimath/math/function/obrace.rb +35 -28
  64. data/lib/plurimath/math/function/oint.rb +4 -4
  65. data/lib/plurimath/math/function/over.rb +3 -3
  66. data/lib/plurimath/math/function/overset.rb +8 -3
  67. data/lib/plurimath/math/function/power.rb +3 -3
  68. data/lib/plurimath/math/function/power_base.rb +8 -8
  69. data/lib/plurimath/math/function/prod.rb +4 -4
  70. data/lib/plurimath/math/function/right.rb +1 -1
  71. data/lib/plurimath/math/function/root.rb +3 -3
  72. data/lib/plurimath/math/function/rule.rb +1 -1
  73. data/lib/plurimath/math/function/scarries.rb +2 -2
  74. data/lib/plurimath/math/function/semantics.rb +2 -2
  75. data/lib/plurimath/math/function/sqrt.rb +2 -2
  76. data/lib/plurimath/math/function/stackrel.rb +3 -3
  77. data/lib/plurimath/math/function/substack.rb +3 -3
  78. data/lib/plurimath/math/function/sum.rb +14 -19
  79. data/lib/plurimath/math/function/sup.rb +2 -2
  80. data/lib/plurimath/math/function/table.rb +7 -7
  81. data/lib/plurimath/math/function/td.rb +2 -2
  82. data/lib/plurimath/math/function/ternary_function.rb +7 -3
  83. data/lib/plurimath/math/function/text.rb +6 -5
  84. data/lib/plurimath/math/function/tilde.rb +22 -4
  85. data/lib/plurimath/math/function/tr.rb +2 -2
  86. data/lib/plurimath/math/function/ubrace.rb +23 -23
  87. data/lib/plurimath/math/function/ul.rb +50 -20
  88. data/lib/plurimath/math/function/unary_function.rb +7 -5
  89. data/lib/plurimath/math/function/underover.rb +10 -5
  90. data/lib/plurimath/math/function/underset.rb +8 -3
  91. data/lib/plurimath/math/function/vec.rb +20 -5
  92. data/lib/plurimath/math/number.rb +6 -2
  93. data/lib/plurimath/math/symbol.rb +6 -2
  94. data/lib/plurimath/math.rb +1 -0
  95. data/lib/plurimath/mathml/constants.rb +9 -1
  96. data/lib/plurimath/mathml/parser.rb +3 -1
  97. data/lib/plurimath/mathml/transform.rb +51 -22
  98. data/lib/plurimath/omml/parser.rb +24 -1
  99. data/lib/plurimath/omml/transform.rb +43 -36
  100. data/lib/plurimath/utility.rb +114 -9
  101. data/lib/plurimath/version.rb +1 -1
  102. metadata +8 -2
@@ -1,11 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "unary_function"
3
+ require_relative "binary_function"
4
4
 
5
5
  module Plurimath
6
6
  module Math
7
7
  module Function
8
- class Ubrace < UnaryFunction
8
+ class Ubrace < BinaryFunction
9
+ def to_asciimath
10
+ first_value = "(#{parameter_one.to_asciimath})" if parameter_one
11
+ "ubrace#{first_value}"
12
+ end
13
+
9
14
  def to_latex
10
15
  first_value = "{#{parameter_one.to_latex}}" if parameter_one
11
16
  "\\underbrace#{first_value}"
@@ -13,13 +18,17 @@ module Plurimath
13
18
 
14
19
  def to_mathml_without_math_tag
15
20
  mo_tag = (Utility.ox_element("mo") << "&#x23df;")
16
- if parameter_one
17
- over_tag = Utility.ox_element("munder")
18
- arr_value = mathml_value
19
- Utility.update_nodes(over_tag, (arr_value << mo_tag))
20
- else
21
- mo_tag
22
- end
21
+ return mo_tag unless parameter_one
22
+
23
+ over_tag = Utility.ox_element("munder")
24
+ over_tag.attributes.merge!(parameter_two) if parameter_two && !parameter_two.empty?
25
+ Utility.update_nodes(
26
+ over_tag,
27
+ [
28
+ parameter_one.to_mathml_without_math_tag,
29
+ mo_tag,
30
+ ],
31
+ )
23
32
  end
24
33
 
25
34
  def tag_name
@@ -34,20 +43,11 @@ module Plurimath
34
43
  false
35
44
  end
36
45
 
37
- def to_omml_without_math_tag
38
- limlow = Utility.ox_element("limLow", namespace: "m")
39
- limlowpr = Utility.ox_element("limLowPr", namespace: "m")
40
- limlowpr << Utility.pr_element("ctrl", true, namespace: "m")
41
- lim = Utility.ox_element("lim", namespace: "m")
42
- Utility.update_nodes(
43
- limlow,
44
- [
45
- limlowpr,
46
- omml_parameter(parameter_one, tag_name: "e"),
47
- Utility.update_nodes(lim, r_element("⏟")),
48
- ],
49
- )
50
- [limlow]
46
+ def to_omml_without_math_tag(display_style)
47
+ return r_element("", rpr_tag: false) unless all_values_exist?
48
+
49
+ symbol = Symbol.new("")
50
+ Underset.new(parameter_one, symbol).to_omml_without_math_tag(true)
51
51
  end
52
52
  end
53
53
 
@@ -1,41 +1,71 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "unary_function"
3
+ require_relative "binary_function"
4
4
 
5
5
  module Plurimath
6
6
  module Math
7
7
  module Function
8
- class Ul < UnaryFunction
8
+ class Ul < BinaryFunction
9
+ def to_asciimath
10
+ first_value = "(#{parameter_one.to_asciimath})" if parameter_one
11
+ "underline#{first_value}"
12
+ end
13
+
14
+ def to_latex
15
+ first_value = "{#{parameter_one.to_latex}}" if parameter_one
16
+ "\\underline#{first_value}"
17
+ end
18
+
9
19
  def to_mathml_without_math_tag
10
- first_value = parameter_one&.to_mathml_without_math_tag
20
+ mo_tag = Utility.ox_element("mo") << "&#x332;"
21
+ return mo_tag unless parameter_one
22
+
23
+ munder_tag = Utility.ox_element("munder")
24
+ munder_tag.attributes.merge!(parameter_two) if parameter_two && !parameter_two.empty?
11
25
  Utility.update_nodes(
12
- Utility.ox_element("munder"),
26
+ munder_tag,
13
27
  [
14
- first_value,
15
- Utility.ox_element("mo") << "&#xaf;",
28
+ parameter_one&.to_mathml_without_math_tag,
29
+ mo_tag,
16
30
  ],
17
31
  )
18
32
  end
19
33
 
20
- def to_omml_without_math_tag
21
- bar = Utility.ox_element("bar", namespace: "m")
22
- barpr = Utility.ox_element("barPr", namespace: "m")
23
- barpr << Utility.pr_element("ctrl", true, namespace: "m")
24
- me = Utility.ox_element("e", namespace: "m")
25
- Utility.update_nodes(me, omml_value)
26
- Utility.update_nodes(
27
- bar,
28
- [
29
- barpr,
30
- me,
31
- ],
32
- )
33
- [bar]
34
+ def to_omml_without_math_tag(display_style)
35
+ return r_element("&#x332;", rpr_tag: false) unless all_values_exist?
36
+
37
+ if parameter_two && parameter_two[:accentunder]
38
+ groupchr_tag(display_style)
39
+ else
40
+ symbol = Symbol.new("&#x332;")
41
+ Underset.new(parameter_one, symbol).to_omml_without_math_tag(true)
42
+ end
34
43
  end
35
44
 
36
45
  def class_name
37
46
  "underline"
38
47
  end
48
+
49
+ def swap_class
50
+ Bar.new(parameter_one, parameter_two)
51
+ end
52
+
53
+ protected
54
+
55
+ def groupchr_tag(display_style)
56
+ groupchr = Utility.ox_element("groupChr", namespace: "m")
57
+ groupchrpr = Utility.ox_element("groupChrPR", namespace: "m")
58
+ chr = Utility.ox_element("chr", namespace: "m", attributes: { "m:val": "_" })
59
+ pos = Utility.ox_element("pos", namespace: "m", attributes: { "m:val": "bot" })
60
+ Utility.update_nodes(groupchrpr, [chr, pos])
61
+ Utility.update_nodes(
62
+ groupchr,
63
+ [
64
+ groupchrpr,
65
+ omml_parameter(parameter_one, display_style, tag_name: "e", namespace: "m"),
66
+ ],
67
+ )
68
+ end
39
69
  end
40
70
 
41
71
  Underline = Ul
@@ -52,7 +52,9 @@ module Plurimath
52
52
  "<i>#{class_name}</i>#{first_value}"
53
53
  end
54
54
 
55
- def to_omml_without_math_tag
55
+ def to_omml_without_math_tag(display_style)
56
+ return r_element(class_name, rpr_tag: false) unless parameter_one
57
+
56
58
  func = Utility.ox_element("func", namespace: "m")
57
59
  funcpr = Utility.ox_element("funcPr", namespace: "m")
58
60
  funcpr << Utility.pr_element("ctrl", true, namespace: "m")
@@ -62,7 +64,7 @@ module Plurimath
62
64
  mt = Utility.ox_element("t", namespace: "m") << class_name
63
65
  fname << Utility.update_nodes(mr, [rpr, mt])
64
66
  me = Utility.ox_element("e", namespace: "m")
65
- Utility.update_nodes(me, omml_value) if parameter_one
67
+ Utility.update_nodes(me, omml_value(display_style)) if parameter_one
66
68
  Utility.update_nodes(
67
69
  func,
68
70
  [
@@ -104,12 +106,12 @@ module Plurimath
104
106
  parameter_one&.to_latex
105
107
  end
106
108
 
107
- def omml_value
109
+ def omml_value(display_style)
108
110
  if parameter_one.is_a?(Array)
109
- return parameter_one&.compact&.map(&:insert_t_tag)
111
+ return parameter_one&.compact&.map { |obj| obj.insert_t_tag(display_style) }
110
112
  end
111
113
 
112
- Array(parameter_one&.insert_t_tag)
114
+ Array(parameter_one&.insert_t_tag(display_style))
113
115
  end
114
116
  end
115
117
  end
@@ -35,16 +35,21 @@ module Plurimath
35
35
  )
36
36
  end
37
37
 
38
- def to_omml_without_math_tag
39
- underover
38
+ def to_omml_without_math_tag(display_style)
39
+ if !display_style
40
+ power_base = PowerBase.new(parameter_one, parameter_two, parameter_three)
41
+ return power_base.to_omml_without_math_tag(display_style)
42
+ end
43
+
44
+ underover(display_style)
40
45
  end
41
46
 
42
- def omml_nary_tag
47
+ def omml_nary_tag(display_style)
43
48
  pr = Utility.ox_element("naryPr", namespace: "m")
44
49
  [
45
50
  pr_element_value(pr),
46
- omml_parameter(parameter_two, tag_name: "sub"),
47
- omml_parameter(parameter_three, tag_name: "sup"),
51
+ omml_parameter(parameter_two, display_style, tag_name: "sub"),
52
+ omml_parameter(parameter_three, display_style, tag_name: "sup"),
48
53
  ]
49
54
  end
50
55
 
@@ -18,7 +18,12 @@ module Plurimath
18
18
  )
19
19
  end
20
20
 
21
- def to_omml_without_math_tag
21
+ def to_omml_without_math_tag(display_style)
22
+ if !display_style
23
+ base = Base.new(parameter_one, parameter_two)
24
+ return base.to_omml_without_math_tag(display_style)
25
+ end
26
+
22
27
  limlow = Utility.ox_element("limLow", namespace: "m")
23
28
  limlowpr = Utility.ox_element("limLowPr", namespace: "m")
24
29
  limlowpr << Utility.pr_element("ctrl", true, namespace: "m")
@@ -26,8 +31,8 @@ module Plurimath
26
31
  limlow,
27
32
  [
28
33
  limlowpr,
29
- omml_parameter(parameter_one, tag_name: "e"),
30
- omml_parameter(parameter_two, tag_name: "lim"),
34
+ omml_parameter(parameter_one, display_style, tag_name: "e"),
35
+ omml_parameter(parameter_two, display_style, tag_name: "lim"),
31
36
  ],
32
37
  )
33
38
  [limlow]
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "unary_function"
3
+ require_relative "binary_function"
4
4
 
5
5
  module Plurimath
6
6
  module Math
7
7
  module Function
8
- class Vec < UnaryFunction
8
+ class Vec < BinaryFunction
9
9
  def to_mathml_without_math_tag
10
+ mover = Utility.ox_element("mover")
10
11
  first_value = parameter_one&.to_mathml_without_math_tag
12
+ mover.attributes.merge!({ accent: parameter_two[:accent] }) if parameter_two
11
13
  Utility.update_nodes(
12
- Utility.ox_element("mover"),
14
+ mover,
13
15
  [
14
16
  first_value,
15
17
  Utility.ox_element("mo") << "&#x2192;",
@@ -17,7 +19,20 @@ module Plurimath
17
19
  )
18
20
  end
19
21
 
20
- def to_omml_without_math_tag
22
+ def to_omml_without_math_tag(display_style)
23
+ return r_element("&#x2192;", rpr_tag: false) unless all_values_exist?
24
+
25
+ if parameter_two && parameter_two[:accent]
26
+ acc_tag(display_style)
27
+ else
28
+ symbol = Symbol.new("→")
29
+ Overset.new(parameter_one, symbol).to_omml_without_math_tag(true)
30
+ end
31
+ end
32
+
33
+ protected
34
+
35
+ def acc_tag(display_style)
21
36
  acc_tag = Utility.ox_element("acc", namespace: "m")
22
37
  acc_pr_tag = Utility.ox_element("accPr", namespace: "m")
23
38
  acc_pr_tag << (Utility.ox_element("chr", namespace: "m", attributes: { "m:val": "→" }))
@@ -25,7 +40,7 @@ module Plurimath
25
40
  acc_tag,
26
41
  [
27
42
  acc_pr_tag,
28
- omml_parameter(parameter_one, tag_name: "e"),
43
+ omml_parameter(parameter_one, display_style, tag_name: "e"),
29
44
  ],
30
45
  )
31
46
  [acc_tag]
@@ -29,16 +29,20 @@ module Plurimath
29
29
  value
30
30
  end
31
31
 
32
- def to_omml_without_math_tag
32
+ def to_omml_without_math_tag(_display_style)
33
33
  [(Utility.ox_element("t", namespace: "m") << value)]
34
34
  end
35
35
 
36
- def insert_t_tag
36
+ def insert_t_tag(_display_style)
37
37
  r_tag = Utility.ox_element("r", namespace: "m")
38
38
  r_tag << (Utility.ox_element("t", namespace: "m") << value)
39
39
  [r_tag]
40
40
  end
41
41
 
42
+ def font_style_t_tag(_display_style)
43
+ Utility.ox_element("t", namespace: "m") << value
44
+ end
45
+
42
46
  def nary_attr_value
43
47
  value
44
48
  end
@@ -58,11 +58,11 @@ module Plurimath
58
58
  value
59
59
  end
60
60
 
61
- def to_omml_without_math_tag
61
+ def to_omml_without_math_tag(_display_style)
62
62
  value
63
63
  end
64
64
 
65
- def insert_t_tag
65
+ def insert_t_tag(_display_style)
66
66
  r_tag = Utility.ox_element("r", namespace: "m")
67
67
  r_tag << (Utility.ox_element("t", namespace: "m") << value)
68
68
  [r_tag]
@@ -80,6 +80,10 @@ module Plurimath
80
80
  "subSup"
81
81
  end
82
82
 
83
+ def font_style_t_tag(_display_style)
84
+ Utility.ox_element("t", namespace: "m") << value
85
+ end
86
+
83
87
  def nary_attr_value
84
88
  value
85
89
  end
@@ -20,6 +20,7 @@ require_relative "html/parser"
20
20
  require_relative "omml/parser"
21
21
  require_relative "utility"
22
22
  require "ox"
23
+ require "yaml"
23
24
  Ox.default_options = { encoding: "UTF-8" }
24
25
 
25
26
  module Plurimath
@@ -130,7 +130,6 @@ module Plurimath
130
130
  "&#x21d2;": "rArr",
131
131
  "&#x21d0;": "lArr",
132
132
  "&#x21d4;": "hArr",
133
- "&#x2192;": "->",
134
133
  "&#x21a3;": ">->",
135
134
  "&#x21a0;": "->>",
136
135
  "&#x2916;": ">->>",
@@ -139,10 +138,19 @@ module Plurimath
139
138
  "&#x2212;": "-",
140
139
  "&#x23de;": "obrace",
141
140
  "&#x23df;": "ubrace",
141
+ "&#x2192;": "vec",
142
+ "&#x302;": "hat",
143
+ "&#x332;": "ul",
144
+ "&#xaf;": "bar",
142
145
  "&#x26;": "&",
143
146
  "&#x3e;": ">",
144
147
  "&#x3c;": "<",
145
148
  "&amp;": "&",
149
+ "~": "tilde",
150
+ "..": "ddot",
151
+ "^": "hat",
152
+ "¯": "bar",
153
+ "_": "ul",
146
154
  }.freeze
147
155
  SYMBOLS = {
148
156
  "|": "|",
@@ -10,8 +10,10 @@ module Plurimath
10
10
  SUPPORTED_ATTRIBUTES = %w[
11
11
  columnlines
12
12
  mathvariant
13
+ accentunder
13
14
  mathcolor
14
15
  notation
16
+ accent
15
17
  close
16
18
  open
17
19
  ].freeze
@@ -26,7 +28,7 @@ module Plurimath
26
28
  nodes = parse_nodes(ox_nodes.nodes)
27
29
  Math::Formula.new(
28
30
  Transform.new.apply(nodes).flatten.compact,
29
- displaystyle: display_style,
31
+ display_style: display_style,
30
32
  )
31
33
  end
32
34
 
@@ -135,23 +135,33 @@ module Plurimath
135
135
  )
136
136
  end
137
137
 
138
- rule(msubsup: sequence(:msubsup)) do
139
- Math::Function::PowerBase.new(
140
- msubsup[0],
141
- msubsup[1],
142
- msubsup[2],
143
- )
138
+ rule(msubsup: sequence(:function)) do
139
+ base_class = function[0].is_a?(Math::Formula) ? function[0]&.value&.first : function[0]
140
+ if base_class.is_a?(Math::Function::BinaryFunction)
141
+ base_class.parameter_one = function[1]
142
+ base_class.parameter_two = function[2]
143
+ base_class
144
+ elsif base_class.is_a?(Math::Function::TernaryFunction)
145
+ base_class.parameter_one = function[1]
146
+ base_class.parameter_two = function[2]
147
+ base_class.parameter_three = function[3]
148
+ base_class
149
+ else
150
+ Math::Function::PowerBase.new(
151
+ function[0],
152
+ function[1],
153
+ function[2],
154
+ )
155
+ end
144
156
  end
145
157
 
146
158
  rule(munderover: sequence(:function)) do
147
- binary_function = Plurimath::Math::Function::BinaryFunction
148
- ternary_function = Plurimath::Math::Function::TernaryFunction
149
- base_class = function[0]&.value&.first if function[0].is_a?(Math::Formula)
150
- if base_class&.class&.ancestors&.include?(binary_function)
159
+ base_class = function[0].is_a?(Math::Formula) ? function[0]&.value&.first : function[0]
160
+ if base_class.is_a?(Math::Function::BinaryFunction)
151
161
  base_class.parameter_one = function[1]
152
162
  base_class.parameter_two = function[2]
153
163
  base_class
154
- elsif base_class&.class&.ancestors&.include?(ternary_function)
164
+ elsif base_class.is_a?(Math::Function::TernaryFunction)
155
165
  base_class.parameter_one = function[1]
156
166
  base_class.parameter_two = function[2]
157
167
  base_class.parameter_three = function[3]
@@ -166,12 +176,15 @@ module Plurimath
166
176
  end
167
177
 
168
178
  rule(mrow: subtree(:mrow)) do
169
- if mrow.any?(String)
170
- mrow.each_with_index do |object, ind|
171
- mrow[ind] = Utility.mathml_unary_classes([object]) if object.is_a?(String)
172
- end
179
+ flatten_mrow = Utility.populate_function_classes(mrow)
180
+ if flatten_mrow.length == 1
181
+ flatten_mrow.first
182
+ else
183
+ Math::Formula.new(
184
+ flatten_mrow,
185
+ Utility.mrow_left_right(flatten_mrow),
186
+ )
173
187
  end
174
- Math::Formula.new(mrow.flatten.compact)
175
188
  end
176
189
 
177
190
  rule(msrow: sequence(:msrow)) do
@@ -184,8 +197,15 @@ module Plurimath
184
197
  )
185
198
  end
186
199
 
187
- rule(mover: sequence(:mover)) do
188
- if ["ubrace", "obrace"].any?(mover.last.class_name)
200
+ rule(mover: subtree(:mover)) do
201
+ Utility.binary_function_classes(mover, under: true)
202
+ if mover&.length == 1
203
+ if mover.first.class_name == "underline"
204
+ mover.first.swap_class
205
+ else
206
+ mover.first
207
+ end
208
+ elsif Constants::CLASSES.any?(mover&.last&.class_name)
189
209
  mover.last.parameter_one = mover.shift if mover.length > 1
190
210
  mover.last
191
211
  else
@@ -202,9 +222,16 @@ module Plurimath
202
222
  munder[ind] = Utility.mathml_unary_classes([object]) if object.is_a?(String)
203
223
  end
204
224
  end
225
+ Utility.binary_function_classes(munder, under: true)
205
226
  if ["ubrace", "obrace"].any?(munder.last.class_name)
206
227
  munder.last.parameter_one = munder.shift if munder.length > 1
207
228
  munder.last
229
+ elsif munder.length == 1
230
+ if munder.first.class_name == "bar"
231
+ munder.first.swap_class
232
+ else
233
+ munder.last
234
+ end
208
235
  else
209
236
  Math::Function::Underset.new(
210
237
  munder[1],
@@ -308,10 +335,12 @@ module Plurimath
308
335
 
309
336
  rule(attributes: subtree(:attrs),
310
337
  value: sequence(:value)) do
311
- Utility.join_attr_value(
312
- attrs.is_a?(Hash) ? nil : attrs,
313
- value&.flatten&.compact,
314
- )
338
+ approved_attrs = if attrs.is_a?(Hash)
339
+ attrs.keys.any? { |k| ["accentunder", "accent"].include?(k.to_s) } ? attrs : nil
340
+ else
341
+ attrs
342
+ end
343
+ Utility.join_attr_value(approved_attrs, value&.flatten&.compact)
315
344
  end
316
345
  end
317
346
  end
@@ -6,6 +6,12 @@ module Plurimath
6
6
  class Parser
7
7
  attr_accessor :text
8
8
 
9
+ CUSTOMIZABLE_TAGS = %w[
10
+ eqArr
11
+ mr
12
+ r
13
+ ].freeze
14
+
9
15
  def initialize(text)
10
16
  @text = text
11
17
  end
@@ -33,17 +39,34 @@ module Plurimath
33
39
  },
34
40
  }
35
41
  else
36
- organize_table_td(node) if %w[mr eqArr].include?(node.name)
42
+ customize_tags(node) if CUSTOMIZABLE_TAGS.include?(node.name)
37
43
  { node.name => parse_nodes(node.nodes) }
38
44
  end
39
45
  end
40
46
  end
41
47
 
48
+ def customize_tags(node)
49
+ case node.name
50
+ when "r"
51
+ organize_fonts(node)
52
+ when "mr", "eqArr"
53
+ organize_table_td(node)
54
+ end
55
+ end
56
+
42
57
  def organize_table_td(node)
43
58
  node.locate("e/?").each do |child_node|
44
59
  child_node.name = "mtd" if child_node.name == "r"
45
60
  end
46
61
  end
62
+
63
+ def organize_fonts(node)
64
+ attrs_arr = { val: [] }
65
+ node.locate("rPr/?").each do |child|
66
+ attrs_arr[:val] << child.attributes["val"]
67
+ end
68
+ node.attributes.merge! attrs_arr
69
+ end
47
70
  end
48
71
  end
49
72
  end