plurimath 0.10.7 → 0.11.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.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +3 -2
- data/README.adoc +343 -44
- data/lib/plurimath/asciimath/parse.rb +6 -2
- data/lib/plurimath/configuration.rb +17 -0
- data/lib/plurimath/deprecation.rb +81 -0
- data/lib/plurimath/errors/configuration_error.rb +27 -0
- data/lib/plurimath/errors/deprecation_error.rb +33 -0
- data/lib/plurimath/errors/error.rb +6 -0
- data/lib/plurimath/errors/formatter/unsupported_base.rb +1 -1
- data/lib/plurimath/errors/formatter/unsupported_locale.rb +18 -0
- data/lib/plurimath/errors/omml/unsupported_node_error.rb +1 -1
- data/lib/plurimath/errors/parse_error.rb +1 -1
- data/lib/plurimath/errors/parse_option_error.rb +34 -0
- data/lib/plurimath/formatter/numbers/base.rb +18 -8
- data/lib/plurimath/formatter/numbers/base_notation.rb +67 -0
- data/lib/plurimath/formatter/numbers/digit_sequence.rb +96 -0
- data/lib/plurimath/formatter/numbers/format_options.rb +141 -0
- data/lib/plurimath/formatter/numbers/fraction.rb +50 -93
- data/lib/plurimath/formatter/numbers/integer.rb +30 -6
- data/lib/plurimath/formatter/numbers/notation_renderer.rb +128 -0
- data/lib/plurimath/formatter/numbers/number_renderer.rb +66 -0
- data/lib/plurimath/formatter/numbers/parts.rb +69 -0
- data/lib/plurimath/formatter/numbers/parts_renderer.rb +30 -0
- data/lib/plurimath/formatter/numbers/precision_resolver.rb +54 -0
- data/lib/plurimath/formatter/numbers/sign_renderer.rb +28 -0
- data/lib/plurimath/formatter/numbers/significant.rb +77 -103
- data/lib/plurimath/formatter/numbers/source.rb +120 -0
- data/lib/plurimath/formatter/numbers/symbol_resolver.rb +55 -0
- data/lib/plurimath/formatter/numbers.rb +11 -0
- data/lib/plurimath/formatter/standard.rb +32 -42
- data/lib/plurimath/formatter/supported_locales.rb +27 -0
- data/lib/plurimath/formatter.rb +1 -2
- data/lib/plurimath/html/constants.rb +2 -0
- data/lib/plurimath/html/parse.rb +77 -14
- data/lib/plurimath/html/parser.rb +15 -3
- data/lib/plurimath/html/transform.rb +193 -91
- data/lib/plurimath/html/transform_utility.rb +61 -0
- data/lib/plurimath/html.rb +1 -0
- data/lib/plurimath/latex/parse.rb +7 -1
- data/lib/plurimath/latex/transform.rb +5 -5
- data/lib/plurimath/math/function/lim.rb +6 -0
- data/lib/plurimath/math/number.rb +8 -2
- data/lib/plurimath/math/symbols/cdot.rb +1 -1
- data/lib/plurimath/math/symbols/exclam.rb +1 -1
- data/lib/plurimath/math/symbols/minus.rb +1 -1
- data/lib/plurimath/math/symbols/percent.rb +1 -1
- data/lib/plurimath/math/symbols/pi.rb +1 -1
- data/lib/plurimath/math/symbols/slash.rb +1 -1
- data/lib/plurimath/math.rb +56 -8
- data/lib/plurimath/number_formatter.rb +57 -27
- data/lib/plurimath/unicode_math/parse.rb +7 -1
- data/lib/plurimath/unicode_math/transform.rb +2 -2
- data/lib/plurimath/version.rb +1 -1
- data/lib/plurimath.rb +23 -1
- metadata +21 -4
- data/lib/plurimath/formatter/number_formatter.rb +0 -115
- data/lib/plurimath/formatter/numeric_formatter.rb +0 -187
data/lib/plurimath/html/parse.rb
CHANGED
|
@@ -6,11 +6,12 @@ module Plurimath
|
|
|
6
6
|
rule(:space) { match["\s"].repeat(1) }
|
|
7
7
|
rule(:unary) { array_to_expression(Constants::UNARY_CLASSES, :unary) }
|
|
8
8
|
rule(:binary) { str("lim").as(:binary) }
|
|
9
|
+
rule(:linebreak) { parse_void_tag("br").as(:linebreak) }
|
|
9
10
|
rule(:sub_tag) { parse_sub_sup_tags("sub") }
|
|
10
11
|
rule(:sup_tag) { parse_sub_sup_tags("sup") }
|
|
11
12
|
|
|
12
13
|
rule(:mod) do
|
|
13
|
-
(
|
|
14
|
+
wrapped_tag(str("mod").as(:binary)) |
|
|
14
15
|
str("mod").as(:binary)
|
|
15
16
|
end
|
|
16
17
|
|
|
@@ -27,12 +28,12 @@ module Plurimath
|
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
rule(:open_paren) do
|
|
30
|
-
(
|
|
31
|
+
wrapped_tag(lparen) |
|
|
31
32
|
lparen
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
rule(:close_paren) do
|
|
35
|
-
(
|
|
36
|
+
wrapped_tag(rparen) |
|
|
36
37
|
rparen
|
|
37
38
|
end
|
|
38
39
|
|
|
@@ -57,12 +58,12 @@ module Plurimath
|
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
rule(:unary_functions) do
|
|
60
|
-
(
|
|
61
|
+
wrapped_tag(unary) |
|
|
61
62
|
unary
|
|
62
63
|
end
|
|
63
64
|
|
|
64
65
|
rule(:binary_functions) do
|
|
65
|
-
(
|
|
66
|
+
wrapped_tag(binary) |
|
|
66
67
|
binary
|
|
67
68
|
end
|
|
68
69
|
|
|
@@ -73,11 +74,11 @@ module Plurimath
|
|
|
73
74
|
|
|
74
75
|
rule(:symbol_text_or_tag) do
|
|
75
76
|
tag_parse |
|
|
76
|
-
|
|
77
|
-
(match["0-9"].repeat(1) >>
|
|
77
|
+
html_entity.as(:symbol) |
|
|
78
|
+
(match["0-9"].repeat(1) >> decimal_marker >> match["0-9"].repeat(1)).as(:number) |
|
|
78
79
|
match["0-9"].repeat(1).as(:number) |
|
|
79
80
|
match["a-zA-Z"].as(:text) |
|
|
80
|
-
match["^0-9a-zA-Z
|
|
81
|
+
match["^0-9a-zA-Z<>(){}\\[\\]\s"].as(:symbol)
|
|
81
82
|
end
|
|
82
83
|
|
|
83
84
|
rule(:intermediate_exp) do
|
|
@@ -85,6 +86,7 @@ module Plurimath
|
|
|
85
86
|
(symbol_text_or_tag.as(:sub_sup) >> sub_sup_tags) |
|
|
86
87
|
sub_sup |
|
|
87
88
|
parse_classes |
|
|
89
|
+
linebreak |
|
|
88
90
|
symbol_text_or_tag |
|
|
89
91
|
space
|
|
90
92
|
end
|
|
@@ -109,8 +111,9 @@ module Plurimath
|
|
|
109
111
|
rule(:tag_parse) do
|
|
110
112
|
parse_sub_sup_tags("table") |
|
|
111
113
|
parse_sub_sup_tags("tr") |
|
|
112
|
-
|
|
113
|
-
(
|
|
114
|
+
# Formula has no header-cell node; HTML <th> is parsed as Td.
|
|
115
|
+
parse_sub_sup_tags(%w[td th], "td") |
|
|
116
|
+
wrapped_tag(sequence.as(:sequence))
|
|
114
117
|
end
|
|
115
118
|
|
|
116
119
|
rule(:expression) do
|
|
@@ -136,15 +139,75 @@ module Plurimath
|
|
|
136
139
|
str(string).as(name)
|
|
137
140
|
end
|
|
138
141
|
|
|
139
|
-
def
|
|
142
|
+
def decimal_marker
|
|
143
|
+
str(Plurimath.configuration.decimal)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def parse_tag(opts, tag_name = nil, capture_name: nil)
|
|
140
147
|
tag = str("<")
|
|
141
148
|
tag = tag >> str("/") if opts == :close
|
|
142
|
-
|
|
149
|
+
name_expression = html_tag_name(tag_name)
|
|
150
|
+
name_expression = name_expression.capture(capture_name) if capture_name
|
|
151
|
+
tag = tag >> name_expression
|
|
152
|
+
tag = tag >> tag_attributes if opts == :open
|
|
143
153
|
tag >> str(">")
|
|
144
154
|
end
|
|
145
155
|
|
|
146
|
-
def
|
|
147
|
-
str("
|
|
156
|
+
def parse_void_tag(tag_name)
|
|
157
|
+
str("<") >> html_tag_name(tag_name) >> tag_attributes >> str(">")
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def html_entity
|
|
161
|
+
(str("&#x") >> match["0-9a-fA-F"].repeat(1) >> str(";")) |
|
|
162
|
+
(str("&#") >> match["0-9"].repeat(1) >> str(";")) |
|
|
163
|
+
(str("&") >> match["a-zA-Z"] >> match["a-zA-Z0-9"].repeat >> str(";"))
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def parse_sub_sup_tags(tag_names, transform_name = tag_names)
|
|
167
|
+
Array(tag_names).map do |tag_name|
|
|
168
|
+
parse_tag(:open, tag_name) >>
|
|
169
|
+
sequence.as(:"#{transform_name}_value") >>
|
|
170
|
+
parse_tag(:close, tag_name)
|
|
171
|
+
end.reduce(:|)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def wrapped_tag(expression)
|
|
175
|
+
scope do
|
|
176
|
+
parse_tag(:open, capture_name: :html_tag_name) >>
|
|
177
|
+
expression >>
|
|
178
|
+
matching_close_tag
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def matching_close_tag
|
|
183
|
+
dynamic do |_source, context|
|
|
184
|
+
parse_tag(:close, context.captures[:html_tag_name].to_s)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def html_tag_name(tag_name)
|
|
189
|
+
return match["a-zA-Z"] >> match["a-zA-Z0-9:._-"].repeat unless tag_name
|
|
190
|
+
|
|
191
|
+
case_insensitive_string(tag_name) >> tag_name_boundary
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def tag_name_boundary
|
|
195
|
+
match["\\s/>"].present?
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def tag_attributes
|
|
199
|
+
(quoted_attribute_value | match["^<>"]).repeat
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def quoted_attribute_value
|
|
203
|
+
(str('"') >> match['^"'].repeat >> str('"')) |
|
|
204
|
+
(str("'") >> match["^'"].repeat >> str("'"))
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def case_insensitive_string(value)
|
|
208
|
+
value.chars
|
|
209
|
+
.map { |char| char.match?(/[A-Za-z]/) ? match["#{char.downcase}#{char.upcase}"] : str(char) }
|
|
210
|
+
.reduce(:>>)
|
|
148
211
|
end
|
|
149
212
|
end
|
|
150
213
|
end
|
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
module Plurimath
|
|
6
6
|
class Html
|
|
7
7
|
class Parser
|
|
8
|
+
HTML_ENTITY = /&(?:#x[0-9a-f]+|#\d+|[a-z][a-z0-9]+);/i
|
|
9
|
+
|
|
8
10
|
attr_accessor :text
|
|
9
11
|
|
|
10
12
|
def initialize(text)
|
|
11
|
-
@text =
|
|
13
|
+
@text = text.to_s
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
def parse
|
|
15
|
-
nodes = Parse.new.parse(
|
|
17
|
+
nodes = Parse.new.parse(normalized_text)
|
|
16
18
|
nodes = JSON.parse(nodes.to_json, symbolize_names: true)
|
|
17
19
|
transformed_tree = Transform.new.apply(nodes)
|
|
18
20
|
return transformed_tree if transformed_tree.is_a?(Math::Formula)
|
|
19
21
|
|
|
20
22
|
Math::Formula.new(transformed_tree)
|
|
21
23
|
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def normalized_text
|
|
28
|
+
text.gsub(HTML_ENTITY) do |entity|
|
|
29
|
+
decoded_entity = Utility.html_entity_to_unicode(entity)
|
|
30
|
+
|
|
31
|
+
Utility.string_to_html_entity(decoded_entity)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
22
34
|
end
|
|
23
35
|
end
|
|
24
36
|
end
|
|
@@ -5,15 +5,28 @@ module Plurimath
|
|
|
5
5
|
class Transform < Parslet::Transform
|
|
6
6
|
rule(text: simple(:text)) { Math::Function::Text.new(text) }
|
|
7
7
|
rule(unary: simple(:unary)) { Utility.get_class(unary).new }
|
|
8
|
-
rule(symbol: simple(:symbol))
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
rule(number: simple(:number)) { Math::Number.new(number) }
|
|
8
|
+
rule(symbol: simple(:symbol)) { TransformUtility.symbol(symbol) }
|
|
9
|
+
rule(number: simple(:number)) { Math::Number.new(number) }
|
|
10
|
+
rule(linebreak: simple(:_linebreak)) { Math::Function::Linebreak.new }
|
|
12
11
|
rule(expression: simple(:exp)) { exp }
|
|
13
12
|
|
|
13
|
+
rule(linebreak: simple(:_linebreak),
|
|
14
|
+
expression: simple(:expr)) do
|
|
15
|
+
[
|
|
16
|
+
Math::Function::Linebreak.new,
|
|
17
|
+
expr,
|
|
18
|
+
]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
rule(linebreak: simple(:_linebreak),
|
|
22
|
+
expression: sequence(:expr)) do
|
|
23
|
+
[Math::Function::Linebreak.new] + expr
|
|
24
|
+
end
|
|
25
|
+
|
|
14
26
|
rule(expression: sequence(:exp)) { exp }
|
|
15
27
|
rule(sequence: simple(:sequence)) { sequence }
|
|
16
28
|
rule(tr_value: simple(:tr_value)) { Math::Function::Tr.new([tr_value]) }
|
|
29
|
+
rule(tr_value: sequence(:tr_value)) { Math::Function::Tr.new(tr_value) }
|
|
17
30
|
rule(td_value: simple(:td_value)) { Math::Function::Td.new([td_value]) }
|
|
18
31
|
rule(sequence: sequence(:sequence)) { sequence }
|
|
19
32
|
rule(td_value: sequence(:td_value)) { Math::Function::Td.new(td_value) }
|
|
@@ -71,6 +84,22 @@ module Plurimath
|
|
|
71
84
|
)
|
|
72
85
|
end
|
|
73
86
|
|
|
87
|
+
rule(td_value: simple(:td_value),
|
|
88
|
+
expression: simple(:expr)) do
|
|
89
|
+
[
|
|
90
|
+
Math::Function::Td.new([td_value]),
|
|
91
|
+
expr,
|
|
92
|
+
]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
rule(td_value: simple(:td_value),
|
|
96
|
+
expression: sequence(:expr)) do
|
|
97
|
+
expr.insert(
|
|
98
|
+
0,
|
|
99
|
+
Math::Function::Td.new([td_value]),
|
|
100
|
+
)
|
|
101
|
+
end
|
|
102
|
+
|
|
74
103
|
rule(unary_function: simple(:unary_function),
|
|
75
104
|
sequence: simple(:sequence)) do
|
|
76
105
|
Math::Formula.new(
|
|
@@ -104,14 +133,14 @@ module Plurimath
|
|
|
104
133
|
rule(symbol: simple(:symbol),
|
|
105
134
|
expression: simple(:expr)) do
|
|
106
135
|
[
|
|
107
|
-
|
|
136
|
+
TransformUtility.symbol(symbol),
|
|
108
137
|
expr,
|
|
109
138
|
]
|
|
110
139
|
end
|
|
111
140
|
|
|
112
141
|
rule(symbol: simple(:symbol),
|
|
113
142
|
expression: sequence(:expr)) do
|
|
114
|
-
[
|
|
143
|
+
[TransformUtility.symbol(symbol)] + expr
|
|
115
144
|
end
|
|
116
145
|
|
|
117
146
|
rule(number: simple(:number),
|
|
@@ -145,135 +174,208 @@ module Plurimath
|
|
|
145
174
|
rule(symbol: simple(:symbol),
|
|
146
175
|
parse_parenthesis: simple(:parse_paren)) do
|
|
147
176
|
[
|
|
148
|
-
|
|
177
|
+
TransformUtility.symbol(symbol),
|
|
149
178
|
parse_paren,
|
|
150
179
|
]
|
|
151
180
|
end
|
|
152
181
|
|
|
153
182
|
rule(sub_sup: simple(:sub_sup),
|
|
154
183
|
sub_value: simple(:sub_value)) do
|
|
155
|
-
|
|
156
|
-
sub_sup.parameter_one = sub_value
|
|
157
|
-
sub_sup
|
|
158
|
-
else
|
|
159
|
-
Math::Function::Base.new(
|
|
160
|
-
sub_sup,
|
|
161
|
-
sub_value,
|
|
162
|
-
)
|
|
163
|
-
end
|
|
184
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value)
|
|
164
185
|
end
|
|
165
186
|
|
|
166
187
|
rule(sub_sup: simple(:sub_sup),
|
|
167
188
|
sub_value: sequence(:sub_value)) do
|
|
168
|
-
|
|
169
|
-
sub_sup.parameter_one = Utility.filter_values(sub_value)
|
|
170
|
-
sub_sup
|
|
171
|
-
else
|
|
172
|
-
Math::Function::Base.new(
|
|
173
|
-
sub_sup,
|
|
174
|
-
Utility.filter_values(sub_value),
|
|
175
|
-
)
|
|
176
|
-
end
|
|
189
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value)
|
|
177
190
|
end
|
|
178
191
|
|
|
179
192
|
rule(sub_sup: simple(:sub_sup),
|
|
180
193
|
sup_value: simple(:sup_value)) do
|
|
181
|
-
|
|
182
|
-
sub_sup.parameter_two = sup_value
|
|
183
|
-
sub_sup
|
|
184
|
-
else
|
|
185
|
-
Math::Function::Power.new(
|
|
186
|
-
sub_sup,
|
|
187
|
-
sup_value,
|
|
188
|
-
)
|
|
189
|
-
end
|
|
194
|
+
TransformUtility.sub_sup_value(sub_sup, sup_value: sup_value)
|
|
190
195
|
end
|
|
191
196
|
|
|
192
197
|
rule(sub_sup: simple(:sub_sup),
|
|
193
198
|
sup_value: sequence(:sup_value)) do
|
|
194
|
-
|
|
195
|
-
sub_sup.parameter_two = Utility.filter_values(sup_value)
|
|
196
|
-
sub_sup
|
|
197
|
-
else
|
|
198
|
-
Math::Function::Power.new(
|
|
199
|
-
sub_sup,
|
|
200
|
-
Utility.filter_values(sup_value),
|
|
201
|
-
)
|
|
202
|
-
end
|
|
199
|
+
TransformUtility.sub_sup_value(sub_sup, sup_value: sup_value)
|
|
203
200
|
end
|
|
204
201
|
|
|
205
202
|
rule(sub_sup: simple(:sub_sup),
|
|
206
203
|
sub_value: simple(:sub_value),
|
|
207
204
|
sup_value: simple(:sup_value)) do
|
|
208
|
-
|
|
209
|
-
sub_sup.parameter_one = sub_value
|
|
210
|
-
sub_sup.parameter_two = sup_value
|
|
211
|
-
sub_sup
|
|
212
|
-
else
|
|
213
|
-
Math::Function::PowerBase.new(
|
|
214
|
-
sub_sup,
|
|
215
|
-
sub_value,
|
|
216
|
-
sup_value,
|
|
217
|
-
)
|
|
218
|
-
end
|
|
205
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value)
|
|
219
206
|
end
|
|
220
207
|
|
|
221
208
|
rule(sub_sup: simple(:sub_sup),
|
|
222
209
|
sub_value: simple(:sub_value),
|
|
223
210
|
sup_value: sequence(:sup_value)) do
|
|
224
|
-
|
|
225
|
-
sub_sup.parameter_one = sub_value
|
|
226
|
-
sub_sup.parameter_two = Utility.filter_values(sup_value)
|
|
227
|
-
sub_sup
|
|
228
|
-
else
|
|
229
|
-
Math::Function::PowerBase.new(
|
|
230
|
-
sub_sup,
|
|
231
|
-
sub_value,
|
|
232
|
-
Utility.filter_values(sup_value),
|
|
233
|
-
)
|
|
234
|
-
end
|
|
211
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value)
|
|
235
212
|
end
|
|
236
213
|
|
|
237
214
|
rule(sub_sup: simple(:sub_sup),
|
|
238
215
|
sub_value: sequence(:sub_value),
|
|
239
216
|
sup_value: simple(:sup_value)) do
|
|
240
|
-
|
|
241
|
-
sub_sup.parameter_one = Utility.filter_values(sub_value)
|
|
242
|
-
sub_sup.parameter_two = sup_value
|
|
243
|
-
sub_sup
|
|
244
|
-
else
|
|
245
|
-
Math::Function::PowerBase.new(
|
|
246
|
-
sub_sup,
|
|
247
|
-
Utility.filter_values(sub_value),
|
|
248
|
-
sup_value,
|
|
249
|
-
)
|
|
250
|
-
end
|
|
217
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value)
|
|
251
218
|
end
|
|
252
219
|
|
|
253
220
|
rule(sub_sup: simple(:sub_sup),
|
|
254
221
|
sub_value: sequence(:sub_value),
|
|
255
222
|
sup_value: sequence(:sup_value)) do
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
223
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Parslet emits separate shapes for each sub/sup value combination and
|
|
227
|
+
# trailing expression form. Keep this cluster mechanical: build the
|
|
228
|
+
# sub/sup node, then append the remaining expression in input order.
|
|
229
|
+
rule(sub_sup: simple(:sub_sup),
|
|
230
|
+
sup_value: sequence(:sup_value),
|
|
231
|
+
expression: simple(:expression)) do
|
|
232
|
+
TransformUtility.append_expression(
|
|
233
|
+
TransformUtility.sub_sup_value(sub_sup, sup_value: sup_value),
|
|
234
|
+
expression,
|
|
235
|
+
)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
rule(sub_sup: simple(:sub_sup),
|
|
239
|
+
sub_value: simple(:sub_value),
|
|
240
|
+
expression: simple(:expression)) do
|
|
241
|
+
TransformUtility.append_expression(
|
|
242
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value),
|
|
243
|
+
expression,
|
|
244
|
+
)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
rule(sub_sup: simple(:sub_sup),
|
|
248
|
+
sub_value: simple(:sub_value),
|
|
249
|
+
expression: sequence(:expression)) do
|
|
250
|
+
TransformUtility.append_expression(
|
|
251
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value),
|
|
252
|
+
expression,
|
|
253
|
+
)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
rule(sub_sup: simple(:sub_sup),
|
|
257
|
+
sub_value: sequence(:sub_value),
|
|
258
|
+
expression: simple(:expression)) do
|
|
259
|
+
TransformUtility.append_expression(
|
|
260
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value),
|
|
261
|
+
expression,
|
|
262
|
+
)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
rule(sub_sup: simple(:sub_sup),
|
|
266
|
+
sub_value: sequence(:sub_value),
|
|
267
|
+
expression: sequence(:expression)) do
|
|
268
|
+
TransformUtility.append_expression(
|
|
269
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value),
|
|
270
|
+
expression,
|
|
271
|
+
)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
rule(sub_sup: simple(:sub_sup),
|
|
275
|
+
sup_value: simple(:sup_value),
|
|
276
|
+
expression: simple(:expression)) do
|
|
277
|
+
TransformUtility.append_expression(
|
|
278
|
+
TransformUtility.sub_sup_value(sub_sup, sup_value: sup_value),
|
|
279
|
+
expression,
|
|
280
|
+
)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
rule(sub_sup: simple(:sub_sup),
|
|
284
|
+
sup_value: simple(:sup_value),
|
|
285
|
+
expression: sequence(:expression)) do
|
|
286
|
+
TransformUtility.append_expression(
|
|
287
|
+
TransformUtility.sub_sup_value(sub_sup, sup_value: sup_value),
|
|
288
|
+
expression,
|
|
289
|
+
)
|
|
267
290
|
end
|
|
268
291
|
|
|
269
292
|
rule(sub_sup: simple(:sub_sup),
|
|
270
293
|
sup_value: sequence(:sup_value),
|
|
294
|
+
expression: sequence(:expression)) do
|
|
295
|
+
TransformUtility.append_expression(
|
|
296
|
+
TransformUtility.sub_sup_value(sub_sup, sup_value: sup_value),
|
|
297
|
+
expression,
|
|
298
|
+
)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
rule(sub_sup: simple(:sub_sup),
|
|
302
|
+
sub_value: simple(:sub_value),
|
|
303
|
+
sup_value: simple(:sup_value),
|
|
271
304
|
expression: simple(:expression)) do
|
|
272
|
-
|
|
273
|
-
sub_sup,
|
|
274
|
-
|
|
305
|
+
TransformUtility.append_expression(
|
|
306
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value),
|
|
307
|
+
expression,
|
|
308
|
+
)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
rule(sub_sup: simple(:sub_sup),
|
|
312
|
+
sub_value: simple(:sub_value),
|
|
313
|
+
sup_value: simple(:sup_value),
|
|
314
|
+
expression: sequence(:expression)) do
|
|
315
|
+
TransformUtility.append_expression(
|
|
316
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value),
|
|
317
|
+
expression,
|
|
318
|
+
)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
rule(sub_sup: simple(:sub_sup),
|
|
322
|
+
sub_value: simple(:sub_value),
|
|
323
|
+
sup_value: sequence(:sup_value),
|
|
324
|
+
expression: simple(:expression)) do
|
|
325
|
+
TransformUtility.append_expression(
|
|
326
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value),
|
|
327
|
+
expression,
|
|
328
|
+
)
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
rule(sub_sup: simple(:sub_sup),
|
|
332
|
+
sub_value: simple(:sub_value),
|
|
333
|
+
sup_value: sequence(:sup_value),
|
|
334
|
+
expression: sequence(:expression)) do
|
|
335
|
+
TransformUtility.append_expression(
|
|
336
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value),
|
|
337
|
+
expression,
|
|
338
|
+
)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
rule(sub_sup: simple(:sub_sup),
|
|
342
|
+
sub_value: sequence(:sub_value),
|
|
343
|
+
sup_value: simple(:sup_value),
|
|
344
|
+
expression: simple(:expression)) do
|
|
345
|
+
TransformUtility.append_expression(
|
|
346
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value),
|
|
347
|
+
expression,
|
|
348
|
+
)
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
rule(sub_sup: simple(:sub_sup),
|
|
352
|
+
sub_value: sequence(:sub_value),
|
|
353
|
+
sup_value: simple(:sup_value),
|
|
354
|
+
expression: sequence(:expression)) do
|
|
355
|
+
TransformUtility.append_expression(
|
|
356
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value),
|
|
357
|
+
expression,
|
|
358
|
+
)
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
rule(sub_sup: simple(:sub_sup),
|
|
362
|
+
sub_value: sequence(:sub_value),
|
|
363
|
+
sup_value: sequence(:sup_value),
|
|
364
|
+
expression: simple(:expression)) do
|
|
365
|
+
TransformUtility.append_expression(
|
|
366
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value),
|
|
367
|
+
expression,
|
|
368
|
+
)
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
rule(sub_sup: simple(:sub_sup),
|
|
372
|
+
sub_value: sequence(:sub_value),
|
|
373
|
+
sup_value: sequence(:sup_value),
|
|
374
|
+
expression: sequence(:expression)) do
|
|
375
|
+
TransformUtility.append_expression(
|
|
376
|
+
TransformUtility.sub_sup_value(sub_sup, sub_value: sub_value, sup_value: sup_value),
|
|
377
|
+
expression,
|
|
275
378
|
)
|
|
276
|
-
[power, expression]
|
|
277
379
|
end
|
|
278
380
|
|
|
279
381
|
rule(lparen: simple(:lparen),
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Plurimath
|
|
4
|
+
class Html
|
|
5
|
+
module TransformUtility
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
HTML_ENTITY = /\A&(?:#x[0-9a-f]+|#\d+|[a-z][a-z0-9]+);\z/i
|
|
9
|
+
|
|
10
|
+
def symbol(symbol)
|
|
11
|
+
Utility.symbols_class(normalize_symbol(symbol), lang: :html)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def append_expression(value, expression)
|
|
15
|
+
return [value] + expression if expression.is_a?(Array)
|
|
16
|
+
|
|
17
|
+
[value, expression]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def sub_sup_value(sub_sup, sub_value: nil, sup_value: nil)
|
|
21
|
+
normalized_sub_value = normalize_sub_sup_value(sub_value)
|
|
22
|
+
normalized_sup_value = normalize_sub_sup_value(sup_value)
|
|
23
|
+
|
|
24
|
+
if Utility.sub_sup_method?(sub_sup)
|
|
25
|
+
sub_sup.parameter_one = normalized_sub_value if normalized_sub_value
|
|
26
|
+
sub_sup.parameter_two = normalized_sup_value if normalized_sup_value
|
|
27
|
+
sub_sup
|
|
28
|
+
elsif normalized_sub_value && normalized_sup_value
|
|
29
|
+
Math::Function::PowerBase.new(
|
|
30
|
+
sub_sup,
|
|
31
|
+
normalized_sub_value,
|
|
32
|
+
normalized_sup_value,
|
|
33
|
+
)
|
|
34
|
+
elsif normalized_sup_value
|
|
35
|
+
Math::Function::Power.new(
|
|
36
|
+
sub_sup,
|
|
37
|
+
normalized_sup_value,
|
|
38
|
+
)
|
|
39
|
+
else
|
|
40
|
+
Math::Function::Base.new(
|
|
41
|
+
sub_sup,
|
|
42
|
+
normalized_sub_value,
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def normalize_sub_sup_value(value)
|
|
48
|
+
return Utility.filter_values(value) if value.is_a?(Array)
|
|
49
|
+
|
|
50
|
+
value
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def normalize_symbol(symbol)
|
|
54
|
+
symbol = symbol.to_s
|
|
55
|
+
return symbol if symbol.match?(HTML_ENTITY)
|
|
56
|
+
|
|
57
|
+
Utility.string_to_html_entity(symbol)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/lib/plurimath/html.rb
CHANGED
|
@@ -101,7 +101,7 @@ module Plurimath
|
|
|
101
101
|
(rparen.absent? >> symbol_class_commands) |
|
|
102
102
|
(slash >> math_operators_classes) |
|
|
103
103
|
match["a-zA-Z"].as(:symbols) |
|
|
104
|
-
(match["0-9"].repeat(0) >>
|
|
104
|
+
(match["0-9"].repeat(0) >> decimal_marker.maybe >> match["0-9"].repeat(1)).as(:number) |
|
|
105
105
|
match["0-9"].repeat(1).as(:number) |
|
|
106
106
|
(str("\\\\").as("\\\\") >> match(/\s/).repeat) |
|
|
107
107
|
str("\\ ").as(:space) |
|
|
@@ -197,6 +197,12 @@ module Plurimath
|
|
|
197
197
|
end
|
|
198
198
|
end
|
|
199
199
|
|
|
200
|
+
def decimal_marker
|
|
201
|
+
# Latex::Parser entity-encodes input before Parslet sees it, so
|
|
202
|
+
# non-ASCII locale markers must match that encoded parser input.
|
|
203
|
+
str(Utility.string_to_html_entity(Plurimath.configuration.decimal))
|
|
204
|
+
end
|
|
205
|
+
|
|
200
206
|
def hash_to_expression(hash)
|
|
201
207
|
@@expression ||= hash.reduce do |expression, (key, value)|
|
|
202
208
|
if expression.is_a?(Array)
|