plurimath 0.8.17 → 0.8.18

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/lib/plurimath/asciimath/parse.rb +1 -0
  4. data/lib/plurimath/asciimath/transform.rb +12 -0
  5. data/lib/plurimath/math/core.rb +63 -4
  6. data/lib/plurimath/math/formula/mrow.rb +193 -0
  7. data/lib/plurimath/math/formula/mstyle.rb +17 -0
  8. data/lib/plurimath/math/formula.rb +307 -4
  9. data/lib/plurimath/math/function/base.rb +4 -0
  10. data/lib/plurimath/math/function/color.rb +17 -4
  11. data/lib/plurimath/math/function/fenced.rb +219 -0
  12. data/lib/plurimath/math/function/frac.rb +4 -0
  13. data/lib/plurimath/math/function/linebreak.rb +2 -2
  14. data/lib/plurimath/math/function/longdiv.rb +3 -0
  15. data/lib/plurimath/math/function/menclose.rb +3 -0
  16. data/lib/plurimath/math/function/merror.rb +5 -2
  17. data/lib/plurimath/math/function/mglyph.rb +27 -0
  18. data/lib/plurimath/math/function/mlabeledtr.rb +19 -0
  19. data/lib/plurimath/math/function/mpadded.rb +28 -1
  20. data/lib/plurimath/math/function/ms.rb +80 -0
  21. data/lib/plurimath/math/function/msgroup.rb +15 -0
  22. data/lib/plurimath/math/function/msline.rb +5 -2
  23. data/lib/plurimath/math/function/multiscript.rb +14 -0
  24. data/lib/plurimath/math/function/over.rb +3 -0
  25. data/lib/plurimath/math/function/overset.rb +11 -0
  26. data/lib/plurimath/math/function/phantom.rb +3 -0
  27. data/lib/plurimath/math/function/power.rb +3 -0
  28. data/lib/plurimath/math/function/power_base.rb +3 -0
  29. data/lib/plurimath/math/function/root.rb +3 -0
  30. data/lib/plurimath/math/function/scarries.rb +3 -0
  31. data/lib/plurimath/math/function/semantics.rb +14 -0
  32. data/lib/plurimath/math/function/sqrt.rb +3 -0
  33. data/lib/plurimath/math/function/stackrel.rb +3 -0
  34. data/lib/plurimath/math/function/table.rb +53 -0
  35. data/lib/plurimath/math/function/td.rb +4 -1
  36. data/lib/plurimath/math/function/text.rb +22 -2
  37. data/lib/plurimath/math/function/tr.rb +13 -0
  38. data/lib/plurimath/math/function/underover.rb +3 -0
  39. data/lib/plurimath/math/function/underset.rb +44 -0
  40. data/lib/plurimath/math/number.rb +10 -1
  41. data/lib/plurimath/math/symbols/gg.rb +4 -4
  42. data/lib/plurimath/math/symbols/ll.rb +4 -4
  43. data/lib/plurimath/math/symbols/minus.rb +1 -1
  44. data/lib/plurimath/math/symbols/symbol.rb +12 -4
  45. data/lib/plurimath/math.rb +2 -0
  46. data/lib/plurimath/mathml/parser.rb +45 -86
  47. data/lib/plurimath/mathml/utility/empty_defined_methods.rb +477 -0
  48. data/lib/plurimath/mathml/utility/formula_transformation.rb +472 -0
  49. data/lib/plurimath/mathml/utility.rb +363 -0
  50. data/lib/plurimath/mathml.rb +1 -0
  51. data/lib/plurimath/unicode_math/transform.rb +2 -2
  52. data/lib/plurimath/utility.rb +5 -23
  53. data/lib/plurimath/version.rb +1 -1
  54. data/lib/plurimath.rb +9 -0
  55. data/plurimath.gemspec +4 -2
  56. metadata +37 -5
  57. data/lib/plurimath/mathml/transform.rb +0 -413
@@ -2,13 +2,20 @@
2
2
 
3
3
  require "htmlentities"
4
4
  require_relative "unary_function"
5
+ require_relative "../../mathml/utility"
5
6
 
6
7
  module Plurimath
7
8
  module Math
8
9
  module Function
9
10
  class Text < UnaryFunction
11
+ include Mathml::Utility
12
+
10
13
  PARSER_REGEX = %r{unicode\[:(?<unicode>\w{1,})\]}.freeze
