plurimath 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.rspec +3 -0
  4. data/.rspec-opal +11 -0
  5. data/Gemfile +3 -0
  6. data/Rakefile +11 -0
  7. data/lib/plurimath/asciimath/transform.rb +15 -0
  8. data/lib/plurimath/latex/constants.rb +3 -0
  9. data/lib/plurimath/latex/parse.rb +20 -11
  10. data/lib/plurimath/latex/transform.rb +24 -2
  11. data/lib/plurimath/math/core.rb +88 -0
  12. data/lib/plurimath/math/formula.rb +68 -24
  13. data/lib/plurimath/math/function/base.rb +8 -2
  14. data/lib/plurimath/math/function/binary_function.rb +36 -4
  15. data/lib/plurimath/math/function/color.rb +14 -0
  16. data/lib/plurimath/math/function/fenced.rb +27 -0
  17. data/lib/plurimath/math/function/floor.rb +1 -1
  18. data/lib/plurimath/math/function/font_style.rb +45 -0
  19. data/lib/plurimath/math/function/frac.rb +6 -0
  20. data/lib/plurimath/math/function/int.rb +7 -0
  21. data/lib/plurimath/math/function/left.rb +19 -1
  22. data/lib/plurimath/math/function/lim.rb +6 -0
  23. data/lib/plurimath/math/function/limits.rb +7 -0
  24. data/lib/plurimath/math/function/log.rb +6 -0
  25. data/lib/plurimath/math/function/menclose.rb +6 -0
  26. data/lib/plurimath/math/function/mod.rb +6 -0
  27. data/lib/plurimath/math/function/msgroup.rb +28 -0
  28. data/lib/plurimath/math/function/multiscript.rb +7 -0
  29. data/lib/plurimath/math/function/nary.rb +94 -0
  30. data/lib/plurimath/math/function/oint.rb +6 -0
  31. data/lib/plurimath/math/function/over.rb +6 -0
  32. data/lib/plurimath/math/function/overset.rb +6 -0
  33. data/lib/plurimath/math/function/power.rb +8 -2
  34. data/lib/plurimath/math/function/power_base.rb +10 -31
  35. data/lib/plurimath/math/function/prod.rb +19 -18
  36. data/lib/plurimath/math/function/right.rb +19 -1
  37. data/lib/plurimath/math/function/root.rb +6 -0
  38. data/lib/plurimath/math/function/rule.rb +7 -0
  39. data/lib/plurimath/math/function/semantics.rb +6 -0
  40. data/lib/plurimath/math/function/stackrel.rb +6 -0
  41. data/lib/plurimath/math/function/substack.rb +6 -0
  42. data/lib/plurimath/math/function/sum.rb +26 -25
  43. data/lib/plurimath/math/function/table.rb +52 -24
  44. data/lib/plurimath/math/function/td.rb +28 -0
  45. data/lib/plurimath/math/function/ternary_function.rb +44 -4
  46. data/lib/plurimath/math/function/text.rb +24 -2
  47. data/lib/plurimath/math/function/tr.rb +28 -0
  48. data/lib/plurimath/math/function/unary_function.rb +43 -3
  49. data/lib/plurimath/math/function/underover.rb +7 -55
  50. data/lib/plurimath/math/function/underset.rb +6 -0
  51. data/lib/plurimath/math/function/vec.rb +40 -0
  52. data/lib/plurimath/math/function.rb +7 -5
  53. data/lib/plurimath/math/number.rb +9 -5
  54. data/lib/plurimath/math/symbol.rb +13 -9
  55. data/lib/plurimath/math.rb +1 -3
  56. data/lib/plurimath/mathml/parser.rb +4 -4
  57. data/lib/plurimath/mathml/transform.rb +3 -4
  58. data/lib/plurimath/omml/parser.rb +3 -3
  59. data/lib/plurimath/omml/transform.rb +12 -11
  60. data/lib/plurimath/setup/oga.rb +5 -0
  61. data/lib/plurimath/setup/opal.rb.erb +8 -0
  62. data/lib/plurimath/setup/ox.rb +5 -0
  63. data/lib/plurimath/utility.rb +48 -13
  64. data/lib/plurimath/version.rb +1 -1
  65. data/lib/plurimath/xml_engine/oga.rb +246 -0
  66. data/lib/plurimath/xml_engine/ox.rb +29 -0
  67. data/lib/plurimath/xml_engine.rb +6 -0
  68. data/lib/plurimath.rb +12 -2
  69. metadata +11 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6fabed12e1b85fa2c5d7b2cacfebaf2bafb8481025f6f0a9b072649ff2991131
