plurimath 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/lib/plurimath/asciimath/parse.rb +3 -2
  4. data/lib/plurimath/asciimath/transform.rb +32 -5
  5. data/lib/plurimath/latex/constants.rb +2 -1
  6. data/lib/plurimath/latex/transform.rb +9 -13
  7. data/lib/plurimath/math/core.rb +134 -20
  8. data/lib/plurimath/math/formula.rb +88 -18
  9. data/lib/plurimath/math/function/abs.rb +28 -15
  10. data/lib/plurimath/math/function/bar.rb +5 -0
  11. data/lib/plurimath/math/function/base.rb +14 -0
  12. data/lib/plurimath/math/function/binary_function.rb +2 -8
  13. data/lib/plurimath/math/function/ceil.rb +24 -9
  14. data/lib/plurimath/math/function/ddot.rb +6 -1
  15. data/lib/plurimath/math/function/deg.rb +4 -1
  16. data/lib/plurimath/math/function/det.rb +4 -1
  17. data/lib/plurimath/math/function/dim.rb +4 -1
  18. data/lib/plurimath/math/function/dot.rb +5 -0
  19. data/lib/plurimath/math/function/exp.rb +4 -1
  20. data/lib/plurimath/math/function/fenced.rb +25 -16
  21. data/lib/plurimath/math/function/floor.rb +23 -13
  22. data/lib/plurimath/math/function/font_style.rb +18 -8
  23. data/lib/plurimath/math/function/frac.rb +32 -18
  24. data/lib/plurimath/math/function/gcd.rb +4 -1
  25. data/lib/plurimath/math/function/glb.rb +8 -1
  26. data/lib/plurimath/math/function/hat.rb +16 -5
  27. data/lib/plurimath/math/function/hom.rb +4 -1
  28. data/lib/plurimath/math/function/inf.rb +16 -0
  29. data/lib/plurimath/math/function/int.rb +28 -9
  30. data/lib/plurimath/math/function/ker.rb +4 -1
  31. data/lib/plurimath/math/function/lcm.rb +17 -1
  32. data/lib/plurimath/math/function/left.rb +1 -1
  33. data/lib/plurimath/math/function/lg.rb +4 -1
  34. data/lib/plurimath/math/function/lim.rb +10 -0
  35. data/lib/plurimath/math/function/liminf.rb +4 -1
  36. data/lib/plurimath/math/function/limits.rb +22 -9
  37. data/lib/plurimath/math/function/limsup.rb +4 -1
  38. data/lib/plurimath/math/function/linebreak.rb +95 -0
  39. data/lib/plurimath/math/function/ln.rb +4 -1
  40. data/lib/plurimath/math/function/log.rb +21 -12
  41. data/lib/plurimath/math/function/longdiv.rb +19 -0
  42. data/lib/plurimath/math/function/lub.rb +4 -1
  43. data/lib/plurimath/math/function/max.rb +4 -1
  44. data/lib/plurimath/math/function/mbox.rb +8 -7
  45. data/lib/plurimath/math/function/merror.rb +12 -3
  46. data/lib/plurimath/math/function/min.rb +4 -1
  47. data/lib/plurimath/math/function/mod.rb +42 -15
  48. data/lib/plurimath/math/function/msgroup.rb +4 -0
  49. data/lib/plurimath/math/function/msline.rb +10 -0
  50. data/lib/plurimath/math/function/multiscript.rb +20 -0
  51. data/lib/plurimath/math/function/nary.rb +39 -5
  52. data/lib/plurimath/math/function/norm.rb +24 -15
  53. data/lib/plurimath/math/function/obrace.rb +5 -0
  54. data/lib/plurimath/math/function/oint.rb +42 -20
  55. data/lib/plurimath/math/function/over.rb +23 -10
  56. data/lib/plurimath/math/function/overset.rb +13 -10
  57. data/lib/plurimath/math/function/phantom.rb +24 -6
  58. data/lib/plurimath/math/function/power.rb +13 -4
  59. data/lib/plurimath/math/function/power_base.rb +28 -6
  60. data/lib/plurimath/math/function/prod.rb +33 -14
  61. data/lib/plurimath/math/function/right.rb +1 -1
  62. data/lib/plurimath/math/function/rule.rb +1 -1
  63. data/lib/plurimath/math/function/scarries.rb +14 -0
  64. data/lib/plurimath/math/function/semantics.rb +9 -0
  65. data/lib/plurimath/math/function/sqrt.rb +5 -0
  66. data/lib/plurimath/math/function/stackrel.rb +8 -0
  67. data/lib/plurimath/math/function/substack.rb +12 -51
  68. data/lib/plurimath/math/function/sum.rb +43 -20
  69. data/lib/plurimath/math/function/sup.rb +11 -2
  70. data/lib/plurimath/math/function/table/array.rb +1 -1
  71. data/lib/plurimath/math/function/table/matrix.rb +4 -0
  72. data/lib/plurimath/math/function/table.rb +10 -2
  73. data/lib/plurimath/math/function/td.rb +14 -4
  74. data/lib/plurimath/math/function/ternary_function.rb +8 -10
  75. data/lib/plurimath/math/function/text.rb +1 -1
  76. data/lib/plurimath/math/function/tilde.rb +5 -0
  77. data/lib/plurimath/math/function/tr.rb +1 -1
  78. data/lib/plurimath/math/function/ubrace.rb +5 -0
  79. data/lib/plurimath/math/function/unary_function.rb +72 -26
  80. data/lib/plurimath/math/function/underover.rb +25 -8
  81. data/lib/plurimath/math/function/underset.rb +19 -9
  82. data/lib/plurimath/math/function/vec.rb +5 -0
  83. data/lib/plurimath/math/number.rb +3 -3
  84. data/lib/plurimath/math/symbol.rb +13 -5
  85. data/lib/plurimath/mathml/parser.rb +2 -0
  86. data/lib/plurimath/mathml/transform.rb +23 -15
  87. data/lib/plurimath/omml/transform.rb +22 -10
  88. data/lib/plurimath/unitsml.rb +2 -1
  89. data/lib/plurimath/utility.rb +29 -28
  90. data/lib/plurimath/version.rb +1 -1
  91. metadata +3 -3
  92. data/lib/plurimath/math/function/scarry.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af2ed460bf37f3496c528c6cb170f2c555873332771086113f90a875312b467a
