plurimath 0.7.2 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/Latex-Supported-Data.adoc +1 -0
  4. data/UnicodeMath-Supported-Data.adoc +1342 -0
  5. data/UnitsML-Supported-Data.adoc +444 -0
  6. data/lib/plurimath/asciimath/parse.rb +1 -1
  7. data/lib/plurimath/asciimath/transform.rb +2 -6
  8. data/lib/plurimath/latex/constants.rb +2 -0
  9. data/lib/plurimath/math/core.rb +38 -6
  10. data/lib/plurimath/math/formula.rb +60 -6
  11. data/lib/plurimath/math/function/abs.rb +4 -0
  12. data/lib/plurimath/math/function/arg.rb +22 -0
  13. data/lib/plurimath/math/function/bar.rb +4 -0
  14. data/lib/plurimath/math/function/base.rb +49 -0
  15. data/lib/plurimath/math/function/binary_function.rb +6 -0
  16. data/lib/plurimath/math/function/cancel.rb +5 -0
  17. data/lib/plurimath/math/function/ceil.rb +6 -0
  18. data/lib/plurimath/math/function/color.rb +20 -1
  19. data/lib/plurimath/math/function/ddot.rb +4 -0
  20. data/lib/plurimath/math/function/dot.rb +5 -0
  21. data/lib/plurimath/math/function/fenced.rb +98 -7
  22. data/lib/plurimath/math/function/floor.rb +6 -0
  23. data/lib/plurimath/math/function/font_style/monospace.rb +4 -0
  24. data/lib/plurimath/math/function/font_style.rb +31 -6
  25. data/lib/plurimath/math/function/frac.rb +69 -15
  26. data/lib/plurimath/math/function/hat.rb +4 -0
  27. data/lib/plurimath/math/function/inf.rb +30 -0
  28. data/lib/plurimath/math/function/int.rb +47 -1
  29. data/lib/plurimath/math/function/intent.rb +22 -0
  30. data/lib/plurimath/math/function/left.rb +4 -0
  31. data/lib/plurimath/math/function/lim.rb +6 -0
  32. data/lib/plurimath/math/function/limits.rb +28 -0
  33. data/lib/plurimath/math/function/linebreak.rb +5 -0
  34. data/lib/plurimath/math/function/log.rb +27 -20
  35. data/lib/plurimath/math/function/longdiv.rb +4 -0
  36. data/lib/plurimath/math/function/mbox.rb +4 -0
  37. data/lib/plurimath/math/function/menclose.rb +74 -5
  38. data/lib/plurimath/math/function/merror.rb +2 -0
  39. data/lib/plurimath/math/function/mglyph.rb +64 -0
  40. data/lib/plurimath/math/function/mlabeledtr.rb +29 -0
  41. data/lib/plurimath/math/function/mod.rb +4 -0
  42. data/lib/plurimath/math/function/mpadded.rb +84 -0
  43. data/lib/plurimath/math/function/ms.rb +33 -0
  44. data/lib/plurimath/math/function/msgroup.rb +4 -0
  45. data/lib/plurimath/math/function/msline.rb +2 -4
  46. data/lib/plurimath/math/function/multiscript.rb +70 -6
  47. data/lib/plurimath/math/function/nary.rb +69 -10
  48. data/lib/plurimath/math/function/none.rb +25 -0
  49. data/lib/plurimath/math/function/norm.rb +6 -0
  50. data/lib/plurimath/math/function/obrace.rb +4 -0
  51. data/lib/plurimath/math/function/oint.rb +25 -1
  52. data/lib/plurimath/math/function/over.rb +6 -0
  53. data/lib/plurimath/math/function/overset.rb +46 -1
  54. data/lib/plurimath/math/function/phantom.rb +18 -2
  55. data/lib/plurimath/math/function/power.rb +37 -0
  56. data/lib/plurimath/math/function/power_base.rb +45 -18
  57. data/lib/plurimath/math/function/prod.rb +46 -0
  58. data/lib/plurimath/math/function/right.rb +4 -0
  59. data/lib/plurimath/math/function/root.rb +9 -1
  60. data/lib/plurimath/math/function/rule.rb +4 -0
  61. data/lib/plurimath/math/function/sqrt.rb +7 -1
  62. data/lib/plurimath/math/function/stackrel.rb +6 -0
  63. data/lib/plurimath/math/function/substack.rb +4 -0
  64. data/lib/plurimath/math/function/sum.rb +45 -24
  65. data/lib/plurimath/math/function/table/bmatrix.rb +18 -5
  66. data/lib/plurimath/math/function/table/cases.rb +24 -0
  67. data/lib/plurimath/math/function/table/eqarray.rb +24 -0
  68. data/lib/plurimath/math/function/table/matrix.rb +23 -3
  69. data/lib/plurimath/math/function/table/pmatrix.rb +4 -0
  70. data/lib/plurimath/math/function/table/vmatrix.rb +10 -0
  71. data/lib/plurimath/math/function/table.rb +58 -7
  72. data/lib/plurimath/math/function/td.rb +9 -0
  73. data/lib/plurimath/math/function/ternary_function.rb +14 -1
  74. data/lib/plurimath/math/function/text.rb +6 -0
  75. data/lib/plurimath/math/function/tilde.rb +4 -0
  76. data/lib/plurimath/math/function/tr.rb +9 -0
  77. data/lib/plurimath/math/function/ubrace.rb +5 -0
  78. data/lib/plurimath/math/function/ul.rb +4 -0
  79. data/lib/plurimath/math/function/unary_function.rb +4 -0
  80. data/lib/plurimath/math/function/underover.rb +14 -0
  81. data/lib/plurimath/math/function/underset.rb +49 -1
  82. data/lib/plurimath/math/function/vec.rb +4 -0
  83. data/lib/plurimath/math/number.rb +33 -3
  84. data/lib/plurimath/math/symbol.rb +68 -3
  85. data/lib/plurimath/math.rb +3 -2
  86. data/lib/plurimath/mathml/constants.rb +16 -0
  87. data/lib/plurimath/mathml/parser.rb +42 -2
  88. data/lib/plurimath/mathml/transform.rb +80 -29
  89. data/lib/plurimath/omml/parser.rb +8 -0
  90. data/lib/plurimath/omml/transform.rb +29 -26
  91. data/lib/plurimath/unicode_math/constants.rb +1014 -0
  92. data/lib/plurimath/unicode_math/parse.rb +233 -0
  93. data/lib/plurimath/unicode_math/parser.rb +58 -0
  94. data/lib/plurimath/unicode_math/parsing_rules/absence_rules.rb +138 -0
  95. data/lib/plurimath/unicode_math/parsing_rules/common_rules.rb +114 -0
  96. data/lib/plurimath/unicode_math/parsing_rules/constants_rules.rb +102 -0
  97. data/lib/plurimath/unicode_math/parsing_rules/helper.rb +19 -0
  98. data/lib/plurimath/unicode_math/parsing_rules/masked.rb +62 -0
  99. data/lib/plurimath/unicode_math/parsing_rules/sub_sup.rb +254 -0
  100. data/lib/plurimath/unicode_math/transform.rb +3831 -0
  101. data/lib/plurimath/{unicode.rb → unicode_math.rb} +2 -2
  102. data/lib/plurimath/unitsml.rb +14 -1
  103. data/lib/plurimath/utility.rb +346 -11
  104. data/lib/plurimath/version.rb +1 -1
  105. data/lib/plurimath/xml_engine/oga.rb +5 -0
  106. data/lib/plurimath/xml_engine/ox.rb +5 -0
  107. metadata +25 -3