11
14
 
15
+ def initialize(parameter_one = "")
16
+ super(parameter_one)
17
+ end
18
+
12
19
  def to_asciimath(**)
13
20
  "\"#{parse_text('asciimath') || parameter_one}\""
14
21
  end
@@ -67,12 +74,25 @@ module Plurimath
67
74
  "#{spacing}\"#{dump_omml(self, display_style, options: options)}\" text\n"
68
75
  end
69
76
 
77
+ def to_unicodemath_math_zone(spacing, _, _, options:)
78
+ "#{spacing}#{to_unicodemath(options: options)} text\n"
79
+ end
80
+
70
81
  def value
71
82
  parameter_one
72
83
  end
73
84
 
74
- def to_unicodemath_math_zone(spacing, _, _, options:)
75
- "#{spacing}#{to_unicodemath(options: options)} text\n"
85
+ def element_order=(*); end
86
+
87
+ def value=(text)
88
+ text = text.join if text.is_a?(Array)
89
+ entities = HTMLEntities.new
90
+ symbols = Mathml::Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
91
+ text = entities.encode(text, :hexadecimal)
92
+ symbols.each do |code, string|
93
+ text = text.gsub(code.downcase, "unicode[:#{string}]")
94
+ end
95
+ self.parameter_one = text
76
96
  end
77
97
 
78
98
  protected
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "unary_function"
4
+ require_relative "../../mathml/utility"
4
5
 
5
6
  module Plurimath
6
7
  module Math
7
8
  module Function
8
9
  class Tr < UnaryFunction
10
+ include Mathml::Utility
11
+
9
12
  def initialize(parameter_one = [])
10
13
  parameter_one.map!.with_index { |_, index| Td.new([]) } if parameter_one&.all?("@")
11
14
  super(parameter_one)
@@ -93,6 +96,16 @@ module Plurimath
93
96
  row_lines.shift if row_lines.first.is_a?(Math::Symbols::Hline)
94
97
  first_value
95
98
  end
99
+
100
+ def mtd_value=(value)
101
+ return if value.nil? || value.empty?
102
+
103
+ self.parameter_one = replace_order_with_value(
104
+ clear_temp_order,
105
+ update_temp_mathml_values(value),
106
+ "mtd"
107
+ )
108
+ end
96
109
  end
97
110
  end
98
111
  end
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../mathml/utility"
3
4
  require_relative "ternary_function"
4
5
 
5
6
  module Plurimath
6
7
  module Math
7
8
  module Function
8
9
  class Underover < TernaryFunction
