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
@@ -6,18 +6,27 @@ module Plurimath
6
6
  module Math
7
7
  module Function
8
8
  class Underset < BinaryFunction
9
+ attr_accessor :options
9
10
  FUNCTION = {
10
11
  name: "underscript",
11
12
  first_value: "underscript value",
12
13
  second_value: "base expression",
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("munder"), value_array)
29
+ Utility.update_nodes(ox_element("munder", attributes: options), value_array)
21
30
  end
22
31
 
23
32
  def to_omml_without_math_tag(display_style)
@@ -40,6 +49,18 @@ module Plurimath
40
49
  [limlow]
41
50
  end
42
51
 
52
+ def to_unicodemath
53
+ if horizontal_brackets?
54
+ "#{parameter_one.to_unicodemath}#{unicodemath_parens(parameter_two)}"
55
+ elsif unicode_classes_accent?(parameter_two)
56
+ "#{parameter_two.to_unicodemath}_#{unicodemath_parens(parameter_one)}"
57
+ elsif unicode_accent?
58
+ "#{unicodemath_parens(parameter_two)}#{parameter_one.value}"
59
+ else
60
+ "#{unicodemath_parens(parameter_two)}┬#{parameter_one.to_unicodemath}"
61
+ end
62
+ end
63
+
43
64
  def line_breaking(obj)
44
65
  parameter_one&.line_breaking(obj)
45
66
  if obj.value_exist?
@@ -53,6 +74,33 @@ module Plurimath
53
74
  obj.update(self.class.new(nil, Utility.filter_values(obj.value)))
54
75
  end
55
76
  end
77
+
78
+ def new_nary_function(fourth_value)
79
+ Nary.new(parameter_two, parameter_one, nil, fourth_value, { type: "undOvr" })
80
+ end
81
+
82
+ def is_nary_function?
83
+ parameter_two.is_nary_function? || parameter_two.is_nary_symbol?
84
+ end
85
+
86
+ protected
87
+
88
+ def unicode_accent?
89
+ parameter_one.is_a?(Math::Symbol) &&
90
+ (
91
+ UnicodeMath::Constants::DIACRITIC_BELOWS.include?(parameter_one.value) ||
92
+ UnicodeMath::Constants::ACCENT_SYMBOLS.has_value?(parameter_one.value)
93
+ )
94
+ end
95
+
96
+ def horizontal_brackets?
97
+ parameter_one.is_a?(Math::Symbol) &&
98
+ UnicodeMath::Constants::HORIZONTAL_BRACKETS.value?(parameter_one.value)
99
+ end
100
+
101
+ def unicode_classes_accent?(field)
102
+ (field.is_a?(Math::Function::Obrace) || field.is_a?(Math::Function::Ubrace))
103
+ end
56
104
  end
57
105
  end
58
106
  end
@@ -37,6 +37,10 @@ module Plurimath
37
37
  end
38
38
  end
39
39
 
40
+ def to_unicodemath
41
+ "#{unicodemath_parens(parameter_one)}⃗"
42
+ end
43
+
40
44
  def to_asciimath_math_zone(spacing, last = false, _)
41
45
  new_spacing = gsub_spacing(spacing, last)
