plurimath 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/Latex-Supported-Data.adoc +1 -0
  4. data/lib/plurimath/asciimath/parse.rb +1 -1
  5. data/lib/plurimath/asciimath/transform.rb +2 -6
  6. data/lib/plurimath/latex/constants.rb +2 -0
  7. data/lib/plurimath/math/core.rb +38 -6
  8. data/lib/plurimath/math/formula.rb +60 -6
  9. data/lib/plurimath/math/function/abs.rb +4 -0
  10. data/lib/plurimath/math/function/arg.rb +22 -0
  11. data/lib/plurimath/math/function/bar.rb +4 -0
  12. data/lib/plurimath/math/function/base.rb +49 -0
  13. data/lib/plurimath/math/function/binary_function.rb +6 -0
  14. data/lib/plurimath/math/function/cancel.rb +5 -0
  15. data/lib/plurimath/math/function/ceil.rb +6 -0
  16. data/lib/plurimath/math/function/color.rb +20 -1
  17. data/lib/plurimath/math/function/ddot.rb +4 -0
  18. data/lib/plurimath/math/function/dot.rb +5 -0
  19. data/lib/plurimath/math/function/fenced.rb +98 -7
  20. data/lib/plurimath/math/function/floor.rb +6 -0
  21. data/lib/plurimath/math/function/font_style/monospace.rb +4 -0
  22. data/lib/plurimath/math/function/font_style.rb +31 -6
  23. data/lib/plurimath/math/function/frac.rb +69 -15
  24. data/lib/plurimath/math/function/hat.rb +4 -0
  25. data/lib/plurimath/math/function/inf.rb +30 -0
  26. data/lib/plurimath/math/function/int.rb +47 -1
  27. data/lib/plurimath/math/function/intent.rb +22 -0
  28. data/lib/plurimath/math/function/left.rb +4 -0
  29. data/lib/plurimath/math/function/lim.rb +6 -0
  30. data/lib/plurimath/math/function/limits.rb +28 -0
  31. data/lib/plurimath/math/function/linebreak.rb +5 -0
  32. data/lib/plurimath/math/function/log.rb +27 -20
  33. data/lib/plurimath/math/function/longdiv.rb +4 -0
  34. data/lib/plurimath/math/function/mbox.rb +4 -0
  35. data/lib/plurimath/math/function/menclose.rb +74 -5
  36. data/lib/plurimath/math/function/merror.rb +2 -0
  37. data/lib/plurimath/math/function/mglyph.rb +64 -0
  38. data/lib/plurimath/math/function/mlabeledtr.rb +29 -0
  39. data/lib/plurimath/math/function/mod.rb +4 -0
  40. data/lib/plurimath/math/function/mpadded.rb +84 -0
  41. data/lib/plurimath/math/function/ms.rb +33 -0
  42. data/lib/plurimath/math/function/msgroup.rb +4 -0
  43. data/lib/plurimath/math/function/msline.rb +2 -4
  44. data/lib/plurimath/math/function/multiscript.rb +70 -6
  45. data/lib/plurimath/math/function/nary.rb +69 -10
  46. data/lib/plurimath/math/function/none.rb +25 -0
  47. data/lib/plurimath/math/function/norm.rb +6 -0
  48. data/lib/plurimath/math/function/obrace.rb +4 -0
  49. data/lib/plurimath/math/function/oint.rb +25 -1
  50. data/lib/plurimath/math/function/over.rb +6 -0
  51. data/lib/plurimath/math/function/overset.rb +46 -1
  52. data/lib/plurimath/math/function/phantom.rb +18 -2
  53. data/lib/plurimath/math/function/power.rb +37 -0
  54. data/lib/plurimath/math/function/power_base.rb +45 -18
  55. data/lib/plurimath/math/function/prod.rb +46 -0
  56. data/lib/plurimath/math/function/right.rb +4 -0
  57. data/lib/plurimath/math/function/root.rb +9 -1
  58. data/lib/plurimath/math/function/rule.rb +4 -0
  59. data/lib/plurimath/math/function/sqrt.rb +7 -1
  60. data/lib/plurimath/math/function/stackrel.rb +6 -0
  61. data/lib/plurimath/math/function/substack.rb +4 -0
  62. data/lib/plurimath/math/function/sum.rb +45 -24
  63. data/lib/plurimath/math/function/table/bmatrix.rb +18 -5
  64. data/lib/plurimath/math/function/table/cases.rb +24 -0
  65. data/lib/plurimath/math/function/table/eqarray.rb +24 -0
  66. data/lib/plurimath/math/function/table/matrix.rb +23 -3
  67. data/lib/plurimath/math/function/table/pmatrix.rb +4 -0
  68. data/lib/plurimath/math/function/table/vmatrix.rb +10 -0
  69. data/lib/plurimath/math/function/table.rb +58 -7
  70. data/lib/plurimath/math/function/td.rb +9 -0
  71. data/lib/plurimath/math/function/ternary_function.rb +14 -1
  72. data/lib/plurimath/math/function/text.rb +6 -0
  73. data/lib/plurimath/math/function/tilde.rb +4 -0
  74. data/lib/plurimath/math/function/tr.rb +9 -0
  75. data/lib/plurimath/math/function/ubrace.rb +5 -0
  76. data/lib/plurimath/math/function/ul.rb +4 -0
  77. data/lib/plurimath/math/function/unary_function.rb +4 -0
  78. data/lib/plurimath/math/function/underover.rb +14 -0
  79. data/lib/plurimath/math/function/underset.rb +49 -1
  80. data/lib/plurimath/math/function/vec.rb +4 -0
  81. data/lib/plurimath/math/number.rb +33 -3
  82. data/lib/plurimath/math/symbol.rb +68 -3
  83. data/lib/plurimath/math.rb +3 -2
  84. data/lib/plurimath/mathml/constants.rb +16 -0
  85. data/lib/plurimath/mathml/parser.rb +42 -2
  86. data/lib/plurimath/mathml/transform.rb +80 -29
  87. data/lib/plurimath/omml/parser.rb +8 -0
  88. data/lib/plurimath/omml/transform.rb +29 -26
  89. data/lib/plurimath/unicode_math/constants.rb +1015 -0
  90. data/lib/plurimath/unicode_math/parse.rb +233 -0
  91. data/lib/plurimath/unicode_math/parser.rb +58 -0
  92. data/lib/plurimath/unicode_math/parsing_rules/absence_rules.rb +138 -0
  93. data/lib/plurimath/unicode_math/parsing_rules/common_rules.rb +114 -0
  94. data/lib/plurimath/unicode_math/parsing_rules/constants_rules.rb +102 -0
  95. data/lib/plurimath/unicode_math/parsing_rules/helper.rb +19 -0
  96. data/lib/plurimath/unicode_math/parsing_rules/masked.rb +62 -0
  97. data/lib/plurimath/unicode_math/parsing_rules/sub_sup.rb +254 -0
  98. data/lib/plurimath/unicode_math/transform.rb +3831 -0
  99. data/lib/plurimath/{unicode.rb → unicode_math.rb} +2 -2
  100. data/lib/plurimath/unitsml.rb +14 -1
  101. data/lib/plurimath/utility.rb +346 -11
  102. data/lib/plurimath/version.rb +1 -1
  103. data/lib/plurimath/xml_engine/oga.rb +5 -0
  104. data/lib/plurimath/xml_engine/ox.rb +5 -0
  105. metadata +23 -3