4
- data.tar.gz: d9311eaf4dfb84c188966346a38d273e544f035c573afb50898bd9f03f81c9fc
3
+ metadata.gz: f58b20082cd94488f247f22399522d777ea751a4eba4f21e45a7a792fc6d30f3
4
+ data.tar.gz: f6e55fa7493ac10ac6e8ded470ea547640b3b5b53f00ac36c8cf941d56d5cc87
5
5
  SHA512:
6
- metadata.gz: cffd311295a1f9e41d372c544909029da3f5798f5744e14e549dd1d7e220755971d5bec0a91cc3695fdef25f3d9b44de606da37876c615eee3cc3818eadbe6e9
7
- data.tar.gz: f4035ab63d7f2f3f0aef261f9491ed163a1ffec03d52011b7dda140d6ce4c303bd277a5d05487028b8c77c32585359a826d85fcfc46bb32220e4d1b103b54fb3
6
+ metadata.gz: 133860ffcca6250cb3bef1e9eb186536685b3697a7d26bcda1d287170d74b9ac98083d352143cc6a9fc3649832229c0e1c3c1963c3e787db4d8b6f992b3f5802
7
+ data.tar.gz: 3a2044197aa65f0820961c14a602ca6df69c316e48203b2d448263032837336053715d95c52290b5241486426d000588d632cd820563ddf6466b0f4ab5d46569
data/Gemfile CHANGED
@@ -11,3 +11,4 @@ gem 'equivalent-xml'
11
11
  gem 'opal-rspec', "~> 1.1.0a"
12
12
  gem 'oga'
13
13
  gem 'ox'
14
+ gem "unitsml"
@@ -69,7 +69,8 @@ module Plurimath
69
69
  end
70
70
 
71
71
  rule(:quoted_text) do
72
- (str('"') >> match("[^\"]").repeat.as(:text) >> str('"')) |
72
+ (str('"') >> str("unitsml(") >> match("[^\)\"]").repeat.as(:unitsml) >> str(')"')) |
73
+ (str('"') >> match("[^\"]").repeat.as(:text) >> str('"')) |
73
74
  (str('"') >> str("").as(:text))
74
75
  end
75
76
 
@@ -188,7 +189,7 @@ module Plurimath
188
189
  def dynamic_parser_rules(expr)