42
46
  new_arr = [
@@ -3,14 +3,19 @@
3
3
  module Plurimath
4
4
  module Math
5
5
  class Number < Core
6
- attr_accessor :value
6
+ attr_accessor :value, :mini_sub_sized, :mini_sup_sized
7
7
 
8
- def initialize(value)
8
+ def initialize(value, mini_sub_sized: false, mini_sup_sized: false)
9
9
  @value = value.is_a?(Parslet::Slice) ? value.to_s : value
10
+ @mini_sub_sized = mini_sub_sized if mini_sub_sized
11
+ @mini_sup_sized = mini_sup_sized if mini_sup_sized
10
12
  end
11
13
 
12
14
  def ==(object)
13
- object.respond_to?(:value) && object.value == value
15
+ object.respond_to?(:value) &&
16
+ object.value == value &&
17
+ object.mini_sub_sized == mini_sub_sized &&
18
+ object.mini_sup_sized == mini_sup_sized
14
19
  end
15
20
 
16
21
  def to_asciimath
@@ -33,6 +38,13 @@ module Plurimath
33
38
  [t_tag]
34
39
  end
35
40
 
41
+ def to_unicodemath
42
+ return mini_sub if mini_sub_sized
43
+ return mini_sup if mini_sup_sized
44
+
45
+ value
46
+ end
47
+
36
48
  def insert_t_tag(_)
37
49
  [
38
50
  (Utility.ox_element("r", namespace: "m") << t_tag),
@@ -54,6 +66,24 @@ module Plurimath
54
66
  def validate_function_formula
55
67
  false
56
68
  end
69
+
70
+ def mini_sized?
71
+ mini_sub_sized || mini_sup_sized
72
+ end
73
+
74
+ protected
75
+
76
+ def mini_sub
77
+ unicode_const(:SUB_DIGITS)[value.to_sym]
78
+ end
79
+
80
+ def mini_sup
81
+ unicode_const(:SUP_DIGITS)[value.to_sym]
82
+ end
83
+
84
+ def unicode_const(const)
85
+ UnicodeMath::Constants.const_get(const)
86
+ end
57
87
  end
58
88
  end
59
89
  end
@@ -3,14 +3,27 @@
3
3
  module Plurimath
4
4
  module Math
5
5
  class Symbol < Core
6
- attr_accessor :value
6
+ attr_accessor :value, :slashed, :mini_sub_sized, :mini_sup_sized, :options
7
7
 
8
- def initialize(sym = nil)
8
+ def initialize(sym = nil,
9
+ slashed = nil,
10
+ mini_sub_sized: false,
11
+ mini_sup_sized: false,
12
+ options: {})
9
13
  @value = sym.is_a?(Parslet::Slice) ? sym.to_s : sym
14
+ @slashed = slashed if slashed
15
+ @mini_sub_sized = mini_sub_sized if mini_sub_sized
16
+ @mini_sup_sized = mini_sup_sized if mini_sup_sized
17
+ @options = options unless options.empty?
10
18
  end
11
19
 
12
20
  def ==(object)
13
- object.respond_to?(:value) && object.value == value
21
+ object.respond_to?(:value) &&
22
+ object.value == value &&
23
+ object.slashed == slashed &&
24
+ object.mini_sub_sized == mini_sub_sized &&
25
+ object.mini_sup_sized == mini_sup_sized &&
26
+ object.options == options
14
27
  end
15
28
 
16
29
  def to_asciimath
@@ -60,6 +73,14 @@ module Plurimath
60
73
  value
61
74
  end
62
75
 
76
+ def to_unicodemath
77
+ return "\\#{value}" if slashed || special_chars
78
+ return mini_sub if mini_sub_sized
79
+ return mini_sup if mini_sup_sized
80
+
81
+ value
82
+ end
83
+
63
84
  def insert_t_tag(_)
64
85
  [(Utility.ox_element("r", namespace: "m") << t_tag)]
65
86
  end
@@ -104,6 +125,25 @@ module Plurimath
104
125
  value == "\\\\"
105
126
  end
106
127
 
128
+ def is_nary_symbol?
129
+ %w[
130
+ &#x222c;
131
+ &#x222d;
132
+ &#x222f;
133
+ &#x2230;
134
+ &#x2232;
135
+ &#x2233;
136
+ &#x2231;
137
+ &#x2229;
138
+ &#x222a;
139
+ &#x2210;
140
+ ].include?(value)
141
+ end
142
+
143
+ def mini_sized?
144
+ mini_sub_sized || mini_sup_sized
145
+ end
146
+
107
147
  private
108
148
 
109
149
  def operator?(unicode)
@@ -114,6 +154,7 @@ module Plurimath
114
154
 
115
155
  def explicit_checks(unicode)
116
156
  return true if [unicode, value].any? { |v| ["∣", "|"].include?(v) }
157
+ return true if unicode_const(:ACCENT_SYMBOLS).has_value?(value)
117
158
  end
118
159
 
119
160
  def specific_values
@@ -123,6 +164,30 @@ module Plurimath
123
164
 
124
165
  return "\\operatorname{if}" if value == "if"
125
166
  end
167
+
168
+ def mini_sub
169
+ unicode_const(:SUB_ALPHABETS)[value.to_sym] ||
170
+ unicode_const(:SUB_OPERATORS)[value.to_sym] ||
171
+ mini_sized_parenthesis(unicode_const(:SUB_PARENTHESIS))
172
+ end
173
+
174
+ def mini_sup
175
+ unicode_const(:SUP_ALPHABETS)[value.to_sym] ||
176
+ unicode_const(:SUP_OPERATORS)[value.to_sym] ||
177
+ mini_sized_parenthesis(unicode_const(:SUP_PARENTHESIS))
178
+ end
179
+
180
+ def unicode_const(const)
181
+ UnicodeMath::Constants.const_get(const)
182
+ end
183
+
184
+ def mini_sized_parenthesis(parens)
185
+ parens.values.find { |paren| paren.dig(value.to_sym) }&.dig(value.to_sym)
186
+ end
187
+
188
+ def special_chars
189
+ %w[& @ ^].include?(value)
190
+ end
126
191
  end
127
192
  end
128
193
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "unicode"
4
3
  require_relative "asciimath"
5
4
  require_relative "omml"
5
+ require_relative "unicode_math"
6
6
  require_relative "mathml"
7
7
  require_relative "html"
8
8
  require_relative "latex"
@@ -14,6 +14,7 @@ require_relative "math/unicode"
14
14
  require_relative "math/formula"
15
15
  require_relative "math/function"
16
16
  require_relative "asciimath/parser"
17
+ require_relative "unicode_math/parser"
17
18
  require_relative "mathml/parser"
18
19
  require_relative "latex/parser"
19
20
  require_relative "html/parser"
@@ -32,7 +33,7 @@ module Plurimath
32
33
  latex: Latex,
33
34
  mathml: Mathml,
34
35
  unitsml: Unitsml,
35
- unicode: Unicode,
36
+ unicode: UnicodeMath,
36
37
  asciimath: Asciimath,
37
38
  }.freeze
38
39
 
@@ -372,6 +372,22 @@ module Plurimath
372
372
  "[",
373
373
  "]",
374
374
  ].freeze
