plurimath 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) 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 +4 -0
  6. data/Rakefile +11 -0
  7. data/lib/plurimath/asciimath/parse.rb +3 -2
  8. data/lib/plurimath/asciimath/transform.rb +47 -5
  9. data/lib/plurimath/latex/constants.rb +5 -1
  10. data/lib/plurimath/latex/parse.rb +20 -11
  11. data/lib/plurimath/latex/transform.rb +32 -14
  12. data/lib/plurimath/math/core.rb +212 -10
  13. data/lib/plurimath/math/formula.rb +154 -40
  14. data/lib/plurimath/math/function/abs.rb +28 -15
  15. data/lib/plurimath/math/function/bar.rb +5 -0
  16. data/lib/plurimath/math/function/base.rb +22 -2
  17. data/lib/plurimath/math/function/binary_function.rb +38 -12
  18. data/lib/plurimath/math/function/ceil.rb +24 -9
  19. data/lib/plurimath/math/function/color.rb +14 -0
  20. data/lib/plurimath/math/function/ddot.rb +6 -1
  21. data/lib/plurimath/math/function/deg.rb +4 -1
  22. data/lib/plurimath/math/function/det.rb +4 -1
  23. data/lib/plurimath/math/function/dim.rb +4 -1
  24. data/lib/plurimath/math/function/dot.rb +5 -0
  25. data/lib/plurimath/math/function/exp.rb +4 -1
  26. data/lib/plurimath/math/function/fenced.rb +51 -15
  27. data/lib/plurimath/math/function/floor.rb +24 -14
  28. data/lib/plurimath/math/function/font_style.rb +63 -8
  29. data/lib/plurimath/math/function/frac.rb +38 -18
  30. data/lib/plurimath/math/function/gcd.rb +4 -1
  31. data/lib/plurimath/math/function/glb.rb +8 -1
  32. data/lib/plurimath/math/function/hat.rb +16 -5
  33. data/lib/plurimath/math/function/hom.rb +4 -1
  34. data/lib/plurimath/math/function/inf.rb +16 -0
  35. data/lib/plurimath/math/function/int.rb +35 -9
  36. data/lib/plurimath/math/function/ker.rb +4 -1
  37. data/lib/plurimath/math/function/lcm.rb +17 -1
  38. data/lib/plurimath/math/function/left.rb +20 -2
  39. data/lib/plurimath/math/function/lg.rb +4 -1
  40. data/lib/plurimath/math/function/lim.rb +16 -0
  41. data/lib/plurimath/math/function/liminf.rb +4 -1
  42. data/lib/plurimath/math/function/limits.rb +29 -9
  43. data/lib/plurimath/math/function/limsup.rb +4 -1
  44. data/lib/plurimath/math/function/linebreak.rb +95 -0
  45. data/lib/plurimath/math/function/ln.rb +4 -1
  46. data/lib/plurimath/math/function/log.rb +27 -12
  47. data/lib/plurimath/math/function/longdiv.rb +19 -0
  48. data/lib/plurimath/math/function/lub.rb +4 -1
  49. data/lib/plurimath/math/function/max.rb +4 -1
  50. data/lib/plurimath/math/function/mbox.rb +8 -7
  51. data/lib/plurimath/math/function/menclose.rb +6 -0
  52. data/lib/plurimath/math/function/merror.rb +12 -3
  53. data/lib/plurimath/math/function/min.rb +4 -1
  54. data/lib/plurimath/math/function/mod.rb +48 -15
  55. data/lib/plurimath/math/function/msgroup.rb +32 -0
  56. data/lib/plurimath/math/function/msline.rb +10 -0
  57. data/lib/plurimath/math/function/multiscript.rb +27 -0
  58. data/lib/plurimath/math/function/nary.rb +128 -0
  59. data/lib/plurimath/math/function/norm.rb +24 -15
  60. data/lib/plurimath/math/function/obrace.rb +5 -0
  61. data/lib/plurimath/math/function/oint.rb +48 -20
  62. data/lib/plurimath/math/function/over.rb +29 -10
  63. data/lib/plurimath/math/function/overset.rb +19 -10
  64. data/lib/plurimath/math/function/phantom.rb +24 -6
  65. data/lib/plurimath/math/function/power.rb +19 -4
  66. data/lib/plurimath/math/function/power_base.rb +34 -33
  67. data/lib/plurimath/math/function/prod.rb +43 -23
  68. data/lib/plurimath/math/function/right.rb +20 -2
  69. data/lib/plurimath/math/function/root.rb +6 -0
  70. data/lib/plurimath/math/function/rule.rb +8 -1
  71. data/lib/plurimath/math/function/scarries.rb +14 -0
  72. data/lib/plurimath/math/function/semantics.rb +15 -0
  73. data/lib/plurimath/math/function/sqrt.rb +5 -0
  74. data/lib/plurimath/math/function/stackrel.rb +14 -0
  75. data/lib/plurimath/math/function/substack.rb +18 -51
  76. data/lib/plurimath/math/function/sum.rb +36 -12
  77. data/lib/plurimath/math/function/sup.rb +11 -2
  78. data/lib/plurimath/math/function/table/array.rb +1 -1
  79. data/lib/plurimath/math/function/table/matrix.rb +4 -0
  80. data/lib/plurimath/math/function/table.rb +62 -26
  81. data/lib/plurimath/math/function/td.rb +42 -4
  82. data/lib/plurimath/math/function/ternary_function.rb +48 -10
  83. data/lib/plurimath/math/function/text.rb +25 -3
  84. data/lib/plurimath/math/function/tilde.rb +5 -0
  85. data/lib/plurimath/math/function/tr.rb +29 -1
  86. data/lib/plurimath/math/function/ubrace.rb +5 -0
  87. data/lib/plurimath/math/function/unary_function.rb +115 -29
  88. data/lib/plurimath/math/function/underover.rb +27 -58
  89. data/lib/plurimath/math/function/underset.rb +25 -9
  90. data/lib/plurimath/math/function/vec.rb +45 -0
  91. data/lib/plurimath/math/function.rb +7 -5
  92. data/lib/plurimath/math/number.rb +12 -8
  93. data/lib/plurimath/math/symbol.rb +25 -13
  94. data/lib/plurimath/math.rb +1 -3
  95. data/lib/plurimath/mathml/parser.rb +6 -4
  96. data/lib/plurimath/mathml/transform.rb +26 -19
  97. data/lib/plurimath/omml/parser.rb +3 -3
  98. data/lib/plurimath/omml/transform.rb +34 -21
  99. data/lib/plurimath/setup/oga.rb +5 -0
  100. data/lib/plurimath/setup/opal.rb.erb +8 -0
  101. data/lib/plurimath/setup/ox.rb +5 -0
  102. data/lib/plurimath/unitsml.rb +2 -1
  103. data/lib/plurimath/utility.rb +77 -41
  104. data/lib/plurimath/version.rb +1 -1
  105. data/lib/plurimath/xml_engine/oga.rb +246 -0
  106. data/lib/plurimath/xml_engine/ox.rb +29 -0
  107. data/lib/plurimath/xml_engine.rb +6 -0
  108. data/lib/plurimath.rb +12 -2
  109. metadata +12 -3
  110. data/lib/plurimath/math/function/scarry.rb +0 -12