4
- data.tar.gz: ec912de1e4e356af0d7458c0b2147ea9aee1fb4676506429ac5e4161cd974c79
3
+ metadata.gz: af2ed460bf37f3496c528c6cb170f2c555873332771086113f90a875312b467a
4
+ data.tar.gz: d9311eaf4dfb84c188966346a38d273e544f035c573afb50898bd9f03f81c9fc
5
5
  SHA512:
6
- metadata.gz: d31d2f5b644402ab58c0f19a9c14e88f91fff26d44dff6c89484b66d45d3760087be0827002c87c3b9ca540ac7dd52ad2ceb014f4b0f6b16fc9f94630f823c70
7
- data.tar.gz: 8f5ea828f70451af6ae075d8e06db4055145e096c83fc39b9a31cdcc57ddfff57afdd736e9f696d83e68d7b6c50ada74fa68f46acc00e878e08c1db22050ed2d
6
+ metadata.gz: cffd311295a1f9e41d372c544909029da3f5798f5744e14e549dd1d7e220755971d5bec0a91cc3695fdef25f3d9b44de606da37876c615eee3cc3818eadbe6e9
7
+ data.tar.gz: f4035ab63d7f2f3f0aef261f9491ed163a1ffec03d52011b7dda140d6ce4c303bd277a5d05487028b8c77c32585359a826d85fcfc46bb32220e4d1b103b54fb3
data/.gitignore CHANGED
@@ -6,7 +6,11 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /Gemfile.lock
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
12
13
  /coverage/
14
+
15
+ # temp files
16
+ *.kate-swp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rspec-opal ADDED
@@ -0,0 +1,11 @@
1
+ --default-path=spec
2
+ -I lib
3
+ -q oga/setup_opal
4
+ -q ll/setup_opal
5
+ --opal-opt=-g,htmlentities
6
+ --opal-opt=-g,equivalent-xml
7
+ --opal-opt=-g,parslet
8
+ --opal-opt=-g,oga
9
+ --format documentation
10
+ --color
11
+ --require spec_helper
data/Gemfile CHANGED
@@ -8,3 +8,6 @@ gem "rspec", "~> 3.0"
8
8
  gem 'simplecov', require: false, group: :test
9
9
  gem 'htmlentities'
10
10
  gem 'equivalent-xml'
11
+ gem 'opal-rspec', "~> 1.1.0a"
12
+ gem 'oga'
13
+ gem 'ox'
data/Rakefile CHANGED
@@ -1,6 +1,17 @@
1
+ require "erb"
1
2
  require "bundler/gem_tasks"
2
3
  require "rspec/core/rake_task"
4
+ require 'opal/rspec/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
8
+ # Opal testing support
9
+ begin
10
+ Opal::RSpec::RakeTask.new(:"spec-opal")
11
+ rescue LoadError
12
+ # Likely the dependencies haven't been upstreamed yet. Ensure you
13
+ # run those tests via the `plurimath-js` repo's `env/plurimath`
14
+ # script.
15
+ end
16
+
6
17
  task :default => :spec
@@ -132,6 +132,13 @@ module Plurimath
132
132
  new_arr
133
133
  end
134
134
 
135
+ rule(sequence: simple(:sequence),
136
+ left_right: sequence(:left_right)) do
137
+ new_arr = [sequence]
138
+ new_arr += left_right unless left_right.empty?
139
+ new_arr
140
+ end
141
+
135
142
  rule(sequence: simple(:sequence),
136
143
  number: simple(:number)) do
137
144
  [sequence, Math::Number.new(number.to_s)]
@@ -629,6 +636,14 @@ module Plurimath
629
636
  sequence.flatten.compact + expr.flatten.compact
630
637
  end
631
638
 
639
+ rule(sequence: simple(:sequence),
640
+ symbol: simple(:symbol)) do
641
+ [
642
+ sequence,
643
+ Math::Symbol.new(symbol),
644
+ ]
645
+ end
646
+
632
647
  rule(binary_class: simple(:function),
633
648
  base_value: simple(:base)) do