189
190
  first_value = str(expr.first.to_s)
190
191
  case expr.last
191
- when :symbol then first_value.as(:symbol)
192
+ when :symbol then (str("\\").as(:slash) >> match("\s").repeat >> str("\n")) | first_value.as(:symbol)
192
193
  when :unary_class then (first_value.as(:unary_class) >> space? >> sequence.maybe).as(:unary)
193
194
  when :fonts then first_value.as(:fonts_class) >> space? >> sequence.as(:fonts_value)
194
195
  when :special_fonts then first_value.as(:bold_fonts)
@@ -8,6 +8,7 @@ module Plurimath
8
8
  rule(unary: simple(:unary)) { unary }
9
9
  rule(table: simple(:table)) { table }
10
10
  rule(comma: simple(:comma)) { Utility.symbol_object(comma) }
11
+ rule(slash: simple(:slash)) { Math::Function::Linebreak.new }
11
12
  rule(unary: sequence(:unary)) { Utility.filter_values(unary) }
12
13
  rule(rparen: simple(:rparen)) { Utility.symbol_object(rparen) }
13
14
  rule(number: simple(:number)) { Math::Number.new(number) }
@@ -27,6 +28,12 @@ module Plurimath
27
28
  rule(power_value: sequence(:power_value)) { power_value }
28
29
  rule(mod: simple(:mod), expr: simple(:expr)) { [mod, expr] }
29
30
 
31
+ rule(unitsml: simple(:unitsml)) do
32
+ Utility.filter_values(
33
+ Unitsml.new(unitsml.to_s).to_formula.value,
34
+ )
35
+ end
36
+
30
37
  rule(bold_fonts: simple(:font)) do
31
38
  Math::Function::FontStyle::DoubleStruck.new(
32
39
  Utility.symbol_object(font.to_s[0]),
@@ -303,11 +310,15 @@ module Plurimath
303
310
  end
304
311
 
305
312
  rule(td: simple(:td)) do
306
- Math::Function::Td.new(
307
- [
308
- Utility.td_value(td),
309
- ],
310
- )
313
+ if td.is_a?(Math::Formula) && td.value.any?(Math::Function::Table)
314
+ Utility.td_values(td.value, ",")
315
+ else
316
+ Math::Function::Td.new(
317
+ [
318
+ Utility.td_value(td),
319
+ ],
320
+ )
321
+ end
311
322
  end
312
323
 
313
324
  rule(td: sequence(:td)) do
@@ -631,6 +642,13 @@ module Plurimath
631
642
  new_arr
632
643
  end
633
644
 
645
+ rule(sequence: sequence(:sequence),
646
+ left_right: simple(:left_right)) do
647
+ new_arr = sequence.flatten.compact
648
+ new_arr << left_right unless left_right.to_s.strip.empty?
649
+ new_arr
650
+ end
651
+
634
652
  rule(sequence: sequence(:sequence),
635
653
  expr: sequence(:expr)) do
636
654
  sequence.flatten.compact + expr.flatten.compact
@@ -860,6 +878,15 @@ module Plurimath
860
878
  )
861
879
  end
862
880
 
881
+ rule(unary_class: simple(:function),
882
+ unitsml: simple(:unitsml)) do
883
+ Utility.get_class(function).new(
884
+ Utility.filter_values(
885
+ Unitsml.new(unitsml.to_s).to_formula.value,
886
+ ),
887
+ )
888
+ end
889
+
863
890
  rule(number: simple(:number),
864
891
  comma: simple(:comma)) do