@@ -12,19 +12,47 @@ module Plurimath
12
12
  third_value: "supscript",
13
13
  }.freeze
14
14
 
15
+ def to_asciimath
16
+ subscript = "_(#{parameter_two&.map(&:to_asciimath).join})" unless valid_value_exist?(parameter_two)
17
+ supscript = "^(#{parameter_three&.map(&:to_asciimath).join})" unless valid_value_exist?(parameter_three)
18
+ prescript = "\\ #{subscript}#{supscript}" if subscript || supscript
19
+ "#{prescript}#{parameter_one&.to_asciimath}"
20
+ end
21
+
22
+ def to_latex
23
+ subscript = "_{#{parameter_two&.map(&:to_latex).join}}" unless valid_value_exist?(parameter_two)
24
+ supscript = "^{#{parameter_three&.map(&:to_latex).join}}" unless valid_value_exist?(parameter_three)
25
+ prescript = "{}#{subscript}#{supscript}" if subscript || supscript
26
+ "#{prescript}#{parameter_one&.to_latex}"
27
+ end
28
+
29
+ def to_mathml_without_math_tag
30
+ mprescript = ox_element("mprescripts") if (parameter_two || parameter_three)
31
+ Utility.update_nodes(
32
+ ox_element("mmultiscripts"),
33
+ [
34
+ parameter_one&.mmultiscript,
35
+ mprescript,
36
+ validate_mathml_fields(prescripts),
37
+ ]
38
+ )
39
+ end
40
+
15
41
  def to_omml_without_math_tag(display_style)