375
+ SUPPORTED_FONT_STYLES = {
376
+ "sans-serif-bold-italic": Math::Function::FontStyle::SansSerifBoldItalic,
377
+ "sans-serif-italic": Math::Function::FontStyle::SansSerifItalic,
378
+ "bold-sans-serif": Math::Function::FontStyle::BoldSansSerif,
379
+ "double-struck": Math::Function::FontStyle::DoubleStruck,
380
+ "bold-fraktur": Math::Function::FontStyle::BoldFraktur,
381
+ "bold-italic": Math::Function::FontStyle::BoldItalic,
382
+ "bold-script": Math::Function::FontStyle::BoldScript,
383
+ "sans-serif": Math::Function::FontStyle::SansSerif,
384
+ monospace: Math::Function::FontStyle::Monospace,
385
+ fraktur: Math::Function::FontStyle::Fraktur,
386
+ normal: Math::Function::FontStyle::Normal,
387
+ script: Math::Function::FontStyle::Script,
388
+ italic: Math::Function::FontStyle::Italic,
389
+ bold: Math::Function::FontStyle::Bold,
390
+ }.freeze
375
391
  end
376
392
  end
377
393
  end
@@ -9,14 +9,26 @@ module Plurimath
9
9
 
10
10
  SUPPORTED_ATTRS = %w[
11
11
  linebreakstyle
12
+ linethickness
12
13
  columnlines
13
14
  mathvariant
14
15
  accentunder
16
+ separators
15
17
  linebreak
16
18
  mathcolor
17
19
  notation
20
+ bevelled
21
+ rowlines
18
22
  accent
23
+ height
24
+ frame
25
+ depth
26
+ height
27
+ width
28
+ index
19
29
  close
30
+ alt
31
+ src
20
32
  open
21
33
  ].freeze