@@ -46,8 +46,8 @@ module Plurimath
46
46
  return norm_table(table_tag) if open_paren == "norm["
47
47
 
48
48
  if present?(open_paren) || present?(close_paren)
49
- first_paren = Utility.ox_element("mo") << mathml_parenthesis(open_paren)
50
- second_paren = Utility.ox_element("mo") << mathml_parenthesis(close_paren)
49
+ first_paren = mo_element(mathml_parenthesis(open_paren))
50
+ second_paren = mo_element(mathml_parenthesis(close_paren))
51
51
  mrow_tag = Utility.ox_element("mrow")
52
52
  return Utility.update_nodes(mrow_tag, [first_paren, table_tag, second_paren])
53
53
  end
@@ -72,7 +72,7 @@ module Plurimath
72
72
  end
73
73
 
74
74
  def to_omml_without_math_tag(display_style)
75
- ox_table = if value.map { |d| d.parameter_one.length == 1 }.all?
75
+ ox_table = if single_table?
76
76
  single_td_table(display_style)
77
77
  else
78
78
  multiple_td_table(display_style)
@@ -80,6 +80,14 @@ module Plurimath
80
80
  fenced_table(ox_table)
81
81
  end
82
82
 
83
+ def to_unicodemath
84
+ if unicodemath_table_class?
85
+ "#{unicodemath_class_name}(#{value.map(&:to_unicodemath).join("@")})"
86
+ else
87
+ "#{open_paren}■(#{value.map(&:to_unicodemath).join("@")})#{close_paren}"
88
+ end
89
+ end
90
+
83
91
  def to_asciimath_math_zone(spacing, last = false, indent = true)