865
892
  [
@@ -2856,6 +2856,7 @@ module Plurimath
2856
2856
  overline: :unary,
2857
2857
  underset: :binary,
2858
2858
  overset: :binary,
2859
+ phantom: :unary,
2859
2860
  ddagger: :symbols,
2860
2861
  trprime: :symbols,
2861
2862
  closure: :symbols,
@@ -3562,7 +3563,7 @@ module Plurimath
3562
3563
  tanh: :unary,
3563
3564
  cosh: :unary,
3564
3565
  ddot: :unary,
3565
- mbox: :unary,
3566
+ mbox: :text,
3566
3567
  text: :text,
3567
3568
  '"': :symbols,
3568
3569
  sum: :ternary,
@@ -14,7 +14,7 @@ module Plurimath
14
14
  rule(lparen: simple(:lparen)) { Math::Symbol.new(lparen) }
15
15
  rule(rparen: simple(:rparen)) { Math::Symbol.new(rparen) }
16
16
  rule(limits: simple(:limits)) { limits }
17
- rule("\\\\" => simple(:slash)) { Math::Symbol.new(slash) }
17
+ rule("\\\\" => simple(:slash)) { Math::Function::Linebreak.new }
18
18
  rule(expression: simple(:expr)) { expr }
19
19
  rule(environment: simple(:env)) { env }
20
20
  rule(ternary: simple(:ternary)) { Utility.get_class(ternary).new }
@@ -488,19 +488,19 @@ module Plurimath
488
488
 
489
489
  rule(text: simple(:text),
490
490
  first_value: simple(:first_value)) do
491
- Math::Function::Text.new(first_value)
491
+ Utility.get_class(text).new(first_value)
492
492
  end
493
493
 
494
494
  rule(text: simple(:text),
495
495
  first_value: sequence(:first_value)) do
496
- Math::Function::Text.new(first_value.join)
496
+ Utility.get_class(text).new(first_value.join)
497
497
  end
498
498
 
499
499
  rule(text: simple(:text),
500
500
  first_value: simple(:first_value),
501
501
  supscript: simple(:supscript),) do
502
502
  Math::Function::Power.new(
503
- Math::Function::Text.new(first_value),
503
+ Utility.get_class(text).new(first_value),
504
504
  supscript,
505
505
  )
506
506
  end
@@ -509,7 +509,7 @@ module Plurimath
509
509
  first_value: sequence(:first_value),
510
510
  supscript: simple(:supscript),) do
511
511
  Math::Function::Power.new(
512
- Math::Function::Text.new(first_value.join),
512
+ Utility.get_class(text).new(first_value.join),
513
513
  supscript,
514
514
  )
515
515
  end
@@ -518,7 +518,7 @@ module Plurimath
518
518
  first_value: sequence(:first_value),
519
519
  subscript: simple(:subscript)) do
520
520
  Math::Function::Base.new(
521
- Math::Function::Text.new(first_value.join),
521
+ Utility.get_class(text).new(first_value.join),
522
522
  subscript,
523
523
  )
524
524
  end
@@ -527,7 +527,7 @@ module Plurimath
527
527
  first_value: simple(:first_value),
528
528
  subscript: simple(:subscript)) do
529
529
  Math::Function::Base.new(
530
- Math::Function::Text.new(first_value),
530
+ Utility.get_class(text).new(first_value),
531
531
  subscript,
532
532
  )
533
533
  end
@@ -537,7 +537,7 @@ module Plurimath
537
537
  subscript: simple(:subscript),
538
538
  supscript: simple(:supscript)) do
539
539
  Math::Function::PowerBase.new(
540
- Math::Function::Text.new(first_value),
540
+ Utility.get_class(text).new(first_value),
541
541
  subscript,
542
542
  supscript,
543
543
  )
@@ -948,12 +948,8 @@ module Plurimath
948
948
 
949
949
  rule(substack: simple(:substack),
950
950
  expression: sequence(:value)) do
951
- tds = Utility.td_values(value, "\\\\")
952
-
953
- substack_values = tds.map { |td| Math::Function::Tr.new([td]) }
954
951
  Math::Function::Substack.new(
955
- substack_values.shift,
956
- substack_values.shift,
952
+ Utility.organize_table(value),
957
953
  )
958
954
  end
959
955
  end
@@ -3,6 +3,11 @@
3
3
  module Plurimath
4
4
  module Math
5
5
  class Core
6
+ REPLACABLES = {
7
+ /&amp;/ => "&",
8
+ /^\n/ => "",
9
+ }
10
+
6
11
  def class_name
7
12
  self.class.name.split("::").last.downcase
8
13
  end
@@ -24,18 +29,18 @@ module Plurimath
24
29
  end
25
30
 
26
31
  def empty_tag(wrapper_tag)
27
- r_tag = Utility.ox_element("r", namespace: "m")
28
- r_tag << (Utility.ox_element("t", namespace: "m") << "&#8203;")
32
+ r_tag = ox_element("r", namespace: "m")
33
+ r_tag << (ox_element("t", namespace: "m") << "&#8203;")
29
34
  wrapper_tag << r_tag
30
35
  end
31
36
 