22
34
 
@@ -27,13 +39,15 @@ module Plurimath
27
39
  def parse
28
40
  ox_nodes = Plurimath.xml_engine.load(text)
29
41
  display_style = ox_nodes&.locate("mstyle/@displaystyle")&.first
30
- nodes = parse_nodes(ox_nodes.nodes)
42
+ nodes = parse_nodes(Array(ox_nodes))
31
43
  Math::Formula.new(
32
44
  Transform.new.apply(nodes).flatten.compact,
33
45
  display_style: (display_style || true),
34
46
  )
35
47
  end
36
48
 
49
+ protected
50
+
37
51
  def parse_nodes(nodes)
38
52
  nodes.map do |node|
39
53
  next if Plurimath.xml_engine.is_xml_comment?(node)
@@ -43,7 +57,7 @@ module Plurimath
43
57
  elsif !node.attributes.empty?
44
58
  attrs_hash(node)
45
59
  else
46
- { node.name.to_sym => parse_nodes(node.nodes) }
60
+ manage_tags(node)
47
61
  end
48
62
  end
49
63
  end
@@ -61,6 +75,32 @@ module Plurimath
61
75
  },
62
76
  }
63
77
  end
78
+
79
+ def manage_tags(node)
80
+ if node.name == "ms"
81
+ Plurimath::xml_engine.replace_nodes(
82
+ node,
83
+ ms_tag(comment_remove(node.nodes)).join(" "),
84
+ )
85
+ end
86
+ { node.name.to_sym => parse_nodes(node.nodes) }
87
+ end
88
+
89
+ def ms_tag(nodes)
90
+ return nodes if nodes.any?(String)
91
+
92
+ nodes.map do |node|
93
+ if node.nodes.any?(String)
94
+ node.nodes
95
+ else
96
+ ms_tag(node.nodes)
97
+ end
98
+ end
99
+ end
100
+
101
+ def comment_remove(nodes)
102
+ nodes.delete_if { |node| node.is_a?(Ox::Comment) }
103
+ end
64
104
  end
65
105
  end
66
106
  end
@@ -8,34 +8,28 @@ module Plurimath
8
8
  rule(mo: sequence(:mo)) { Utility.mathml_unary_classes(mo) }
9
9
  rule(mtd: sequence(:mtd)) { Math::Function::Td.new(mtd) }
10
10
  rule(mtr: sequence(:mtr)) { Math::Function::Tr.new(mtr) }
11
+ rule(math: subtree(:math)) { math.flatten.compact }
12
+ rule(mfrac: simple(:mfrac)) { mfrac }
11
13
  rule(none: sequence(:none)) { nil }
12
- rule(mspace: simple(:space)) { nil }
13
- rule(notation: simple(:att)) { Math::Function::Menclose.new(att) }
14
+ rule(mspace: simple(:space)) { space.is_a?(Math::Function::Mpadded) ? nil : space }
14
15
  rule(mtable: simple(:table)) { table }
15
- rule(msqrt: sequence(:sqrt)) { Math::Function::Sqrt.new(sqrt.first) }
16
+ rule(mglyph: simple(:glyph)) { glyph }
16
17
  rule(mstyle: simple(:mstyle)) { mstyle }
17
18
  rule(msline: sequence(:line)) { Math::Function::Msline.new }
18
19
  rule(value: sequence(:value)) { Utility.filter_values(value) }
19
20
 
21
+ rule(mpadded: simple(:padded)) { padded }
20
22
  rule(mspace: sequence(:space)) { nil }
21
- rule(mstyle: sequence(:mstyle)) { Utility.filter_values(mstyle) }
22
23
  rule(mfenced: simple(:mfenced)) { mfenced }
23
24
  rule(mtable: sequence(:mtable)) { Math::Function::Table.new(mtable) }
24
25
  rule(mscarry: sequence(:scarry)) { nil }