16
- pre_element = Utility.ox_element("sPre", namespace: "m")
17
- pr_element = Utility.ox_element("sPrePr", namespace: "m")
18
42
  Utility.update_nodes(
19
- pre_element,
43
+ ox_element("sPre", namespace: "m"),
20
44
  [
21
- pr_element << Utility.pr_element("ctrl", true, namespace: "m"),
45
+ omml_parameter(parameter_one, display_style, tag_name: "e"),
22
46
  omml_parameter(parameter_two, display_style, tag_name: "sub"),
23
47
  omml_parameter(parameter_three, display_style, tag_name: "sup"),
24
- omml_parameter(parameter_one, display_style, tag_name: "e"),
25
48
  ],
26
49
  )
27
- [pre_element]
50
+ end
51
+
52
+ def to_unicodemath
53
+ first_value = sub_value if unicode_valid_value?(parameter_two)
54
+ second_value = sup_value if unicode_valid_value?(parameter_three)
55
+ "#{first_value}#{second_value} #{parameter_one&.to_unicodemath}"
28
56
  end
29
57
 
30
58
  def line_breaking(obj)
@@ -46,6 +74,42 @@ module Plurimath
46
74
  self.parameter_three = nil
47
75
  end
48
76
  end
77
+
78
+ private
79
+
80
+ def prescripts
81
+ Array(parameter_two)&.zip(Array(parameter_three))&.flatten&.compact
82
+ end
83
+
84
+ def valid_value_exist?(field)
85
+ !field && (field&.empty? || field&.all?(None))
86
+ end
87
+
88
+ def unicode_valid_value?(field)
89
+ !field.empty? && !valid_value_exist?(field)
90
+ end
91
+
92
+ def sup_value
93
+ field = Utility.filter_values(parameter_two)
94
+ if field&.mini_sized? || prime_unicode?(field)
95
+ parameter_three.map(&:to_unicodemath).join
96
+ elsif field.is_a?(Math::Function::Power)
97
+ "^#{parameter_three.map(&:to_unicodemath).join}"
98
+ elsif parameter_three && !parameter_three.empty?
99
+ "^(#{parameter_three.map(&:to_unicodemath).join})"
100
+ end
101
+ end
102
+
103
+ def sub_value
104
+ field = Utility.filter_values(parameter_two)
105
+ if field&.mini_sized?
106
+ parameter_two.map(&:to_unicodemath).join
107
+ elsif parameter_two.is_a?(Math::Function::Base)
108
+ "_#{parameter_two.map(&:to_unicodemath).join}"
109
+ elsif parameter_two && !parameter_two.empty?
110
+ "_(#{parameter_two.map(&:to_unicodemath).join})"
111
+ end
112
+ end
49
113
  end
50
114
  end
51
115
  end
@@ -30,22 +30,31 @@ module Plurimath
30
30
 
31
31
  def to_asciimath
32
32
  first_value = parameter_one&.to_asciimath || "int"
33
- second_value = "_#{parameter_two.to_asciimath}" if parameter_two
34
- third_value = "^#{parameter_three.to_asciimath}" if parameter_three
33
+ second_value = "_(#{parameter_two.to_asciimath})" if parameter_two
34
+ third_value = "^(#{parameter_three.to_asciimath})" if parameter_three
35
35
  fourth_value = " #{parameter_four.to_asciimath}" if parameter_four
36
36
  "#{first_value}#{second_value}#{third_value}#{fourth_value}"
37
37
  end
38
38
 
39
39
  def to_latex
40
40
  first_value = parameter_one&.to_latex || "\\int"
41
- second_value = "_#{parameter_two.to_latex}" if parameter_two
42
- third_value = "^#{parameter_three.to_latex}" if parameter_three
43
- fourth_value = "{#{parameter_four.to_latex}}" if parameter_four
41
+ second_value = "_{#{parameter_two.to_latex}}" if parameter_two
42
+ third_value = "^{#{parameter_three.to_latex}}" if parameter_three
43
+ fourth_value = " #{parameter_four.to_latex}" if parameter_four
44
44
  "#{first_value}#{second_value}#{third_value}#{fourth_value}"