32
- def omml_parameter(field, display_style, tag_name: , namespace: "m")
33
- tag = Utility.ox_element(tag_name, namespace: namespace)
37
+ def omml_parameter(field, display_style, tag_name:, namespace: "m")
38
+ tag = ox_element(tag_name, namespace: namespace)
34
39
  return empty_tag(tag) unless field
35
40
 
36
41
  Utility.update_nodes(
37
42
  tag,
38
- field&.insert_t_tag(display_style),
43
+ field.insert_t_tag(display_style),
39
44
  )
40
45
  end
41
46
 
@@ -44,12 +49,13 @@ module Plurimath
44
49
  end
45
50
 
46
51
  def r_element(string, rpr_tag: true)
47
- r_tag = Utility.ox_element("r", namespace: "m")
52
+ r_tag = ox_element("r", namespace: "m")
48
53
  if rpr_tag
49
- sty_tag = Utility.ox_element("sty", namespace: "m", attributes: { "m:val": "p" })
50
- r_tag << (Utility.ox_element("rPr", namespace: "m") << sty_tag)
54
+ attrs = { "m:val": "p" }
55
+ sty_tag = ox_element("sty", namespace: "m", attributes: attrs)
56
+ r_tag << (ox_element("rPr", namespace: "m") << sty_tag)
51
57
  end
52
- r_tag << (Utility.ox_element("t", namespace: "m") << string)
58
+ r_tag << (ox_element("t", namespace: "m") << string)
53
59
  Array(r_tag)
54
60
  end
55
61
 
@@ -57,7 +63,7 @@ module Plurimath
57
63
  false
58
64
  end
59
65
 
60
- def extract_class_from_text
66
+ def extract_class_name_from_text
61
67
  ""
62
68
  end
63
69
 
@@ -107,16 +113,13 @@ module Plurimath
107
113
  end
108
114
 
109
115
  def dump_mathml(field)
110
- mathml = dump_ox_nodes(field.to_mathml_without_math_tag)
111
- mathml.gsub(/\n\s*/, "").gsub("&amp;", "&")
116
+ dump_ox_nodes(field.to_mathml_without_math_tag).gsub(/\n\s*/, "")
112
117
  end
113
118
 
114
119
  def dump_omml(field, display_style)
115
120
  return if field.nil?
116
121
 
117
- omml = field.omml_nodes(display_style)
118
- omml_string = omml.is_a?(Array) ? omml.flatten.map { |obj| dump_ox_nodes(obj) }.join : dump_ox_nodes(omml)
119
- omml_string.gsub(/\n\s*/, "").gsub("&amp;", "&")
122
+ dump_ox_nodes(field.omml_nodes(display_style)).gsub(/\n\s*/, "")
120
123
  end
121
124
 
122
125
  def omml_nodes(display_style)
@@ -124,16 +127,16 @@ module Plurimath
124
127
  end
125
128
 
126
129
  def validate_mathml_fields(field)
127
- field.nil? ? Utility.ox_element("mi") : field.to_mathml_without_math_tag
130
+ field.nil? ? ox_element("mi") : field.to_mathml_without_math_tag
128
131
  end
129
132
 
130
133
  def common_math_zone_conversion(field, options = {})
131
134
  {
132
135
  spacing: options[:spacing],
133
136
  last: options[:last] || true,
134
- indent: !field&.is_a?(Formula),
137
+ indent: !field.is_a?(Formula),
135
138
  function_spacing: "#{options[:spacing]}#{options[:additional_space]}",
136
- field_name: options[:field_name] ? " #{options[:field_name]}" : "",
139
+ field_name: (options[:field_name] ? " #{options[:field_name]}" : ""),
137
140
  }
138
141
  end
139
142
 
@@ -142,16 +145,127 @@ module Plurimath
142
145
  end
143
146
 
144
147
  def dump_ox_nodes(nodes)
145
- Plurimath.xml_engine.dump(nodes)
148
+ return dump_nodes(nodes) unless nodes.is_a?(Array)
149
+
150
+ nodes.flatten.map { |node| dump_nodes(node) }.join
151
+ end
152
+
153
+ def dump_nodes(nodes, indent: nil)
154
+ replacable_values(
155
+ Plurimath.xml_engine.dump(nodes, indent: indent),
156
+ )
157
+ end
158
+
159
+ def replacable_values(string)
160
+ REPLACABLES.each { |regex, str| string.gsub!(regex, str) }
161
+ string
146
162
  end