634
649
  Utility.get_class(function).new(
@@ -1720,6 +1720,7 @@ module Plurimath
1720
1720
  cap: "∩",
1721
1721
  cup: "∪",
1722
1722
  sim: "∼",
1723
+ int: "∫",
1723
1724
  neq: "≠",
1724
1725
  leq: "≤",
1725
1726
  geq: "≥",
@@ -2853,6 +2854,7 @@ module Plurimath
2853
2854
  mathbfit: :fonts,
2854
2855
  mathfrak: :fonts,
2855
2856
  overline: :unary,
2857
+ underset: :binary,
2856
2858
  overset: :binary,
2857
2859
  ddagger: :symbols,
2858
2860
  trprime: :symbols,
@@ -3245,6 +3247,7 @@ module Plurimath
3245
3247
  textrm: :fonts,
3246
3248
  textbf: :fonts,
3247
3249
  arccos: :unary,
3250
+ cancel: :unary,
3248
3251
  arcsin: :unary,
3249
3252
  arctan: :unary,
3250
3253
  limsup: :unary,
@@ -4,11 +4,18 @@ require "parslet"
4
4
  module Plurimath
5
5
  class Latex
6
6
  class Parse < Parslet::Parser
7
- rule(:base) { str("_") }
8
- rule(:power) { str("^") }
9
- rule(:slash) { str("\\") }
10
- rule(:under_over) { slash >> underover_classes }
11
- rule(:array_args) { (str("{") >> expression.as(:args) >> str("}")) }
7
+ rule(:base) { str("_") }
8
+ rule(:power) { str("^") }
9
+ rule(:slash) { str("\\") }
10
+ rule(:under_over) { slash >> underover_classes }
11
+ rule(:array_args) { (str("{") >> expression.as(:args) >> str("}")) }
12
+ rule(:array_begin) { (str("\\begin{") >> str("array").as(:environment) >> str("}")) }
13
+ rule(:optional_args) { (str("[") >> intermediate_exp.maybe.as(:options) >> str("]")).maybe }
14
+
15
+ rule(:color) do
16
+ (str("{") >> (str("}").absent? >> any).repeat.as(:symbol) >> str("}")) |
17
+ any.as(:symbol)
18
+ end
12
19
 
13
20
  rule(:optional_args) do
14
21
  (str("[") >> intermediate_exp.maybe.as(:options) >> str("]")).maybe
@@ -16,11 +23,7 @@ module Plurimath
16
23
 
17
24
  rule(:begining) do
18
25
  (slash >> str("begin") >> (str("{") >> symbol_text_or_integer >> str("*").as(:asterisk) >> str("}")) >> optional_args.maybe) |
19
- (slash >> str("begin") >> (str("{") >> symbol_text_or_integer >> str("}")))
20
- end
21
-
22
- rule(:array_begin) do
23
- (str("\\begin{") >> str("array").as(:environment) >> str("}"))
26
+ (slash >> str("begin") >> (str("{") >> symbol_text_or_integer >> str("}")))
24
27
  end
25
28
 
26
29
  rule(:ending) do
@@ -123,7 +126,8 @@ module Plurimath
123
126
  rule(:binary_functions) do
124
127
  (intermediate_exp.as(:first_value) >> under_over >> intermediate_exp.as(:second_value)).as(:under_over) |
125
128
  (slash >> str("sqrt").as(:root) >> sqrt_arg.as(:first_value) >> intermediate_exp.as(:second_value)).as(:binary) |
126
- (slash >> str("sqrt").as(:sqrt) >> intermediate_exp.as(:intermediate_exp)).as(:binary)
129
+ (slash >> str("sqrt").as(:sqrt) >> intermediate_exp.as(:intermediate_exp)).as(:binary) |
130
+ (color_rules)
127
131
  end
128
132
 
129
133
  rule(:sequence) do
@@ -242,6 +246,11 @@ module Plurimath
242
246
  (power >> intermediate_exp.as(:supscript)) |
243
247
  (base >> intermediate_exp.as(:subscript))
244
248
  end
249
+
250
+ def color_rules
251
+ (str("{") >> slash >> str("color").as(:binary) >> color.as(:first_value) >> (sequence >> iteration.maybe).as(:second_value).maybe >> str("}")) |
252
+ (slash >> str("color").as(:binary) >> color.as(:first_value) >> expression.as(:second_value).maybe)
253
+ end
245
254
  end
246
255
  end
247
256
  end
@@ -516,7 +516,7 @@ module Plurimath
516
516
 
517
517
  rule(text: simple(:text),
518
518
  first_value: sequence(:first_value),
519
- subscript: simple(:subscript),) do
519
+ subscript: simple(:subscript)) do
520
520
  Math::Function::Base.new(
521
521
  Math::Function::Text.new(first_value.join),
522
522
  subscript,
@@ -525,13 +525,24 @@ module Plurimath
525
525
 
526
526
  rule(text: simple(:text),
527
527
  first_value: simple(:first_value),
528
- subscript: simple(:subscript),) do
528
+ subscript: simple(:subscript)) do
529
529
  Math::Function::Base.new(
530
530
  Math::Function::Text.new(first_value),
531
531
  subscript,
532
532
  )