45
45
  end
46
46
 
47
47
  def to_mathml_without_math_tag
48
48
  tag_name = options[:type] == "undOvr" ? "munderover" : "msubsup"
49
+ if !(parameter_two && parameter_three)
50
+ tag_name = if parameter_two
51
+ tag_name == "munderover" ? "munder" : "msub"
52
+ elsif parameter_three
53
+ tag_name == "munderover" ? "mover" : "msup"
54
+ else
55
+ 'mrow'
56
+ end
57
+ end
49
58
  subsup_tag = ox_element(tag_name)
50
59
  new_arr = [
51
60
  validate_mathml_fields(parameter_one),
@@ -56,10 +65,10 @@ module Plurimath
56
65
  return subsup_tag unless parameter_four
57
66
 
58
67
  Utility.update_nodes(
59
- ox_element("mrow"),
68
+ row_tag,
60
69
  [
61
70
  subsup_tag,
62
- parameter_four&.to_mathml_without_math_tag,
71
+ (row_tag << validate_mathml_fields(parameter_four)),
63
72
  ],
64
73
  )
65
74
  end
@@ -70,10 +79,20 @@ module Plurimath
70
79
  Array(nary_element)
71
80
  end
72
81
 
82
+ def to_unicodemath
83
+ first_value = sub_value if parameter_two
84
+ second_value = sup_value if parameter_three
85
+ if prime_unicode?(parameter_three)
86
+ "#{parameter_one&.to_unicodemath}#{second_value}#{first_value}#{naryand_value(parameter_four)}"
87
+ else
88
+ "#{parameter_one&.to_unicodemath}#{first_value}#{second_value}#{naryand_value(parameter_four)}"
89
+ end
90
+ end
91
+
73
92
  def line_breaking(obj)
74
93
  parameter_one&.line_breaking(obj)
75
94
  if obj.value_exist?
76
- obj.update(self.class.new(Utility.filter_values(obj.value), self.parameter_two, self.parameter_three, self.parameter_four))
95
+ obj.update(self.class.new(Utility.filter_values(obj.value), self.parameter_two, self.parameter_three, self.parameter_four, self.options))
77
96
  self.parameter_two = nil
78
97
  self.parameter_three = nil
79
98
  self.parameter_four = nil
@@ -82,7 +101,7 @@ module Plurimath
82
101
 
83
102
  parameter_two&.line_breaking(obj)
84
103
  if obj.value_exist?
85
- obj.update(self.class.new(nil, Utility.filter_values(obj.value), self.parameter_three, self.parameter_four))
104
+ obj.update(self.class.new(nil, Utility.filter_values(obj.value), self.parameter_three, self.parameter_four, self.options))
86
105
  self.parameter_three = nil
87
106
  self.parameter_four = nil
88
107
  return
@@ -100,7 +119,7 @@ module Plurimath
100
119
  first_value = Utility.html_entity_to_unicode(parameter_one&.nary_attr_value)
101
120
  narypr << Utility.ox_element("chr", namespace: "m", attributes: { "m:val": first_value }) unless first_value == "∫"
102
121
 
103
- narypr << Utility.ox_element("limLoc", namespace: "m", attributes: { "m:val": options[:type].to_s })
122
+ narypr << Utility.ox_element("limLoc", namespace: "m", attributes: { "m:val": (options[:type] || "subSup").to_s })
104
123
  hide_tags(narypr, parameter_two, "sub")
105
124
  hide_tags(narypr, parameter_three, "sup")
106
125
  narypr
@@ -122,6 +141,46 @@ module Plurimath
122
141
  omml_parameter(parameter_four, display_style, tag_name: "e"),
123
142
  ]
124
143
  end