84
92
  [
85
93
  "#{spacing}\"table\" function apply\n",
@@ -115,7 +123,7 @@ module Plurimath
115
123
  end
116
124
 
117
125
  def mathml_parenthesis(field)
118
- return "" if field&.include?(":")
126
+ return "" if field&.include?(":") || validate_paren(field)
119
127
 
120
128
  present?(field) ? field : ""
121
129
  end
@@ -235,13 +243,12 @@ module Plurimath
235
243
  end
236
244
 
237
245
  def norm_table(table_tag)
238
- mo_tag = Utility.ox_element("mo") << "&#x2225;"
239
246
  Utility.update_nodes(
240
247
  Utility.ox_element("mrow"),
241
248
  [
242
- mo_tag,
249
+ mo_element("&#x2016;"),
243
250
  table_tag,
244
- mo_tag,
251
+ mo_element("&#x2016;"),
245
252
  ],
246
253
  )
247
254
  end
@@ -284,6 +291,50 @@ module Plurimath
284
291
  def parentheless_table
285
292
  "{:#{value.map(&:to_asciimath).join(", ")}:}"
286
293
  end
294
+
295
+ def single_table?
296
+ value.map { |d| d.parameter_one.length == 1 }.all? &&
297
+ nil_option?(:frame) &&
298
+ nil_option?(:columnlines) &&
299
+ nil_option?(:rowlines)
300
+ end
301
+
302
+ def nil_option?(option)
303
+ options[option].nil? ||
304
+ options[option] == "" ||
305
+ options[option] == "none"
306
+ end
307
+
308
+ def validate_paren(paren)
309
+ ["&#x3016;", "&#x3017;"].include?(paren)
310
+ end
311
+
312
+ def mo_element(value)
313
+ Utility.ox_element("mo") << value
314
+ end
315
+
316
+ def unicodemath_table_class?
317
+ return unless class_name == "table"
318
+ return if open_paren.nil? && close_paren.nil?
319
+
320
+ (!(open_paren.nil? || open_paren.empty?) && !(close_paren.nil? || close_paren.empty?)) ||
321
+ Utility::PARENTHESIS[open_paren&.to_sym] == close_paren ||
322
+ (open_paren.include?("|") && close_paren.include?("|"))
323
+ end
324
+
325
+ def unicodemath_class_name
326
+ return matrices_functions(:Vmatrix) if class_name == "vmatrix" && open_paren == "norm["
327
+ return matrices_functions(:vmatrix) if open_paren == "|" && close_paren == "|"
328
+ return matrices_functions(:matrix) if class_name == "Bmatrix" && open_paren == "{"
329
+ return unless unicodemath_table_class?
330
+
331
+ matrix_name = UnicodeMath::Constants::PARENTHESIS_MATRICES.key(open_paren)
332
+ matrices_functions(matrix_name)
333
+ end
334
+
335
+ def matrices_functions(matrix_name)
336
+ UnicodeMath::Constants::MATRIXS[matrix_name]
337
+ end
287
338
  end
288
339
  end
289
340
  end
@@ -6,6 +6,11 @@ module Plurimath
6
6
  module Math
7
7
  module Function
8
8
  class Td < BinaryFunction
9
+ def initialize(parameter_one = nil, parameter_two = nil)
10
+ parameter_one&.delete_if { |td| td == "&" }
11
+ super(parameter_one, parameter_two)
12
+ end
13
+
9
14
  def to_asciimath
10
15
  parameter_one.map(&:to_asciimath).join(" ")
11
16
  end
@@ -40,6 +45,10 @@ module Plurimath
40
45
  [me]
41
46
  end
42
47
 
48
+ def to_unicodemath
49
+ parameter_one&.map(&:to_unicodemath)&.join
50
+ end
51
+
43
52
  def to_asciimath_math_zone(spacing, last = false, _)
44
53
  [
45
54
  "#{spacing}\"td\" function apply\n",
@@ -125,7 +125,7 @@ module Plurimath
125
125
 
126
126
  def ascii_wrap(field)
127
127
  asciimath = field.to_asciimath
128
- return latex if ["obrace", "ubrace"].include?(field.class_name)
128
+ return asciimath if ["obrace", "ubrace"].include?(field.class_name)
129
129
 
130
130
  case field
131
131
  when Formula || field.class.name.include?("Function")
@@ -180,6 +180,19 @@ module Plurimath
180
180
 
181
181
  Underset.new(overset, parameter_two)&.to_omml_without_math_tag(display_style)
182
182
  end
183
+
184
+ def naryand_value(field)
185
+ return "" unless field
186
+
187
+ field_value = field.to_unicodemath
188
+ field.is_a?(Math::Function::Fenced) ? "▒#{field_value}" : "▒〖#{field_value}〗"
189
+ end
190
+
191
+ def prime_unicode?(field)
192
+ return unless field.is_a?(Math::Symbol)
193
+
194
+ UnicodeMath::Constants::PREFIXED_PRIMES.any? { |prefix, prime| field.value.include?(prime) || field.value.include?("&#x27;") }
195
+ end
183
196
  end
184
197
  end
185
198
  end
@@ -35,6 +35,12 @@ module Plurimath
35
35
  [text]
36
36
  end
37
37
 
38
+ def to_unicodemath
39
+ return unless value
40
+
41
+ value&.start_with?("\\") ? value : "\"#{(Utility.html_entity_to_unicode(value))}\""
42
+ end
43
+
38
44
  def insert_t_tag(display_style)
39
45
  r_tag = Utility.ox_element("r", namespace: "m")
40
46
  Utility.update_nodes(r_tag, to_omml_without_math_tag(display_style))
@@ -36,6 +36,10 @@ module Plurimath
36
36
  false
37
37
  end
38
38
 
39
+ def to_unicodemath
40
+ "#{unicodemath_parens(parameter_one)}̃"
41
+ end
42
+
39
43
  def line_breaking(obj)
40
44
  parameter_one&.line_breaking(obj)
41
45
  obj.update(Utility.filter_values(obj.value)) if obj.value_exist?
@@ -6,6 +6,11 @@ module Plurimath
6
6
  module Math
7
7
  module Function
8
8
  class Tr < UnaryFunction
9
+ def initialize(parameter_one = [])
10
+ parameter_one.map!.with_index { |_, index| Td.new([]) } if parameter_one&.all?("@")
11
+ super(parameter_one)
12
+ end
13
+
9
14
  def to_asciimath
10
15
  "[#{parameter_one.map(&:to_asciimath).join(', ')}]"
11
16
  end
@@ -45,6 +50,10 @@ module Plurimath
45
50
  end
46
51
  end
47
52
 
53
+ def to_unicodemath
54
+ parameter_one&.map(&:to_unicodemath)&.join("&")
55
+ end
56
+
48
57
  def to_asciimath_math_zone(spacing, last = false, indent = true)
49
58
  [
50
59
  "#{spacing}\"tr\" function apply\n",
@@ -57,6 +57,11 @@ module Plurimath
57
57
  Underset.new(parameter_one, symbol).to_omml_without_math_tag(true)
58
58
  end
59
59
 
60
+ def to_unicodemath
61
+ first_value = "(#{parameter_one&.to_unicodemath})" if parameter_one
62
+ "⏟#{first_value}"
63
+ end
64
+
60
65
  def line_breaking(obj)
61
66
  parameter_one&.line_breaking(obj)
62
67
  obj.update(Utility.filter_values(obj.value)) if obj.value_exist?
@@ -49,6 +49,10 @@ module Plurimath
49
49
  end
50
50
  end
51
51
 
52
+ def to_unicodemath
53
+ "▁#{unicodemath_parens(parameter_one)}"
54
+ end
55
+
52
56
  def class_name
53
57
  "underline"
54
58
  end
@@ -64,6 +64,10 @@ module Plurimath
64
64
  Array(value)
65
65
  end
66
66
 
67
+ def to_unicodemath
68
+ "#{class_name}⁡#{parameter_one&.to_unicodemath}"
69
+ end
70
+
67
71
  def to_asciimath_math_zone(spacing, last = false, _)
68
72
  new_spacing = gsub_spacing(spacing, last)
69
73
  new_arr = [
@@ -47,6 +47,12 @@ module Plurimath
47
47
  underover(display_style)
48
48
  end
49
49
 
50
+ def to_unicodemath
51
+ sub_value = "┬#{unicodemath_parens(parameter_two)}" if parameter_two
52
+ sup_value = "┴#{unicodemath_parens(parameter_three)}" if parameter_three
53
+ "#{parameter_one&.to_unicodemath}#{sub_value}#{sup_value}"
54
+ end
55
+
50
56
  def line_breaking(obj)
51
57
  parameter_one&.line_breaking(obj)
52
58
  if obj.value_exist?
@@ -67,6 +73,14 @@ module Plurimath
67
73
  self.parameter_three = nil
68
74
  end
69
75
  end
76
+
77
+ def new_nary_function(fourth_value)
78
+ Nary.new(parameter_one, parameter_two, parameter_three, fourth_value, { type: "undOvr" })
79
+ end
80
+
81
+ def is_nary_function?
82
+ parameter_one.is_nary_function? || parameter_one.is_nary_symbol?
83
+ end
70
84
  end
71
85
  end
72
86
  end
@@ -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