@@ -0,0 +1,246 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "plurimath/xml_engine"
4
+ require "corelib/array/pack" if RUBY_ENGINE == "opal"
5
+ require "oga"
6
+
7
+ module Plurimath
8
+ module XMLEngine
9
+ class Oga
10
+ class << self
11
+ def new_element(name)
12
+ data = ::Oga::XML::Element.new(name: name)
13
+ Node.new(data)
14
+ end
15
+
16
+ def dump(data, indent: nil)
17
+ Dumper.new(data, indent: indent).dump.out
18
+ end
19
+
20
+ def load(data)
21
+ data = ::Oga::XML::Parser.new(data, html: true).parse
22
+ if data.xml_declaration
23
+ Document.new(data)
24
+ else
25
+ Document.new(data).nodes.first
26
+ end
27
+ end
28
+
29
+ def is_xml_comment?(node)
30
+ node = node.unwrap if node.respond_to? :unwrap
31
+ node.is_a?(Comment)
32
+ end
33
+ end
34
+
35
+ # Create API compatible with Ox, per Plurimath usage
36
+ class Wrapper
37
+ def initialize(value)
38
+ @wrapped = value
39
+ end
40
+
41
+ def unwrap
42
+ @wrapped
43
+ end
44
+
45
+ def ==(other)
46
+ self.class == other.class &&
47
+ @wrapped.inspect == other.unwrap.inspect
48
+ end
49
+ end
50
+
51
+ class Node < Wrapper
52
+ # Ox removes text nodes that are whitespace-only.
53
+ # There exists a weird edge case on which Plurimath depends:
54
+ # <mi> <!-- xxx --> &#x3C0;<!--GREEK SMALL LETTER PI--> </mi>
55
+ # If the last text node of an element that does not contain other
56
+ # elements is a whitespace, it preserves it. The first one can be
57
+ # safely removed.
58
+ def nodes
59
+ children = @wrapped.children
60
+ length = children.length
61
+ preserve_last = true
62
+ children.map.with_index do |i,idx|
63
+ if preserve_last && idx == length-1 && i.is_a?(::Oga::XML::Text)
64
+ i.text
65
+ elsif i.is_a? ::Oga::XML::Text
66
+ remove_indentation(i)
67
+ elsif i.is_a? ::Oga::XML::Comment
68
+ Node.new(i)
69
+ else
70
+ preserve_last = false
71
+ Node.new(i)
72
+ end
73
+ end.compact
74
+ end
75
+
76
+ def [](attr)
77
+ attr = attr.to_s
78
+
79
+ @wrapped.attributes.each do |e|
80
+ return e.value if [e.name, e.name.split(":").last].include? attr
81
+ end
82
+
83
+ nil
84
+ end
85
+
86
+ def []=(attr, value)
87
+ # Here we tap into the internal representation due to some likely
88
+ # bug in Oga
89
+ attr = ::Oga::XML::Attribute.new(name: attr.to_s)
90
+ attr.element = @wrapped
91
+ attr.instance_variable_set(:@value, value.to_s)
92
+ attr.instance_variable_set(:@decoded, true)
93
+ @wrapped.attributes << attr
94
+ end
95
+
96
+ def <<(other)
97
+ other = other.unwrap if other.respond_to? :unwrap
98
+
99
+ case other
100
+ when String
101
+ text = other
102
+ # Here we tap into the internal representation due to some likely
103
+ # bug in Oga
104
+ other = ::Oga::XML::Text.new
105
+ other.instance_variable_set(:@from_plurimath, true)
106
+ other.instance_variable_set(:@text, text)
107
+ other.instance_variable_set(:@decoded, true)
108
+ end
109
+
110
+ @wrapped.children << other.dup
111
+ self
112
+ end
113
+
114
+ def attributes
115
+ @wrapped.attributes.to_h do |e|
116
+ [e.name.split(":").last, e.value]
117
+ end
118
+ end
119
+
120
+ def locate(xpath)
121
+ @wrapped.xpath(xpath).map do |i|
122
+ case i
123
+ when ::Oga::XML::Text
124
+ i.text
125
+ when ::Oga::XML::Attribute
126
+ i.value
127
+ else
128
+ Node.new(i)
129
+ end
130
+ end
131
+ end
132
+
133
+ def name
134
+ @wrapped.name
135
+ end
136
+
137
+ def name=(new_name)
138
+ @wrapped.name = new_name
139
+ end
140
+
141
+ private
142
+
143
+ def remove_indentation(text)
144
+ from_us = text.instance_variable_get(:@from_plurimath)
145
+ !from_us && text.text.strip == "" ? nil : text.text
146
+ end
147
+ end
148
+
149
+ class Document < Node
150
+ end
151
+
152
+ Comment = ::Oga::XML::Comment
153
+
154
+ # Dump the tree just as if we were Ox. This is a limited implementation.
155
+ class Dumper
156
+ def initialize(tree, indent: nil)
157
+ @tree = tree
158
+ @indent = indent
159
+ @depth = 0
160
+ @out = ""
161
+ end
162
+
163
+ def dump(node = @tree)
164
+ case node
165
+ when Node
166
+ nodes = node.nodes
167
+ if nodes.length == 0
168
+ line_break
169
+ @out += "<#{node.unwrap.name}#{dump_attrs(node)}/>"
170
+ else
171
+ line_break
172
+ @out += "<#{node.unwrap.name}#{dump_attrs(node)}>"
173
+ @depth += 1
174
+ nodes.each { |i| dump(i) }
175
+ @depth -= 1
176
+ line_break unless nodes.last.is_a?(::String)
177
+ @out += "</#{node.unwrap.name}>"
178
+ end
179
+ when ::String
180
+ @out += entities(node)
181
+ end
182
+
183
+ line_break if node.object_id == @tree.object_id
184
+
185
+ self
186
+ end
187
+
188
+ attr_reader :out
189
+
190
+ ORD_AMP="&".ord
191
+ ORD_LT="<".ord
192
+ ORD_GT=">".ord
193
+ ORD_APOS="'".ord
194
+ ORD_QUOT='"'.ord
195
+ ORD_NEWLINE="\n".ord
196
+ ORD_CARRIAGERETURN="\r".ord
197
+
198
+ def self.entities(text,attr=false)
199
+ text.to_s.chars.map(&:ord).map do |i|
200
+ if i == ORD_AMP
201
+ "&amp;"
202
+ elsif i == ORD_LT
203
+ "&lt;"
204
+ elsif i == ORD_GT
205
+ "&gt;"
206
+ elsif i == ORD_QUOT && attr
207
+ "&quot;"
208
+ elsif i == ORD_NEWLINE || i == ORD_CARRIAGERETURN
209
+ i.chr("utf-8")
210
+ elsif i < 0x20
211
+ "&#x#{i.to_s(16).rjust(4, "0")};"
212
+ else
213
+ i.chr("utf-8")
214
+ end
215
+ end.join
216
+ end
217
+
218
+ private
219
+
220
+ def dump_attrs(node)
221
+ node.unwrap.attributes.map do |i|
222
+ # Currently, this is not part of the contract. But in the future
223
+ # it may be needed to also handle namespaces:
224
+ #
225
+ # if i.namespace
226
+ # %{ #{i.namespace.name}:#{i.name}="#{attr_entities i.value}"}
227
+ %{ #{i.name}="#{attr_entities i.value}"}
228
+ end.join
229
+ end
230
+
231
+ def entities(text)
232
+ self.class.entities(text)
233
+ end
234
+
235
+ def attr_entities(text)
236
+ self.class.entities(text, true)
237
+ end
238
+
239
+ def line_break
240
+ @out += "\n"
241
+ @out += " " * (@indent * @depth) if @indent
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "plurimath/xml_engine"
4
+ require "ox"
5
+ Ox.default_options = { encoding: "UTF-8" }
6
+
7
+ module Plurimath
8
+ module XMLEngine
9
+ class Ox
10
+ class << self
11
+ def new_element(name)
12
+ ::Ox::Element.new(name)
13
+ end
14
+
15
+ def dump(data, **options)
16
+ ::Ox.dump(data, **options)
17
+ end
18
+
19
+ def load(data)
20
+ ::Ox.load(data, strip_namespace: true)
21
+ end
22
+
23
+ def is_xml_comment?(node)
24
+ node.is_a?(::Ox::Comment)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ module Plurimath
2
+ singleton_class.attr_accessor :xml_engine
3
+
4
+ module XMLEngine
5
+ end
6
+ end
data/lib/plurimath.rb CHANGED
@@ -1,4 +1,14 @@
1
- # frozen_string_literal: true
2
1
 
3
2
  require_relative "plurimath/version"
4
- require_relative "plurimath/math"
3
+
4
+ # Select an XML engine
5
+ if RUBY_ENGINE == 'opal'
6
+ require "plurimath/setup/oga"
7
+ require "plurimath/setup/opal"
8
+ elsif ENV['PLURIMATH_OGA']
9
+ require "plurimath/setup/oga"
10
+ else
11
+ require "plurimath/setup/ox"
12
+ end
13
+
14
+ require "plurimath/math"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plurimath
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-09-08 00:00:00.000000000 Z
11
+ date: 2023-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -49,6 +49,8 @@ files:
49
49
  - ".github/workflows/release.yml"
50
50
  - ".gitignore"
51
51
  - ".hound.yml"
52
+ - ".rspec"
53
+ - ".rspec-opal"
52
54
  - ".rubocop.yml"
53
55
  - AsciiMath-Supported-Data.adoc
54
56
  - CODE_OF_CONDUCT.md
@@ -133,6 +135,7 @@ files:
133
135
  - lib/plurimath/math/function/liminf.rb
134
136
  - lib/plurimath/math/function/limits.rb
135
137
  - lib/plurimath/math/function/limsup.rb
138
+ - lib/plurimath/math/function/linebreak.rb
136
139
  - lib/plurimath/math/function/ln.rb
137
140
  - lib/plurimath/math/function/log.rb
138
141
  - lib/plurimath/math/function/longdiv.rb
@@ -146,6 +149,7 @@ files:
146
149
  - lib/plurimath/math/function/msgroup.rb
147
150
  - lib/plurimath/math/function/msline.rb
148
151
  - lib/plurimath/math/function/multiscript.rb
152
+ - lib/plurimath/math/function/nary.rb
149
153
  - lib/plurimath/math/function/norm.rb
150
154
  - lib/plurimath/math/function/obrace.rb
151
155
  - lib/plurimath/math/function/oint.rb
@@ -159,7 +163,6 @@ files:
159
163
  - lib/plurimath/math/function/root.rb
160
164
  - lib/plurimath/math/function/rule.rb
161
165
  - lib/plurimath/math/function/scarries.rb
162
- - lib/plurimath/math/function/scarry.rb
163
166
  - lib/plurimath/math/function/sec.rb
164
167
  - lib/plurimath/math/function/sech.rb
165
168
  - lib/plurimath/math/function/semantics.rb
@@ -202,10 +205,16 @@ files:
202
205
  - lib/plurimath/omml.rb
203
206
  - lib/plurimath/omml/parser.rb
204
207
  - lib/plurimath/omml/transform.rb
208
+ - lib/plurimath/setup/oga.rb
209
+ - lib/plurimath/setup/opal.rb.erb
210
+ - lib/plurimath/setup/ox.rb
205
211
  - lib/plurimath/unicode.rb
206
212
  - lib/plurimath/unitsml.rb
207
213
  - lib/plurimath/utility.rb
208
214
  - lib/plurimath/version.rb
215
+ - lib/plurimath/xml_engine.rb
216
+ - lib/plurimath/xml_engine/oga.rb
217
+ - lib/plurimath/xml_engine/ox.rb
209
218
  - plurimath.gemspec
210
219
  homepage: https://github.com/plurimath/plurimath
211
220
  licenses:
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "unary_function"
4
-
5
- module Plurimath
6
- module Math
7
- module Function
8
- class Scarry < UnaryFunction
9
- end
10
- end
11
- end
12
- end