144
+
145
+ def row_tag
146
+ Utility.ox_element("mrow")
147
+ end
148
+
149
+ def sup_value
150
+ if parameter_three.mini_sized? || prime_unicode?(parameter_three)
151
+ parameter_three.to_unicodemath
152
+ elsif parameter_three.is_a?(Math::Function::Power)
153
+ "^#{parameter_three.to_unicodemath}"
154
+ elsif parameter_one.is_a?(Math::Function::Power) && parameter_one&.prime_unicode?(parameter_one&.parameter_two)
155
+ "^#{parameter_three.to_unicodemath}"
156
+ else
157
+ "^#{unicodemath_parens(parameter_three)}"
158
+ end
159
+ end
160
+
161
+ def sub_value
162
+ if parameter_two.mini_sized?
163
+ parameter_two.to_unicodemath
164
+ elsif parameter_two.is_a?(Math::Function::Base)
165
+ "_#{parameter_two.to_unicodemath}"
166
+ else
167
+ "_#{unicodemath_parens(parameter_two)}"
168
+ end
169
+ end
170
+
171
+ def prime_unicode?(field)
172
+ return unless field.is_a?(Math::Symbol)
173
+ return true if field.value.include?("&#x27;")
174
+
175
+ UnicodeMath::Constants::PREFIXED_PRIMES.any? { |prefix, prime| field.value.include?(prime) }
176
+ end
177
+
178
+ def naryand_value(field)
179
+ return "" unless field
180
+
181
+ field_value = field.to_unicodemath
182
+ field.is_a?(Math::Function::Fenced) ? "▒#{field_value}" : "▒〖#{field_value}〗"
183
+ end
125
184
  end
126
185
  end
127
186
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "unary_function"
4
+
5
+ module Plurimath
6
+ module Math
7
+ module Function
8
+ class None < UnaryFunction
9
+ def to_asciimath; end
10
+
11
+ def to_latex; end
12
+
13
+ def to_mathml_without_math_tag
14
+ ox_element("none")
15
+ end
16
+
17
+ def to_omml_without_math_tag(_)
18
+ empty_tag
19
+ end
20
+
21
+ def to_unicodemath; end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -24,6 +24,12 @@ module Plurimath
24
24
  Utility.update_nodes(ox_element("mrow"), first_value)
25
25
  end
26
26
 
27
+ def to_unicodemath
28
+ first_value = "&#x2016;" unless open_paren
29
+ second_value = "&#x2016;" unless close_paren
30
+ "#{first_value}#{parameter_one&.to_unicodemath}#{second_value}"
31
+ end
32
+
27
33
  def to_omml_without_math_tag(display_style)
28
34
  array = []
29
35
  array << r_element("∥") unless open_paren
@@ -53,6 +53,10 @@ module Plurimath
53
53
  end
54
54
  end
55
55
 
56
+ def to_unicodemath
57
+ "⏞(#{parameter_one&.to_unicodemath})"
58
+ end
59
+
56
60
  def line_breaking(obj)
57
61
  parameter_one&.line_breaking(obj)
58
62
  obj.update(Utility.filter_values(obj.value)) if obj.value_exist?
@@ -6,11 +6,24 @@ module Plurimath
6
6
  module Math
7
7
  module Function
8
8
  class Oint < TernaryFunction
9
+ attr_accessor :options
9
10
  FUNCTION = {
10
11
  name: "contour integral",
11
12
  first_value: "subscript",
12
13
  second_value: "supscript",
13
- }
14
+ }.freeze
15
+
16
+ def initialize(parameter_one = nil,
17
+ parameter_two = nil,
18
+ parameter_three = nil,
19
+ options = {})
20
+ super(parameter_one, parameter_two, parameter_three)
21
+ @options = options unless options&.empty?
22
+ end
23
+
24
+ def ==(object)
25
+ super(object) && object.options == options
26
+ end
14
27
 
15
28
  def to_asciimath
16
29
  first_value = "_#{wrapped(parameter_one)}" if parameter_one
@@ -75,6 +88,13 @@ module Plurimath
75
88
  end
76
89
  end
77
90
 
91
+ def to_unicodemath
92
+ first_value = "_#{unicodemath_parens(parameter_one)}" if parameter_one
93
+ second_value = "^#{unicodemath_parens(parameter_two)}" if parameter_two
94
+ mask = options&.dig(:mask) if options&.key?(:mask)
95
+ "∮#{mask}#{first_value}#{second_value}#{naryand_value(parameter_three)}"
96
+ end
97
+
78
98
  def line_breaking(obj)
79
99
  parameter_one&.line_breaking(obj)
80
100
  if obj.value_exist?
@@ -91,6 +111,10 @@ module Plurimath
91
111
  obj.update(Utility.filter_values(obj.value))
92
112
  end
93
113
  end
114
+
115
+ def is_nary_function?
116
+ true
117
+ end
94
118
  end
95
119
  end
96
120
  end
@@ -47,6 +47,12 @@ module Plurimath
47
47
  [f_element]
48
48
  end
49
49
 
50
+ def to_unicodemath
51
+ first_value = unicodemath_parens(parameter_one) if parameter_one
52
+ second_value = unicodemath_parens(parameter_two) if parameter_two
53
+ "#{first_value}/#{second_value}"
54
+ end
55
+
50
56
  def line_breaking(obj)