147
163
 
148
164
  def gsub_spacing(spacing, last)
149
- spacing.gsub(/\|\_/, last ? " " : "| ")
165
+ spacing.gsub(/\|_/, last ? " " : "| ")
150
166
  end
151
167
 
152
168
  def invert_unicode_symbols
153
169
  Mathml::Constants::UNICODE_SYMBOLS.invert[class_name] || class_name
154
170
  end
171
+
172
+ def separate_table
173
+ false
174
+ end
175
+
176
+ def linebreak
177
+ false
178
+ end
179
+
180
+ def cloned_objects
181
+ object = self.class.new rescue self.class.new(nil)
182
+ variables.each { |var| object.set(var, variable_value(get(var))) }
183
+ object
184
+ end
185
+
186
+ def variable_value(value)
187
+ case value
188
+ when Core
189
+ value.cloned_objects
190
+ when Array
191
+ value.map { |object| variable_value(object) }
192
+ else
193
+ value
194
+ end
195
+ end
196
+
197
+ def line_breaking(obj)
198
+ variables.each do |variable|
199
+ field = get(variable)
200
+ case field
201
+ when Core
202
+ field.line_breaking(obj)
203
+ updated_object_values(variable, obj: obj, update_value: true) if obj.value_exist?
204
+ when Array
205
+ if result(field).length > 1
206
+ updated_object_values(variable, obj: obj)
207
+ else
208
+ field.each { |object| object.line_breaking(obj) }
209
+ end
210
+ end
211
+ end
212
+ end
213
+
214
+ def updated_object_values(param, obj:, update_value: false)
215
+ object = self.class.new(nil)
216
+ found = false
217
+ variables.each do |variable|
218
+ value = if param == variable
219
+ found = true
220
+ if update_value
221
+ return_value = obj.value
222
+ obj.value = []
223
+ return_value
224
+ else
225
+ formula = Formula.new(get(variable))
226
+ formula.line_breaking(obj)
227
+ set(variable, obj)
228
+ get(variable)
229
+ end
230
+ else
231
+ return_value = get(variable)
232
+ set(variable, nil) if found
233
+ return_value
234
+ end
235
+ object.set(variable, Utility.filter_values(value))
236
+ end
237
+ object.hide_function_name = true if object.methods.include?(:hide_function_name)
238
+ obj.update(object)
239
+ end
240
+
241
+ def get(variable)
242
+ instance_variable_get(variable)
243
+ end
244
+
245
+ def set(variable, value)
246
+ instance_variable_set(variable, value)
247
+ end
248
+
249
+ def variables
250
+ instance_variables
251
+ end
252
+
253
+ def ox_element(node, attributes: [], namespace: "")
254
+ Utility.ox_element(
255
+ node,
256
+ attributes: attributes,
257
+ namespace: namespace,
258
+ )
259
+ end
260
+
261
+ def result(value = [])
262
+ value = get("@value") || value
263
+ value.slice_after { |d| d.is_a?(Math::Function::Linebreak) }.to_a
264
+ end
265
+
266
+ def is_unary?
267
+ is_a?(Math::Function::UnaryFunction)
268
+ end
155
269
  end
156
270
  end
157
271
  end
@@ -4,6 +4,7 @@ module Plurimath
4
4
  module Math
5
5
  class Formula < Core
6
6
  attr_accessor :value, :left_right_wrapper, :displaystyle, :input_string