25
26
  rule(menclose: simple(:enclose)) { enclose }
26
27
  rule(mlabeledtr: sequence(:mtr)) { Math::Function::Tr.new(mtr) }
27
- rule(mpadded: sequence(:padded)) { Utility.filter_values(padded) }
28
28
  rule(malignmark: sequence(:mark)) { nil }
29
29
  rule(maligngroup: sequence(:att)) { nil }
30
30
  rule(mprescripts: sequence(:att)) { "mprescripts" }
31
31
  rule(columnlines: simple(:lines)) { lines }
32
32
 
33
- rule(math: subtree(:math)) do
34
- Utility.filter_values(
35
- math.flatten.compact,
36
- )
37
- end
38
-
39
33
  rule(mphantom: sequence(:phantom)) do
40
34
  Math::Function::Phantom.new(
41
35
  Utility.filter_values(phantom),
@@ -75,9 +69,10 @@ module Plurimath
75
69
  Math::Function::Longdiv.new(long.flatten.compact)
76
70
  end
77
71
 
78
- rule(menclose: sequence(:close)) do
72
+ rule(menclose: subtree(:close)) do
73
+ options = close.find { |obj| obj.is_a?(Hash) and close.delete(obj) }
79
74
  Math::Function::Menclose.new(
80
- nil,
75
+ (options[:notation] if options),
81
76
  Utility.filter_values(close),
82
77
  )
83
78
  end
@@ -95,6 +90,15 @@ module Plurimath
95
90
  )
96
91
  end
97
92
 
93
+ rule(msqrt: subtree(:sqrt)) do
94
+ options = sqrt.find { |sqr| sqr.is_a?(Hash) and sqrt.delete(sqr) }
95
+ sqrt_obj = Math::Function::Sqrt.new(
96
+ Utility.filter_values(sqrt),
97
+ )
98
+ sqrt_obj.options = options
99
+ sqrt_obj
100
+ end
101
+
98
102
  rule(mfrac: sequence(:mfrac)) do