51
57
  parameter_one&.line_breaking(obj)
52
58
  if obj.value_exist?
@@ -6,18 +6,27 @@ module Plurimath
6
6
  module Math
7
7
  module Function
8
8
  class Overset < BinaryFunction
9
+ attr_accessor :options
9
10
  FUNCTION = {
10
11
  name: "overset",
11
12
  first_value: "base",
12
13
  second_value: "supscript",
13
14
  }.freeze
14
15
 
16
+ def initialize(
17
+ parameter_one = nil,
18
+ parameter_two = nil,
19
+ options = {})
20
+ super(parameter_one, parameter_two)
21
+ @options = options unless options.empty?
22
+ end
23
+
15
24
  def to_mathml_without_math_tag
16
25
  value_array = [
17
26
  validate_mathml_fields(parameter_two),
18
27
  validate_mathml_fields(parameter_one),
19
28
  ]
20
- Utility.update_nodes(ox_element("mover"), value_array)
29
+ Utility.update_nodes(ox_element("mover", attributes: options), value_array)
21
30
  end
22
31
 
23
32
  def to_omml_without_math_tag(display_style)
@@ -40,6 +49,15 @@ module Plurimath
40
49
  [limupp]
41
50
  end
42
51
 
52
+ def to_unicodemath
53
+ return "#{unicodemath_parens(parameter_two)}#{parameter_one.value}" if unicode_accent?(parameter_one)
54
+ return "#{parameter_one.value}#{parameter_two.to_unicodemath}" if unicode_accent?(parameter_two)
55
+ return "#{parameter_one.to_unicodemath}#{unicodemath_parens(parameter_two)}" if horizontal_brackets?
56
+ return "#{parameter_two.to_unicodemath}^#{unicodemath_parens(parameter_one)}" if unicode_classes_accent?(parameter_two)
57
+
58
+ "#{unicodemath_parens(parameter_two)}┴#{unicodemath_parens(parameter_one)}" if parameter_one || parameter_two
59
+ end
60
+
43
61
  def line_breaking(obj)
44
62
  parameter_two&.line_breaking(obj)
45
63
  if obj.value_exist?
@@ -47,6 +65,33 @@ module Plurimath
47
65
  self.parameter_one = nil
48
66
  end
49
67
  end
68
+
69
+ def new_nary_function(fourth_value)
70
+ Nary.new(parameter_two, nil, parameter_one, fourth_value, { type: "undOvr" })
71
+ end
72
+
73
+ def is_nary_function?
74
+ parameter_two.is_nary_function? || parameter_two.is_nary_symbol?
75
+ end
76
+
77
+ protected
78
+
79
+ def unicode_accent?(field)
80
+ field.is_a?(Math::Symbol) &&
81
+ (
82
+ UnicodeMath::Constants::DIACRITIC_OVERLAYS.include?(field.value) ||
83
+ UnicodeMath::Constants::ACCENT_SYMBOLS.has_value?(field.value)
84
+ )
85
+ end
86
+
87
+ def unicode_classes_accent?(field)
88
+ (field.is_a?(Math::Function::Obrace) || field.is_a?(Math::Function::Ubrace))
89
+ end
90
+
91
+ def horizontal_brackets?
92
+ parameter_one.is_a?(Math::Symbol) &&
93
+ UnicodeMath::Constants::HORIZONTAL_BRACKETS.value?(parameter_one.value)
94
+ end
50
95
  end
51
96
  end
52
97
  end
@@ -32,6 +32,14 @@ module Plurimath
32
32
  Utility.update_nodes(phant, [phant_pr, e_tag])
33
33
  end
34
34
 
35
+ def to_unicodemath
36
+ if parameter_one.is_a?(Math::Function::Mpadded) && parameter_one&.options&.dig(:phantom)
37
+ "#{phantom_unicode}#{unicodemath_parens(parameter_one.parameter_one)}"
38
+ else
39
+ "⟡#{unicodemath_parens(parameter_one)}"
40
+ end
41
+ end
42
+
35
43
  def line_breaking(obj)
36
44
  custom_array_line_breaking(obj)
37
45
  end
@@ -39,10 +47,18 @@ module Plurimath
39
47
  protected
40
48
 
41
49
  def phant_pr