10
+ include Mathml::Utility
11
+
9
12
  FUNCTION = {
10
13
  name: "UnderOver",
11
14
  first_value: "base",
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "binary_function"
4
+ require_relative "../../mathml/utility"
4
5
 
5
6
  module Plurimath
6
7
  module Math
7
8
  module Function
8
9
  class Underset < BinaryFunction
10
+ include Mathml::Utility
11
+
9
12
  attr_accessor :options
13
+
10
14
  FUNCTION = {
11
15
  name: "underscript",
12
16
  first_value: "underscript value",
@@ -21,6 +25,13 @@ module Plurimath
21
25
  @options = options unless options.empty?
22
26
  end
23
27
 
28
+ def element_order=(value)
29
+ @temp_mathml_order = validated_order(
30
+ value,
31
+ rejectable_array: ["comment"]
32
+ )
33
+ end
34
+
24
35
  def to_mathml_without_math_tag(intent, options:)
25
36
  value_array = [
26
37
  validate_mathml_fields(parameter_two, intent, options: options),
@@ -79,8 +90,41 @@ module Plurimath
79
90
  parameter_two.is_nary_function? || parameter_two.is_nary_symbol?
80
91
  end
81
92
 
93
+ def content=(value)
94
+ if no_content_in?(Array(value))
95
+ delete_all_text
96
+ else
97
+ new_val = Array(value).map do |val|
98
+ validate_symbols(val) unless val.strip.empty?
99
+ end
100
+ validate_text_order(new_val)
101
+ end
102
+ update_temp_mathml_values(@temp_mathml_order)
103
+ end
104
+
82
105
  protected
83
106
 
107
+ def validate_text_order(value)
108
+ @temp_mathml_order.each_with_index do |item, index|
109
+ next unless item == "text"
110
+
111
+ shifted_value = value.shift
112
+ next @temp_mathml_order[index] = shifted_value if shifted_value
113
+
114
+ @temp_mathml_order.delete_at(index)
115
+ end
116
+ end
117
+
118
+ def delete_all_text
119
+ @temp_mathml_order.delete("text")
120
+ end
121
+
122
+ def no_content_in?(value)
123
+ value.nil? ||
124
+ value.empty? ||
125
+ value&.all? { |val| val.strip.empty? }
126
+ end
127
+
84
128
  def unicode_accent?(field)
85
129
  return unless field.is_a?(Math::Symbols::Symbol)
86
130
 
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../mathml/utility"
4
+
3
5
  module Plurimath
4
6
  module Math
5
7
  class Number < Core
6
8
  attr_accessor :value, :mini_sub_sized, :mini_sup_sized
9
+ include Mathml::Utility
7
10
 
8
- def initialize(value, mini_sub_sized: false, mini_sup_sized: false)
11
+ def initialize(value = nil, mini_sub_sized: false, mini_sup_sized: false)
9
12
  @value = value.is_a?(Parslet::Slice) ? value.to_s : value
10
13
  @mini_sub_sized = mini_sub_sized if mini_sub_sized
11
14
  @mini_sup_sized = mini_sup_sized if mini_sup_sized
@@ -18,6 +21,8 @@ module Plurimath
18
21
  object.mini_sup_sized == mini_sup_sized
19
22
  end
20
23
 
24
+ def element_order=(*); end
25
+
21
26
  def to_asciimath(options:)
22
27
  format_value_with_options(options)
23
28
  end
@@ -71,6 +76,10 @@ module Plurimath
71
76
  mini_sub_sized || mini_sup_sized
72
77
  end
73
78
 
79
+ def value=(value)
80
+ @value = value.is_a?(Array) ? value.join : value
81
+ end
82
+
74
83
  protected
75
84
 
76
85
  def mini_sub
@@ -3,10 +3,10 @@ module Plurimath
3
3
  module Symbols
4
4
  class Gg < Symbol
5
5
  INPUT = {
6
- unicodemath: [["gg", "&#x226b;"]],
7
- asciimath: [["&#x226b;"], parsing_wrapper(["gg"], lang: :asciimath)],
6
+ unicodemath: ["gg", "&#x226b;", parsing_wrapper(["mgt"], lang: :unicode)],
7
+ asciimath: ["&#x226b;", "gg", "mgt"],
8
8
  mathml: ["&#x226b;"],
9
- latex: [["gg", "&#x226b;"]],
9
+ latex: ["gg", "&#x226b;", parsing_wrapper(["mgt"], lang: :latex)],
10
10
  omml: ["&#x226b;"],
11
11
  html: ["&#x226b;"],
12
12
  }.freeze
@@ -17,7 +17,7 @@ module Plurimath
17
17
  end
18
18
 
19
19
  def to_asciimath(**)
20
- parsing_wrapper("gg", lang: :asciimath)
20
+ "gg"
21
21
  end
22
22
 
23
23
  def to_unicodemath(**)
@@ -3,10 +3,10 @@ module Plurimath
3
3
  module Symbols
4
4
  class Ll < Symbol
5
5
  INPUT = {
6
- unicodemath: [["ll", "&#x226a;"]],
7
- asciimath: [["&#x226a;"], parsing_wrapper(["ll"], lang: :asciimath)],
6
+ unicodemath: ["ll", "&#x226a;", parsing_wrapper(["mlt"], lang: :unicode)],
7
+ asciimath: ["&#x226a;", "ll", "mlt"],
8
8
  mathml: ["&#x226a;"],
9
- latex: [["ll", "&#x226a;"]],
9
+ latex: ["ll", "&#x226a;", parsing_wrapper(["mlt"], lang: :latex)],
10
10
  omml: ["&#x226a;"],
11
11
  html: ["&#x226a;"],
12
12
  }.freeze
@@ -17,7 +17,7 @@ module Plurimath
17
17
  end
18
18
 
19
19
  def to_asciimath(**)
20
- parsing_wrapper("ll", lang: :asciimath)
20
+ "ll"
21
21
  end
22
22
 
23
23
  def to_unicodemath(**)
@@ -5,7 +5,7 @@ module Plurimath
5
5
  INPUT = {
6
6
  unicodemath: [["&#x2212;", "-"], parsing_wrapper(["minus"], lang: :unicode)],
7
7
  asciimath: [["-", "&#x2212;"], parsing_wrapper(["minus"], lang: :asciimath)],
8
- mathml: ["&#x2212;"],
8
+ mathml: ["&#x2212;", "-"],
9
9
  latex: [["minus", "-", "&#x2212;"]],
10
10
  omml: ["&#x2212;"],
11
11
  html: ["&#x2212;"],
@@ -1,9 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../mathml/utility"
4
+
3
5
  module Plurimath
4
6
  module Math
5
7
  module Symbols
6
8
  class Symbol < Core
9
+ include Mathml::Utility
10
+
7
11
  attr_accessor :value, :slashed, :mini_sub_sized, :mini_sup_sized, :options
8
12
 
9
13
  INPUT = {}.freeze
@@ -13,7 +17,7 @@ module Plurimath
13
17
  mini_sub_sized: false,
14
18
  mini_sup_sized: false,
15
19
  options: {})
16
- @value = sym.is_a?(Parslet::Slice) ? sym.to_s : sym
20
+ @value = sym.is_a?(Array) ? sym.join : sym&.to_s
17
21
  @slashed = slashed if slashed
18
22
  @mini_sub_sized = mini_sub_sized if mini_sub_sized
19
23
  @mini_sup_sized = mini_sup_sized if mini_sup_sized
@@ -22,7 +26,7 @@ module Plurimath
22
26
 
23
27
  def ==(object)
24
28
  object.respond_to?(:value) &&
25
- object.class == object.class &&
29
+ object.class == self.class &&
26
30
  object.value == value &&
27
31
  object.slashed == slashed &&
28
32
  object.mini_sub_sized == mini_sub_sized &&
@@ -36,6 +40,10 @@ module Plurimath
36
40
  value
37
41
  end
38
42
 
43
+ def value=(value)
44
+ @value = value.is_a?(Array) ? value.join : value.to_s
45
+ end
46
+
39
47
  def to_mathml_without_math_tag(intent, **)
40
48
  if value&.include?("&#x2147;")
41
49
  attributes = {
@@ -45,7 +53,7 @@ module Plurimath
45
53
  mi_tag = ox_element("mi", attributes: attributes)
46
54
  return mi_tag if ["{:", ":}"].include?(value)
47
55
 
48
- mi_tag << value
56
+ value ? mi_tag << value : mi_tag
49
57
  end
50
58
 
51
59
  def to_latex(**)
@@ -108,7 +116,7 @@ module Plurimath
108
116
  self.is_a?(Math::Symbols::Ampersand)
109
117
  end
110
118
 
111
- def linebreak
119
+ def linebreak?
112
120
  value == "\\\\"
113
121
  end
114
122
 
@@ -13,6 +13,8 @@ require_relative "math/core"
13
13
  require_relative "math/number"
14
14
  require_relative "math/symbols"
15
15
  require_relative "math/formula"
16
+ require_relative "math/formula/mrow"
17
+ require_relative "math/formula/mstyle"
16
18
  require_relative "math/function"
17
19
  require_relative "asciimath/parser"
18
20
  require_relative "unicode_math/parser"
@@ -1,106 +1,65 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "constants"
4
- require_relative "transform"
4
+
5
5
  module Plurimath
6
6
  class Mathml
7
7
  class Parser
8
8
  attr_accessor :text
9
9
 
10
- SUPPORTED_ATTRS = %w[
11
- linebreakstyle
12
- linethickness
13
- columnlines
14
- mathvariant
15
- accentunder
16
- separators
17
- linebreak
18
- mathcolor
19
- notation
20
- bevelled
21
- rowlines
22
- intent
23
- accent
24
- height
25
- frame
26
- depth
27
- height
28
- width
29
- index
30
- close
31
- alt
32
- src
33
- open
34
- ].freeze
35
-
36
10
  def initialize(text)
11
+ mml_config
37
12
  @text = text
38
13
  end
39
14
 
40
15
  def parse
41
- ox_nodes = Plurimath.xml_engine.load(text)
42
- display_style = ox_nodes&.locate("mstyle/@displaystyle")&.first
43
- nodes = parse_nodes(Array(ox_nodes))
44
- Math::Formula.new(
45
- Transform.new.apply(nodes).flatten.compact,
46
- display_style: (display_style || true),
47
- )
16
+ namespace_exist = text.split(">").first.include?(" xmlns=")
17
+ ::Mml.parse(text, namespace_exist: namespace_exist)
48
18
  end
49
19
 
50
- protected
51
-
52
- def parse_nodes(nodes)
53
- nodes.map do |node|
54
- next if Plurimath.xml_engine.is_xml_comment?(node)
55
-
56
- if node.is_a?(String)
57
- node
58
- elsif !node.attributes.empty?
59
- attrs_hash(node)
60
- else
61
- manage_tags(node)
62
- end
63
- end
64
- end
65
-
66
- def validate_attributes(attributes)
67
- attributes&.select! { |key, _| SUPPORTED_ATTRS.include?(key.to_s) }
68
- attributes&.transform_keys(&:to_sym) if attributes&.any?
69
- end
20
+ private
70
21
 
71
- def attrs_hash(node)
72
- {
73
- node.name.to_sym => {
74
- attributes: validate_attributes(node.attributes),
75
- value: parse_nodes(node.nodes),
76
- },
22
+ def mml_config
23
+ ::Mml::Configuration.config = {
24
+ mmultiscripts: Plurimath::Math::Function::Multiscript,
25
+ mlabeledtr: Plurimath::Math::Function::Mlabeledtr,
26
+ munderover: Plurimath::Math::Function::Underover,
27
+ semantics: Plurimath::Math::Function::Semantics,
28
+ mscarries: Plurimath::Math::Function::Scarries,
29
+ mfraction: Plurimath::Math::Function::Frac,
30
+ menclose: Plurimath::Math::Function::Menclose,
31
+ mlongdiv: Plurimath::Math::Function::Longdiv,
32
+ mphantom: Plurimath::Math::Function::Phantom,
33
+ msubsup: Plurimath::Math::Function::PowerBase,
34
+ msgroup: Plurimath::Math::Function::Msgroup,
35
+ mpadded: Plurimath::Math::Function::Mpadded,
36
+ mfenced: Plurimath::Math::Function::Fenced,
37
+ mstack: Plurimath::Math::Function::Stackrel,
38
+ munder: Plurimath::Math::Function::Underset,
39
+ msline: Plurimath::Math::Function::Msline,
40
+ merror: Plurimath::Math::Function::Merror,
41
+ mtable: Plurimath::Math::Function::Table,
42
+ mstyle: Plurimath::Math::Formula::Mstyle,
43
+ mglyph: Plurimath::Math::Function::Mglyph,
44
+ mover: Plurimath::Math::Function::Overset,
45
+ msqrt: Plurimath::Math::Function::Sqrt,
46
+ mroot: Plurimath::Math::Function::Root,
47
+ mtext: Plurimath::Math::Function::Text,
48
+ mfrac: Plurimath::Math::Function::Frac,
49
+ msrow: Plurimath::Math::Formula,
50
+ msup: Plurimath::Math::Function::Power,
51
+ msub: Plurimath::Math::Function::Base,
52
+ none: Plurimath::Math::Function::None,
53
+ mrow: Plurimath::Math::Formula::Mrow,
54
+ math: Plurimath::Math::Formula,
55
+ mtd: Plurimath::Math::Function::Td,
56
+ mtr: Plurimath::Math::Function::Tr,
57
+ mi: Plurimath::Math::Symbols::Symbol,
58
+ mo: Plurimath::Math::Symbols::Symbol,
59
+ ms: Plurimath::Math::Function::Ms,
60
+ mn: Plurimath::Math::Number,
77
61
  }
78
- end
79
-
80
- def manage_tags(node)
81
- if node.name == "ms"
82
- Plurimath::xml_engine.replace_nodes(
83
- node,
84
- ms_tag(comment_remove(node.nodes)).join(" "),
85
- )
86
- end
87
- { node.name.to_sym => parse_nodes(node.nodes) }
88
- end
89
-
90
- def ms_tag(nodes)
91
- return nodes if nodes.any?(String)
92
-
93
- nodes.map do |node|
94
- if node.nodes.any?(String)
95
- node.nodes
96
- else
97
- ms_tag(node.nodes)
98
- end
99
- end
100
- end
101
-
102
- def comment_remove(nodes)
103
- nodes.delete_if { |node| Plurimath.xml_engine.is_xml_comment?(node) }
62
+ require "mml" unless ::Mml.respond_to?(:config)
104
63
  end
105
64
  end
106
65
  end