99
103
  Math::Function::Frac.new(
100
104
  mfrac[0],
@@ -184,6 +188,20 @@ module Plurimath
184
188
  Utility.fenceable_classes(flatten_mrow)
185
189
  if flatten_mrow.length == 1
186
190
  flatten_mrow.first
191
+ elsif flatten_mrow&.first&.is_nary_function? && flatten_mrow.length == 2
192
+ nary_function = flatten_mrow.first
193
+ if nary_function.is_ternary_function? && nary_function.all_values_exist?
194
+ flatten_mrow[0] = nary_function.new_nary_function(flatten_mrow.delete_at(1))
195
+ flatten_mrow
196
+ elsif nary_function.is_binary_function? && nary_function.any_value_exist?
197
+ flatten_mrow[0] = nary_function.new_nary_function(flatten_mrow.delete_at(1))
198
+ flatten_mrow
199
+ else
200
+ Math::Formula.new(
201
+ flatten_mrow,
202
+ Utility.mrow_left_right(flatten_mrow),
203
+ )
204
+ end
187
205
  else
188
206
  Math::Formula.new(
189
207
  flatten_mrow,
@@ -192,6 +210,18 @@ module Plurimath
192
210
  end
193
211
  end
194
212
 
213
+ rule(mstyle: sequence(:mstyle)) do
214
+ nary_function = mstyle.first
215
+ if nary_function&.is_nary_function?
216
+ if nary_function.is_ternary_function? && nary_function.parameter_three.nil?
217
+ nary_function.parameter_three = mstyle.delete_at(1)
218
+ elsif nary_function.is_binary_function?
219
+ mstyle[0] = nary_function.new_nary_function(mstyle.delete_at(1))
220
+ end
221
+ end
222
+ Utility.filter_values(mstyle)
223
+ end
224
+
195
225
  rule(msrow: sequence(:msrow)) do
196
226
  Math::Formula.new(msrow.flatten.compact)
197
227
  end
@@ -210,10 +240,7 @@ module Plurimath
210
240
  mover.last.parameter_one = mover.shift if mover.length > 1
211
241
  mover.last
212
242
  else
213
- Math::Function::Overset.new(
214
- mover[1],
215
- mover[0],
216
- )
243
+ Math::Function::Overset.new(mover[1], mover[0])
217
244
  end
218
245
  end
219
246
 
@@ -230,6 +257,9 @@ module Plurimath
230
257
  elsif ["ubrace", "obrace", "underline"].any?(munder.last.class_name)
231
258
  munder.last.parameter_one = munder.shift if munder.length > 1
232
259
  munder.last
260
+ elsif Constants::CLASSES.include?(munder.first.class_name)
261
+ munder.first.parameter_one = munder.delete_at(1)
262
+ munder.first
233
263
  else
234
264
  Math::Function::Underset.new(
235
265
  munder[1],
@@ -244,6 +274,12 @@ module Plurimath
244
274
  )
245
275
  end
246
276
 
277
+ rule(mpadded: sequence(:padded)) do
278
+ Math::Function::Mpadded.new(
279
+ Utility.filter_values(padded),
280
+ )
281
+ end
282
+
247
283
  rule(mtext: subtree(:mtext)) do
248
284
  entities = HTMLEntities.new
249
285
  symbols = Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
@@ -255,13 +291,9 @@ module Plurimath
255
291
  end
256
292
 
257
293
  rule(ms: sequence(:ms)) do
258
- entities = HTMLEntities.new
259
- symbols = Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
260
- text = entities.encode(ms.first, :hexadecimal)
261
- symbols.each do |code, string|
262
- text = text.gsub(code.downcase, "unicode[:#{string}]")
263
- end
264
- Math::Function::Text.new(text)
294
+ Math::Function::Ms.new(
295
+ ms.flatten.compact.join(" "),
296
+ )
265
297
  end
266
298
 
267
299
  rule(mfenced: sequence(:fenced)) do
@@ -273,7 +305,7 @@ module Plurimath
273
305
  end
274
306
 
275
307
  rule(mmultiscripts: subtree(:script)) do
276
- multi = Utility.multiscript(script.compact)
308
+ multi = Utility.multiscript(script)
277
309
  prescripts = multi[1]
278
310
  Math::Function::Multiscript.new(
279
311
  multi[0],
@@ -334,11 +366,30 @@ module Plurimath
334
366
  rule(attributes: subtree(:attrs),
335
367
  value: sequence(:value)) do
336
368
  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
369
+ supported_attrs = %w[
370
+ linethickness
371
+ accentunder
372
+ columnlines
373
+ separators
374
+ rowlines
375
+ bevelled
376
+ notation
377
+ height
378
+ accent
379
+ height
380
+ width
381
+ index
382
+ depth
383
+ width
384
+ frame
385
+ alt
386
+ src
387
+ ]
388
+ attrs if attrs.keys.any? do |k|
389
+ supported_attrs.include?(k.to_s)
341
390
  end
391
+ unicode_only = true if attrs.key?(:linebreak)
392
+ attrs
342
393
  else
343
394
  attrs
344
395
  end
@@ -8,6 +8,7 @@ module Plurimath
8
8
 
9
9
  CUSTOMIZABLE_TAGS = %w[
10
10
  eqArr
11
+ sPre
11
12
  mr
12
13
  r
13
14
  ].freeze
@@ -67,6 +68,8 @@ module Plurimath
67
68
  organize_fonts(node)
68
69
  when "mr", "eqArr"
69
70
  organize_table_td(node)
71
+ when "sPre"
72
+ organize_spre(node)
70
73
  end
71
74
  end
72
75
 
@@ -83,6 +86,11 @@ module Plurimath
83
86
  end
84
87
  node.attributes.merge! attrs_arr
85
88
  end
89
+
90
+ def organize_spre(node)
91
+ node.locate("sub").first.name = "sPreSub"
92
+ node.locate("sup").first.name = "sPreSup"
93
+ end
86
94
  end
87
95
  end
88
96
  end