42
- attributes = { val: "m:off" }
43
- phant = Utility.ox_element("phant", namespace: "m")
50
+ attributes = { "m:val": "off" }
51
+ phant = Utility.ox_element("phantPr", namespace: "m")
44
52
  phant << Utility.ox_element("show", namespace: "m", attributes: attributes)
45
53
  end
54
+
55
+ def phantom_symbol
56
+ UnicodeMath::Constants::PHANTOM_SYMBOLS.key(parameter_one.options)
57
+ end
58
+
59
+ def phantom_unicode
60
+ UnicodeMath::Constants::UNARY_SYMBOLS[phantom_symbol]
61
+ end
46
62
  end
47
63
  end
48
64
  end
@@ -53,6 +53,22 @@ module Plurimath
53
53
  [ssup_element]
54
54
  end
55
55
 
56
+ def to_unicodemath
57
+ if accented?(parameter_two)
58
+ "#{parameter_one.to_unicodemath}#{parameter_two.to_unicodemath}"
59
+ elsif parameter_two.mini_sized?
60
+ "#{parameter_one.to_unicodemath}#{parameter_two.to_unicodemath}"
61
+ else
62
+ first_value = parameter_one.to_unicodemath if parameter_one
63
+ second_value = if parameter_two.is_a?(self.class)
64
+ "^#{parameter_two.to_unicodemath}"
65
+ else
66
+ "^#{unicodemath_parens(parameter_two)}"
67
+ end
68
+ "#{first_value}#{second_value}"
69
+ end
70
+ end
71
+
56
72
  def line_breaking(obj)
57
73
  parameter_one&.line_breaking(obj)
58
74
  if obj.value_exist?
@@ -60,6 +76,27 @@ module Plurimath
60
76
  self.parameter_two = nil
61
77
  end
62
78
  end
79
+
80
+ def new_nary_function(fourth_value)
81
+ Nary.new(parameter_one, nil, parameter_two, fourth_value)
82
+ end
83
+
84
+ def is_nary_function?
85
+ parameter_one.is_nary_function? || parameter_one.is_nary_symbol?
86
+ end
87
+
88
+ def prime_unicode?(field)
89
+ return unless field.is_a?(Math::Symbol)
90
+
91
+ UnicodeMath::Constants::PREFIXED_PRIMES.any? { |prefix, prime| field.value.include?(prime) || field.value.include?("&#x27;") }
92
+ end
93
+
94
+ protected
95
+
96
+ def accented?(field)
97
+ (field.is_a?(Math::Symbol) && prime_unicode?(field)) ||
98
+ (field.is_a?(Math::Function::Power) && prime_unicode?(field.parameter_one))
99
+ end
63
100
  end
64
101
  end
65
102
  end
@@ -43,9 +43,7 @@ module Plurimath
43
43
 
44
44
  ssubsup = Utility.ox_element("sSubSup", namespace: "m")
45
45
  ssubsuppr = Utility.ox_element("sSubSupPr", namespace: "m")