533
533
  end
534
534
 
535
+ rule(text: simple(:text),
536
+ first_value: simple(:first_value),
537
+ subscript: simple(:subscript),
538
+ supscript: simple(:supscript)) do
539
+ Math::Function::PowerBase.new(
540
+ Math::Function::Text.new(first_value),
541
+ subscript,
542
+ supscript,
543
+ )
544
+ end
545
+
535
546
  rule(unary: simple(:unary),
536
547
  first_value: simple(:first_value)) do
537
548
  Utility.get_class(
@@ -788,6 +799,17 @@ module Plurimath
788
799
  end
789
800
  end
790
801
 
802
+ rule(binary: simple(:binary),
803
+ first_value: simple(:first_value),
804
+ second_value: sequence(:second_value)) do
805
+ Utility.get_class(
806
+ binary.to_s.include?("mod") ? "mod" : binary,
807
+ ).new(
808
+ first_value,
809
+ Utility.filter_values(second_value),
810
+ )
811
+ end
812
+
791
813
  rule(underover: simple(:function),
792
814
  first_value: simple(:first),
793
815
  subscript: simple(:subscript),
@@ -64,6 +64,94 @@ module Plurimath
64
64
  def font_style_t_tag(display_style)
65
65
  to_omml_without_math_tag(display_style)
66
66
  end
67
+
68
+ def ascii_fields_to_print(field, options = {})
69
+ return if field.nil?
70
+
71
+ hashed = common_math_zone_conversion(field, options)
72
+ options[:array] << "#{hashed[:spacing]}|_ \"#{field&.to_asciimath}\"#{hashed[:field_name]}\n"
73
+ return unless Utility.validate_math_zone(field)
74
+
75
+ options[:array] << field&.to_asciimath_math_zone(hashed[:function_spacing], hashed[:last], hashed[:indent])
76
+ end
77
+
78
+ def latex_fields_to_print(field, options = {})
79
+ return if field.nil?
80
+
81
+ hashed = common_math_zone_conversion(field, options)
82
+ options[:array] << "#{hashed[:spacing]}|_ \"#{field&.to_latex}\"#{hashed[:field_name]}\n"
83
+ return unless Utility.validate_math_zone(field)
84
+
85
+ options[:array] << field&.to_latex_math_zone(hashed[:function_spacing], hashed[:last], hashed[:indent])
86
+ end
87
+
88
+ def mathml_fields_to_print(field, options = {})
89
+ return if field.nil?
90
+
91
+ hashed = common_math_zone_conversion(field, options)
92
+ options[:array] << "#{hashed[:spacing]}|_ \"#{dump_mathml(field)}\"#{hashed[:field_name]}\n"
93
+ return unless Utility.validate_math_zone(field)
94
+
95
+ options[:array] << field&.to_mathml_math_zone(hashed[:function_spacing], hashed[:last], hashed[:indent])
96
+ end
97
+
98
+ def omml_fields_to_print(field, options = {})
99
+ return if field.nil?
100
+
101
+ hashed = common_math_zone_conversion(field, options)
102
+ display_style = options[:display_style]
103
+ options[:array] << "#{hashed[:spacing]}|_ \"#{dump_omml(field, display_style)}\"#{hashed[:field_name]}\n"
104
+ return unless Utility.validate_math_zone(field)
105
+
106
+ options[:array] << field&.to_omml_math_zone(hashed[:function_spacing], hashed[:last], hashed[:indent], display_style: display_style)
107
+ end
108
+
109
+ def dump_mathml(field)
110
+ mathml = dump_ox_nodes(field.to_mathml_without_math_tag)
111
+ mathml.gsub(/\n\s*/, "").gsub("&amp;", "&")
112
+ end
113
+
114
+ def dump_omml(field, display_style)
115
+ return if field.nil?
116
+
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;", "&")
120
+ end
121
+
122
+ def omml_nodes(display_style)
123
+ to_omml_without_math_tag(display_style)
124
+ end
125
+
126
+ def validate_mathml_fields(field)
127
+ field.nil? ? Utility.ox_element("mi") : field.to_mathml_without_math_tag
128
+ end
129
+
130
+ def common_math_zone_conversion(field, options = {})
131
+ {
132
+ spacing: options[:spacing],
133
+ last: options[:last] || true,
134
+ indent: !field&.is_a?(Formula),
135
+ function_spacing: "#{options[:spacing]}#{options[:additional_space]}",
136
+ field_name: options[:field_name] ? " #{options[:field_name]}" : "",
137
+ }
138
+ end
139
+
140
+ def filtered_values(value)
141
+ @values = Utility.filter_math_zone_values(value)
142
+ end
143
+
144
+ def dump_ox_nodes(nodes)
145
+ Plurimath.xml_engine.dump(nodes)
146
+ end
147
+
148
+ def gsub_spacing(spacing, last)
149
+ spacing.gsub(/\|\_/, last ? " " : "| ")
150
+ end
151
+
152
+ def invert_unicode_symbols
153
+ Mathml::Constants::UNICODE_SYMBOLS.invert[class_name] || class_name
154
+ end
67
155
  end
68
156
  end
69
157
  end
@@ -4,6 +4,12 @@ module Plurimath
4
4
  module Math
5
5
  class Formula < Core
6
6
  attr_accessor :value, :left_right_wrapper, :displaystyle, :input_string
7
+ MATH_ZONE_TYPES = %i[
8
+ omml
9
+ latex
10
+ mathml
11
+ asciimath
12
+ ].freeze
7
13
 
8
14
  def initialize(
9
15
  value = [],
@@ -18,7 +24,9 @@ module Plurimath
18
24
  end
19
25
 
20
26
  def ==(object)
21
- object.value == value &&
27
+ object.respond_to?(:value) &&
28
+ object.respond_to?(:left_right_wrapper) &&
29
+ object.value == value &&
22
30
  object.left_right_wrapper == left_right_wrapper
23
31
  end
24
32
 
@@ -38,7 +46,7 @@ module Plurimath
38
46
  style = Utility.ox_element("mstyle", attributes: style_attrs)
39
47
  Utility.update_nodes(style, mathml_content)
40
48
  Utility.update_nodes(math, [style])
41
- Ox.dump(math, indent: 2).gsub("&amp;", "&")
49
+ Plurimath.xml_engine.dump(math, indent: 2).gsub("&amp;", "&")
42
50
  rescue
43
51
  parse_error!(:mathml)
44
52
  end
@@ -100,7 +108,7 @@ module Plurimath
100
108
  math_element = Utility.ox_element("oMath", namespace: "m")
101
109
  content = omml_content(boolean_display_style(display_style))
102
110
  para_element << Utility.update_nodes(math_element, content)
103
- Ox.dump(para_element, indent: 2).gsub("&amp;", "&").lstrip
111
+ Plurimath.xml_engine.dump(para_element, indent: 2).gsub("&amp;", "&").lstrip
104
112
  rescue
105
113
  parse_error!(:omml)
106
114
  end
@@ -110,20 +118,54 @@ module Plurimath
110
118
  end
111
119
 
112
120
  def to_omml_without_math_tag(display_style)
113
- return nary_tag(display_style) if nary_tag_able?(display_style)
114
-
115
121
  omml_content(display_style)
116
122
  end
117
123
 
118
- def nary_tag(display_style)
119
- nary_element = Utility.ox_element("nary", namespace: "m")
120
- e_tag = Utility.ox_element("e", namespace: "m")
121
- Utility.update_nodes(e_tag, value.last.insert_t_tag(display_style))
122
- Utility.update_nodes(
123
- nary_element,
124
- (value.first.omml_nary_tag(display_style) << e_tag),
125
- )
126
- [nary_element]
124
+ def to_display(type = nil)
125
+ return type_error! unless MATH_ZONE_TYPES.include?(type.downcase.to_sym)
126
+
127
+ math_zone = case type
128
+ when :asciimath
129
+ " |_ \"#{to_asciimath}\"\n#{to_asciimath_math_zone(" ").join}"
130
+ when :latex
131
+ " |_ \"#{to_latex}\"\n#{to_latex_math_zone(" ").join}"
132
+ when :mathml
133
+ " |_ \"#{to_mathml.gsub(/\n\s*/, "")}\"\n#{to_mathml_math_zone(" ").join}"
134
+ when :omml
135
+ " |_ \"#{to_omml.gsub(/\n\s*/, "")}\"\n#{to_omml_math_zone(" ", display_style: displaystyle).join}"
136
+ end
137
+ <<~MATHZONE.sub(/\n$/, "")
138
+ |_ Math zone
139
+ #{math_zone}
140
+ MATHZONE
141
+ end
142
+
143
+ def to_asciimath_math_zone(spacing = "", last = false, indent = true)
144
+ filtered_values(value).map.with_index(1) do |object, index|
145
+ last = index == @values.length
146
+ object.to_asciimath_math_zone(new_space(spacing, indent), last, indent)
147
+ end
148
+ end
149
+
150
+ def to_latex_math_zone(spacing = "", last = false, indent = true)
151
+ filtered_values(value).map.with_index(1) do |object, index|
152
+ last = index == @values.length
153
+ object.to_latex_math_zone(new_space(spacing, indent), last, indent)
154
+ end
155
+ end
156
+
157
+ def to_mathml_math_zone(spacing = "", last = false, indent = true)
158
+ filtered_values(value).map.with_index(1) do |object, index|
159
+ last = index == @values.length
160
+ object.to_mathml_math_zone(new_space(spacing, indent), last, indent)
161
+ end
162
+ end
163
+
164
+ def to_omml_math_zone(spacing = "", last = false, indent = true, display_style:)
165
+ filtered_values(value).map.with_index(1) do |object, index|
166
+ last = index == @values.length
167
+ object.to_omml_math_zone(new_space(spacing, indent), last, indent, display_style: display_style)
168
+ end
127
169
  end
128
170
 
129
171
  def extract_class_from_text
@@ -136,16 +178,6 @@ module Plurimath
136
178
  value.first.nary_attr_value
137
179
  end
138
180
 
139
- def nary_tag_able?(display_style)
140
- value.length == 2 &&
141
- ["underover", "powerbase"].include?(value&.first&.class_name) &&
142
- !value.first.parameter_one.is_a?(Function::FontStyle) &&
143
- (
144
- value&.first&.parameter_one&.to_omml_without_math_tag(display_style)&.length == 1 ||
145
- value&.first&.parameter_one.to_omml_without_math_tag(display_style).match?(/^&#x\w*\d*;$/)
146
- )
147
- end
148
-
149
181
  def validate_function_formula
150
182
  (value.none?(Function::Left) || value.none?(Function::Right))
151
183
  end
@@ -156,6 +188,18 @@ module Plurimath
156
188
  YAML.load(display_style.to_s)
157
189
  end
158
190
 
191
+ def new_space(spacing, indent)
192
+ if value.any? { |val| val.class_name == "left" } && value.any? { |val| val.class_name == "right" }
193
+ return spacing
194
+ end
195
+
196
+ (indent && wrapable?(spacing)) ? spacing + "|_ " : spacing
197
+ end
198
+
199
+ def wrapable?(spacing)
200
+ left_right_wrapper && !spacing.end_with?("|_ ")
201
+ end
202
+
159
203
  def parse_error!(type)
160
204
  Math.parse_error!(input_string, type)
161
205
  end
@@ -6,6 +6,12 @@ module Plurimath
6
6
  module Math
7
7
  module Function
8
8
  class Base < BinaryFunction
9
+ FUNCTION = {
10
+ name: "subscript",
11
+ first_value: "base",
12
+ second_value: "script",
13
+ }.freeze
14
+
9
15
  def to_asciimath
10
16
  first_value = parameter_one.to_asciimath if parameter_one
11
17
  second_value = "_#{wrapped(parameter_two)}" if parameter_two
@@ -16,8 +22,8 @@ module Plurimath
16
22
  tag_name = (Utility::MUNDER_CLASSES.include?(parameter_one&.class_name) ? "under" : "sub")
17
23
  sub_tag = Utility.ox_element("m#{tag_name}")
18
24
  mathml_value = []
19
- mathml_value << parameter_one&.to_mathml_without_math_tag
20
- mathml_value << parameter_two&.to_mathml_without_math_tag if parameter_two
25
+ mathml_value << validate_mathml_fields(parameter_one)
26
+ mathml_value << validate_mathml_fields(parameter_two)
21
27
  Utility.update_nodes(sub_tag, mathml_value)
22
28
  end
23
29
 
@@ -64,6 +64,42 @@ module Plurimath
64
64
  !(parameter_one.nil? && parameter_two.nil?)
65
65
  end
66
66
 
67
+ def to_asciimath_math_zone(spacing, last = false, _)
68
+ parameters = self.class::FUNCTION
69
+ new_spacing = gsub_spacing(spacing, last)
70
+ new_arr = ["#{spacing}\"#{to_asciimath}\" #{parameters[:name]}\n"]
71
+ ascii_fields_to_print(parameter_one, { spacing: new_spacing, field_name: parameters[:first_value], additional_space: "| |_ " , array: new_arr })
72
+ ascii_fields_to_print(parameter_two, { spacing: new_spacing, field_name: parameters[:second_value], additional_space: " |_ " , array: new_arr })
73
+ new_arr
74
+ end
75
+
76
+ def to_latex_math_zone(spacing, last = false, _)
77
+ parameters = self.class::FUNCTION
78
+ new_spacing = gsub_spacing(spacing, last)
79
+ new_arr = ["#{spacing}\"#{to_latex}\" #{parameters[:name]}\n"]
80
+ latex_fields_to_print(parameter_one, { spacing: new_spacing, field_name: parameters[:first_value], additional_space: "| |_ " , array: new_arr })
81
+ latex_fields_to_print(parameter_two, { spacing: new_spacing, field_name: parameters[:second_value], additional_space: " |_ " , array: new_arr })
82
+ new_arr
83
+ end
84
+
85
+ def to_mathml_math_zone(spacing, last = false, _)
86
+ parameters = self.class::FUNCTION
87
+ new_spacing = gsub_spacing(spacing, last)
88
+ new_arr = ["#{spacing}\"#{dump_mathml(self)}\" #{parameters[:name]}\n"]
89
+ mathml_fields_to_print(parameter_one, { spacing: new_spacing, field_name: parameters[:first_value], additional_space: "| |_ ", array: new_arr })
90
+ mathml_fields_to_print(parameter_two, { spacing: new_spacing, field_name: parameters[:second_value], additional_space: " |_ ", array: new_arr })
91
+ new_arr
92
+ end
93
+
94
+ def to_omml_math_zone(spacing, last = false, _, display_style:)
95
+ parameters = self.class::FUNCTION
96
+ new_spacing = gsub_spacing(spacing, last)
97
+ new_arr = ["#{spacing}\"#{dump_omml(self, display_style)}\" #{parameters[:name]}\n"]
98
+ omml_fields_to_print(parameter_one, { spacing: new_spacing, field_name: parameters[:first_value], additional_space: "| |_ ", array: new_arr, display_style: display_style })
99
+ omml_fields_to_print(parameter_two, { spacing: new_spacing, field_name: parameters[:second_value], additional_space: " |_ ", array: new_arr, display_style: display_style })
100
+ new_arr
101
+ end
102
+
67
103
  protected
68
104
 
69
105
  def latex_wrapped(field)
@@ -80,10 +116,6 @@ module Plurimath
80
116
  "(#{field.to_asciimath})"
81
117
  end
82
118
 
83
- def invert_unicode_symbols
84
- Mathml::Constants::UNICODE_SYMBOLS.invert[class_name] || class_name
85
- end
86
-
87
119
  def empty_tag(wrapper_tag)
88
120
  r_tag = Utility.ox_element("r", namespace: "m")
89
121
  r_tag << (Utility.ox_element("t", namespace: "m") << "&#8203;")
@@ -6,6 +6,12 @@ module Plurimath
6
6
  module Math
7
7
  module Function
8
8
  class Color < BinaryFunction
9
+ FUNCTION = {
10
+ name: "color",
11
+ first_value: "mathcolor",
12
+ second_value: "text",
13
+ }.freeze
14
+
9
15
  def to_asciimath
10
16
  first_value = "(#{parameter_one&.to_asciimath&.gsub(/\s/, '')})"
11
17
  second_value = "(#{parameter_two&.to_asciimath})"
@@ -31,6 +37,14 @@ module Plurimath
31
37
  def to_omml_without_math_tag(display_style)
32
38
  Array(parameter_two.insert_t_tag(display_style))
33
39
  end
40
+
41
+ def to_omml_math_zone(spacing, last = false, _, display_style:)
42
+ parameters = self.class::FUNCTION
43
+ new_spacing = gsub_spacing(spacing, last)
44
+ new_arr = ["#{spacing}\"#{dump_omml(self, display_style)}\" #{parameters[:name]}\n"]
45
+ omml_fields_to_print(parameter_two, { spacing: new_spacing, field_name: "text", additional_space: "| |_ ", array: new_arr, display_style: display_style })
46
+ new_arr
47
+ end
34
48
  end
35
49
  end
36
50
  end
@@ -56,6 +56,33 @@ module Plurimath
56
56
  [d]
57
57
  end
58
58
 
59
+ def to_asciimath_math_zone(spacing, last = false, indent = true)
60
+ filtered_values(parameter_two).map.with_index(1) do |object, index|
61
+ last = index == @values.length
62
+ object.to_asciimath_math_zone(spacing, last, indent)
63
+ end
64
+ end
65
+
66
+ def to_latex_math_zone(spacing, last = false, indent = true)
67
+ filtered_values(parameter_two).map.with_index(1) do |object, index|
68
+ last = index == @values.length
69
+ object.to_latex_math_zone(spacing, last, indent)
70
+ end
71
+ end
72
+
73
+ def to_mathml_math_zone(spacing, last = false, indent = true)
74
+ filtered_values(parameter_two).map.with_index(1) do |object, index|
75
+ last = index == @values.length
76
+ object.to_mathml_math_zone(spacing, last, indent)
77
+ end
78
+ end
79
+
80
+ def to_omml_math_zone(spacing, last = false, indent = true, display_style:)
81
+ filtered_values(parameter_two).map.with_index(1) do |object, index|
82
+ object.to_omml_math_zone(spacing, last, !indent, display_style: display_style)
83
+ end
84
+ end
85
+
59
86
  protected
60
87
 
61
88
  def first_value(dpr)
@@ -7,7 +7,7 @@ module Plurimath
7
7
  module Function
8
8
  class Floor < UnaryFunction
9
9
  def to_latex
10
- "\\lfloor #{parameter_one.to_latex} \\rfloor"
10
+ "{\\lfloor #{parameter_one.to_latex} \\rfloor}"
11
11
  end
12
12
 
13
13
  def to_mathml_without_math_tag
@@ -59,6 +59,51 @@ module Plurimath
59
59
  )
60
60
  [r_tag]
61
61
  end
62
+
63
+ def to_asciimath_math_zone(spacing, last = false, _)
64
+ new_spacing = gsub_spacing(spacing, last)
65
+ new_arr = [
66
+ "#{spacing}\"#{to_asciimath}\" function apply\n",
67
+ "#{new_spacing}|_ \"#{parameter_two}\" font family\n",
68
+ ]
69
+ ascii_fields_to_print(parameter_one, { spacing: new_spacing, field_name: "argument", additional_space: "| |_ " , array: new_arr })
70
+ new_arr
71
+ end
72
+
73
+ def to_latex_math_zone(spacing, last = false, _)
74
+ new_spacing = gsub_spacing(spacing, last)
75
+ new_arr = [
76
+ "#{spacing}\"#{to_latex}\" function apply\n",
77
+ "#{new_spacing}|_ \"#{parameter_two}\" font family\n",
78
+ ]
79
+ latex_fields_to_print(parameter_one, { spacing: new_spacing, field_name: "argument", additional_space: "| |_ " , array: new_arr })
80
+ new_arr
81
+ end
82
+
83
+ def to_mathml_math_zone(spacing, last = false, _)
84
+ new_spacing = gsub_spacing(spacing, last)
85
+ new_arr = [
86
+ "#{spacing}\"#{dump_mathml(self)}\" function apply\n",
87
+ "#{new_spacing}|_ \"#{omml_and_mathml_font_family}\" font family\n",
88
+ ]
89
+ mathml_fields_to_print(parameter_one, { spacing: new_spacing, field_name: "argument", additional_space: "| |_ ", array: new_arr })
90
+ new_arr
91
+ end
92
+
93
+ def to_omml_math_zone(spacing, last = false, _, display_style:)
94
+ new_spacing = gsub_spacing(spacing, last)
95
+ new_arr = [
96
+ "#{spacing}\"#{dump_omml(self, display_style)}\" function apply\n",
97
+ "#{new_spacing}|_ \"#{omml_and_mathml_font_family}\" font family\n",
98
+ ]
99
+ omml_fields_to_print(parameter_one, { spacing: new_spacing, field_name: "argument", additional_space: "| |_ ", array: new_arr, display_style: display_style })
100
+ new_arr
101
+ end
102
+
103
+ def omml_and_mathml_font_family
104
+ fonts = Utility::FONT_STYLES.select { |_font, font_class| font_class == self.class }.keys.map(&:to_s)
105
+ Omml::Parser::SUPPORTED_FONTS.values.find { |value| fonts.include?(value) }
106
+ end
62
107
  end
63
108
  end
64
109
  end