7
+
7
8
  MATH_ZONE_TYPES = %i[
8
9
  omml
9
10
  latex
@@ -36,21 +37,29 @@ module Plurimath
36
37
  parse_error!(:asciimath)
37
38
  end
38
39
 
39
- def to_mathml(display_style: displaystyle)
40
+ def to_mathml(display_style: displaystyle, split_on_linebreak: false)
41
+ return line_breaked_mathml(display_style) if split_on_linebreak
42
+
40
43
  math_attrs = {
41
44
  xmlns: "http://www.w3.org/1998/Math/MathML",
42
45
  display: "block",
43
46
  }
44
47
  style_attrs = { displaystyle: boolean_display_style(display_style) }
45
- math = Utility.ox_element("math", attributes: math_attrs)
46
- style = Utility.ox_element("mstyle", attributes: style_attrs)
48
+ math = ox_element("math", attributes: math_attrs)
49
+ style = ox_element("mstyle", attributes: style_attrs)
47
50
  Utility.update_nodes(style, mathml_content)
48
51
  Utility.update_nodes(math, [style])
49
- Plurimath.xml_engine.dump(math, indent: 2).gsub("&amp;", "&")
52
+ dump_nodes(math, indent: 2)
50
53
  rescue
51
54
  parse_error!(:mathml)
52
55
  end
53
56
 
57
+ def line_breaked_mathml(display_style)
58
+ new_line_support.map do |formula|
59
+ formula.to_mathml(display_style: display_style)
60
+ end.join
61
+ end
62
+
54
63
  def to_mathml_without_math_tag
55
64
  return mathml_content unless left_right_wrapper
56
65
 
@@ -76,7 +85,7 @@ module Plurimath
76
85
  parse_error!(:html)
77
86
  end
78
87
 
79
- def omml_math_attrs
88
+ def omml_attrs
80
89
  {
81
90
  "xmlns:m": "http://schemas.openxmlformats.org/officeDocument/2006/math",
82
91
  "xmlns:mc": "http://schemas.openxmlformats.org/markup-compatibility/2006",
@@ -99,16 +108,20 @@ module Plurimath
99
108
  }
100
109
  end
101
110
 
102
- def to_omml(display_style: displaystyle)
103
- para_element = Utility.ox_element(
104
- "oMathPara",
105
- attributes: omml_math_attrs,
106
- namespace: "m",
107
- )
108
- math_element = Utility.ox_element("oMath", namespace: "m")
109
- content = omml_content(boolean_display_style(display_style))
110
- para_element << Utility.update_nodes(math_element, content)
111
- Plurimath.xml_engine.dump(para_element, indent: 2).gsub("&amp;", "&").lstrip
111
+ def to_omml(display_style: displaystyle, split_on_linebreak: false)
112
+ objects = split_on_linebreak ? new_line_support : [self]
113
+
114
+ para_element = Utility.ox_element("oMathPara", attributes: omml_attrs, namespace: "m")
115
+ objects.each.with_index(1) do |object, index|
116
+ para_element << Utility.update_nodes(
117
+ Utility.ox_element("oMath", namespace: "m"),
118
+ object.omml_content(boolean_display_style(display_style)),
119
+ )
120
+ next if objects.length == index
121
+
122
+ para_element << omml_br_tag
123
+ end
124
+ dump_nodes(para_element, indent: 2)
112
125
  rescue
113
126
  parse_error!(:omml)
114
127
  end
@@ -168,8 +181,8 @@ module Plurimath
168
181
  end
169
182
  end
170
183
 
171
- def extract_class_from_text
172
- return false unless (value.length < 2 && value&.first&.is_a?(Function::Text))
184
+ def extract_class_name_from_text
185
+ return unless value.length < 2 && value.first.is_a?(Function::Text)
173
186
 
174
187
  value.first.parameter_one
175
188
  end
@@ -182,10 +195,62 @@ module Plurimath
182
195
  (value.none?(Function::Left) || value.none?(Function::Right))
183
196
  end
184
197
 
198
+ def value_exist?
199
+ value && !value.empty?
200
+ end
201
+
202
+ def update(object)
203
+ self.value = Array(object)
204
+ end
205
+
206
+ def cloned_objects
207
+ cloned_obj = value.map(&:cloned_objects)
208
+ formula = self.class.new(cloned_obj)
209
+ formula.left_right_wrapper = @left_right_wrapper
210
+ formula
211
+ end
212
+
213
+ def new_line_support(array = [])
214
+ cloned = cloned_objects
215
+ obj = self.class.new
216
+ cloned.line_breaking(obj)
217
+ array << cloned
218
+ obj.value_exist? ? obj.new_line_support(array) : array
219
+ end
220
+
221
+ def line_breaking(obj)
222
+ if result.size > 1
223
+ breaked_result = result.first.last.omml_line_break(result)
224
+ update(Array(breaked_result.shift))
225
+ obj.update(breaked_result.flatten)
226
+ reprocess_value(obj)
227
+ return
228
+ end
229
+
230
+ value.each.with_index(1) do |object, index|
231
+ object.line_breaking(obj)
232
+ break obj.insert(value.slice!(index..value.size)) if obj.value_exist?
233
+ end
234
+ end
235
+
236
+ def reprocess_value(obj)
237
+ new_obj = self.class.new([])
238
+ self.line_breaking(new_obj)
239
+ if new_obj.value_exist?
240
+ obj.value.insert(0, Function::Linebreak.new)
241
+ obj.value.insert(0, self.class.new(new_obj.value))
242
+ end
243
+ end
244
+
245
+ def insert(values)
246
+ update(Array(value) + values)
247
+ end
248
+
249
+
185
250
  protected
186
251
 
187
252
  def boolean_display_style(display_style = displaystyle)
188
- YAML.load(display_style.to_s)
253
+ YAML.safe_load(display_style.to_s)
189
254
  end
190
255
 
191
256
  def new_space(spacing, indent)
@@ -203,6 +268,11 @@ module Plurimath
203
268
  def parse_error!(type)
204
269
  Math.parse_error!(input_string, type)
205
270
  end
271
+
272
+ def omml_br_tag
273
+ r_tag = ox_element("r", namespace: "m")
274
+ r_tag << ox_element("br")
275
+ end
206
276
  end
207
277
  end
208
278
  end
@@ -6,32 +6,45 @@ module Plurimath
6
6
  module Math
7
7
  module Function
8
8
  class Abs < UnaryFunction
9
+ attr_accessor :open_paren, :close_paren
10
+
9
11
  def to_mathml_without_math_tag
10
12
  symbol = Utility.ox_element("mo") << "|"
11
- first_value = mathml_value&.insert(0, symbol)
12
- Utility.update_nodes(
13
- Utility.ox_element("mrow"),
14
- first_value << symbol,
15
- )
13
+ first_value = mathml_value
14
+ first_value = first_value&.insert(0, symbol) unless open_paren
15
+ first_value << symbol unless close_paren
16
+ Utility.update_nodes(ox_element("mrow"), first_value)
16
17
  end
17
18
 
18
19
  def to_omml_without_math_tag(display_style)
19
- md = (Utility.ox_element("d", namespace: "m") << mdpr_tag)
20
- me = Utility.ox_element("e", namespace: "m")
21
- Utility.update_nodes(me, omml_value(display_style))
22
- Utility.update_nodes(md, Array(me))
23
- [md]
20
+ Array(
21
+ md_tag << omml_parameter(parameter_one, display_style, tag_name: "e"),
22
+ )
23
+ end
24
+
25
+ def line_breaking(obj)
26
+ parameter_one.line_breaking(obj)
27
+ if obj.value_exist?
28
+ ceil_object = self.class.new(Utility.filter_values(obj.value))
29
+ ceil_object.open_paren = true
30
+ ceil_object.close_paren = false
31
+ obj.update(ceil_object)
32
+ self.close_paren = true
33
+ self.open_paren = false unless open_paren
34
+ end
24
35
  end
25
36
 
26
37
  protected
27
38
 
28
- def mdpr_tag
39
+ def md_tag
29
40
  attribute = { "m:val": "|" }
41
+ sepchr_attr = { "m:val": "" }
30
42
  mdpr = Utility.pr_element("d", namespace: "m")
31
- mdpr << Utility.ox_element("begChr", namespace: "m", attributes: attribute)
32
- mdpr << Utility.ox_element("endChr", namespace: "m", attributes: attribute)
33
- mdpr << Utility.ox_element("sepChr", namespace: "m", attributes: { "m:val": "" })
34
- mdpr << Utility.ox_element("grow", namespace: "m")
43
+ mdpr << ox_element("begChr", namespace: "m", attributes: attribute) unless open_paren
44
+ mdpr << ox_element("endChr", namespace: "m", attributes: attribute) unless close_paren
45
+ mdpr << ox_element("sepChr", namespace: "m", attributes: sepchr_attr)
46
+ mdpr << ox_element("grow", namespace: "m")
47
+ ox_element("d", namespace: "m") << mdpr
35
48
  end
36
49
  end
37
50
  end
@@ -48,6 +48,11 @@ module Plurimath
48
48
  Ul.new(parameter_one, attributes)
49
49
  end
50
50
 
51
+ def line_breaking(obj)
52
+ parameter_one&.line_breaking(obj)
53
+ obj.update(Utility.filter_values(obj.value)) if obj.value_exist?
54
+ end
55
+
51
56
  protected
52
57
 
53
58
  def acc_tag(display_style)