46
- ssubsuppr << hide_tags(
47
- Utility.pr_element("ctrl", true, namespace: "m"),
48
- )
46
+ ssubsuppr << Utility.pr_element("ctrl", true, namespace: "m")
49
47
  Utility.update_nodes(
50
48
  ssubsup,
51
49
  [
@@ -58,6 +56,16 @@ module Plurimath
58
56
  [ssubsup]
59
57
  end
60
58
 
59
+ def to_unicodemath
60
+ first_value = sub_value if parameter_two
61
+ second_value = sup_value if parameter_three
62
+ if prime_unicode?(parameter_three)
63
+ "#{parameter_one&.to_unicodemath}#{second_value}#{first_value}"
64
+ else
65
+ "#{parameter_one&.to_unicodemath}#{first_value}#{second_value}"
66
+ end
67
+ end
68
+
61
69
  def line_breaking(obj)
62
70
  parameter_one&.line_breaking(obj)
63
71
  if obj.value_exist?
@@ -78,25 +86,44 @@ module Plurimath
78
86
  end
79
87
  end
80
88
 
89
+ def new_nary_function(fourth_value)
90
+ Nary.new(parameter_one, parameter_two, parameter_three, fourth_value)
91
+ end
92
+
93
+ def is_nary_function?
94
+ parameter_one.is_nary_function? || parameter_one.is_nary_symbol?
95
+ end
96
+
97
+ def mmultiscript
98
+ [
99
+ validate_mathml_fields(parameter_one),
100
+ validate_mathml_fields(parameter_two),
101
+ validate_mathml_fields(parameter_three),
102
+ ]
103
+ end
104
+
81
105
  protected
82
106
 
83
- def hide_tags(nar)
84
- attr = { "m:val": "1" }
85
- if parameter_two.nil?
86
- nar << Utility.ox_element(
87
- "subHide",
88
- namespace: "m",
89
- attributes: attr,
90
- )
107
+ def sup_value
108
+ if parameter_three.mini_sized? || prime_unicode?(parameter_three)
109
+ parameter_three.to_unicodemath
110
+ elsif parameter_three.is_a?(Math::Function::Power)
111
+ "^#{parameter_three.to_unicodemath}"
112
+ elsif parameter_one.is_a?(Math::Function::Power) && parameter_one&.prime_unicode?(parameter_one&.parameter_two)
113
+ "^#{parameter_three.to_unicodemath}"
114
+ else
115
+ "^#{unicodemath_parens(parameter_three)}"
91
116
  end
92
- if parameter_three.nil?
93
- nar << Utility.ox_element(
94
- "supHide",
95
- namespace: "m",
96
- attributes: attr,
97
- )
117
+ end
118
+
119
+ def sub_value
120
+ if parameter_two.mini_sized?
121
+ parameter_two.to_unicodemath
122
+ elsif parameter_two.is_a?(Math::Function::Base)
123
+ "_#{parameter_two.to_unicodemath}"
124
+ else
125
+ "_#{unicodemath_parens(parameter_two)}"
98
126
  end
99
- nar
100
127
  end
101
128
  end
102
129
  end
@@ -6,12 +6,25 @@ module Plurimath
6
6
  module Math
7
7
  module Function
8
8
  class Prod < TernaryFunction
9
+ attr_accessor :options
9
10
  FUNCTION = {
10
11
  name: "prod",
11
12
  first_value: "subscript",
12
13
  second_value: "supscript",
13
14
  }.freeze
14
15
 
16
+ def initialize(parameter_one = nil,
17
+ parameter_two = nil,
18
+ parameter_three = nil,
19
+ options = {})
20
+ super(parameter_one, parameter_two, parameter_three)
21
+ @options = options unless options&.empty?
22
+ end
23
+
24
+ def ==(object)
25
+ super(object) && object.options == options
26
+ end
27
+
15
28
  def to_asciimath
16
29
  first_value = "_#{wrapped(parameter_one)}" if parameter_one
17
30
  second_value = "^#{wrapped(parameter_two)}" if parameter_two
@@ -71,6 +84,13 @@ module Plurimath
71
84
  [nary]
72
85
  end
73
86
 
87
+ def to_unicodemath
88
+ first_value = sub_value if parameter_one
89
+ second_value = sup_value if parameter_two
90
+ mask = options&.dig(:mask) if options&.key?(:mask)
91
+ "#{nary_attr_value}#{mask}#{first_value}#{second_value}#{naryand_value(parameter_three)}"
92
+ end
93
+
74
94
  def nary_values(display_style)
75
95
  [
76
96
  narypr(hide_function_name ? "" : nary_attr_value),
@@ -98,6 +118,32 @@ module Plurimath
98
118
  obj.update(Utility.filter_values(obj.value))
99
119
  end
100
120
  end
121
+
122
+ def is_nary_function?
123
+ true
124
+ end
125
+
126
+ protected
127
+
128
+ def sup_value
129
+ if parameter_two&.mini_sized? || prime_unicode?(parameter_two)
130
+ parameter_two.to_unicodemath
131
+ elsif parameter_two.is_a?(Math::Function::Power)
132
+ "^#{parameter_two.to_unicodemath}"
133
+ else
134
+ "^#{unicodemath_parens(parameter_two)}"
135
+ end
136
+ end
137
+
138
+ def sub_value
139
+ if parameter_one&.mini_sized?
140
+ parameter_one.to_unicodemath
141
+ elsif parameter_one.is_a?(Math::Function::Base)
142
+ "_#{parameter_one.to_unicodemath}"
143
+ else
144
+ "_#{unicodemath_parens(parameter_one)}"
145
+ end
146
+ end
101
147
  end
102
148
  end
103
149
  end
@@ -33,6 +33,10 @@ module Plurimath
33
33
  "\\right #{latex_paren}"
34
34
  end
35
35
 
36
+ def to_unicodemath
37
+ parameter_one
38
+ end
39
+
36
40
  def validate_function_formula
37
41
  false
38
42
  end