plurimath 0.8.11 → 0.8.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2125384d29ad98d919d7fd71cebaf3e5fdc6ffc1aa8df386f3b63f20754ae6bb
4
- data.tar.gz: 64a002bc99ed60eada7e7a59df1f0bfa083eaa4427efdb0ec2fbe615db33f851
3
+ metadata.gz: 4c68ac69d198de23d6a021dd5d33b68cd942f95de739f92d870e70826445da59
4
+ data.tar.gz: 361960657e4a8a5e38a11b237744e33b9f7aa5c5eced8582f9ec9de1ca95a7b0
5
5
  SHA512:
6
- metadata.gz: a88aae5ca0beb6e36de8f3e025241cb291cb2d8c44faeeb2325ea4a2276ca6c93b32176484d7698a6818cf5f05e76f3a8b0fad829ed657f417a7fda183726ba9
7
- data.tar.gz: fb521143940cab36ef15320d65aad971e56e150776229809fa9bdd1014847ac36cfef09fc55f2e182338ee2e1e2a6d13f086eb0a285d01e51b847df1c07cbe53
6
+ metadata.gz: 8e5af5caafefef2bde39dd2330b8291bce8a3831f891141360fb5b15c6c170576023551d3aa284b08026ae2a70d67ff43a268c12002502b72387521fde0c8b78
7
+ data.tar.gz: 34f049ad3c1c8ce77b9abfe0def2c29ca20c06876b0ed81f92096837d10d0e1a2fd8bf51cb5c99b73e6eb3733f7a6635ab8200406cd71cbc8278c0faaa5ce672
data/README.adoc CHANGED
@@ -61,16 +61,91 @@ Or install it yourself with:
61
61
  $ gem install plurimath
62
62
  ----
63
63
 
64
- == Usage
64
+ == Command Line Interface (CLI) usage
65
+
66
+ === General
67
+
68
+ Plurimath provides a Command Line Interface (CLI) tool for converting between
69
+ different math formats.
70
+
71
+ NOTE: Before continuing please ensure you have the gem installed.
72
+
73
+ To convert math equations between formats, use the following command followed by
74
+ appropriate options.
75
+
76
+ [source,bash]
77
+ ----
78
+ plurimath convert [options]
79
+ ----
80
+
81
+ Options available are:
82
+
83
+ `-i`, `--input <INPUT>`::
84
+ Specifies the input math equation. Should be provided within double quotes.
85
+
86
+ `-f`, `--input-format <FORMAT>`::
87
+ Specifies the input format of the equation. Defaults to `asciimath`.
88
+
89
+ `-p`, `--file-path <FILE_PATH>`::
90
+ Reads input from a file instead of the command line input. Use this for larger
91
+ inputs or when input contains special characters.
92
+
93
+ `-t`, `--output-format <FORMAT>`::
94
+ Specifies the output format type. Defaults to `mathml`.
95
+
96
+ `-m`, `--math-rendering`::
97
+ Renders the converted equation as a math zone display tree. Boolean option
98
+ (`true`, `false`).
99
+
100
+ `-d`, `--display-style`::
101
+ Specifies the DisplayStyle for OMML and MathML outputs only. Boolean option
102
+ (`true`, `false`).
103
+
104
+ `-s`, `--split-on-linebreak`::
105
+ Splits MathML and OMML output into multiple equations. Boolean option (`true`,
106
+ `false`).
107
+
108
+
109
+ === Convert an AsciiMath equation to MathML
110
+
111
+ [source,bash]
112
+ ----
113
+ plurimath convert -i "sqrt(x^2 + y^2)" -f asciimath -t mathml
114
+ ----
115
+
116
+ === Convert an OMML equation to MathML with DisplayStyle
117
+
118
+ [source,bash]
119
+ ----
120
+ plurimath convert -i "equation" -f omml -t mathml -d true
121
+ ----
122
+
123
+ === Convert equations from a file and output as UnicodeMath
124
+
125
+ [source,bash]
126
+ ----
127
+ plurimath convert -e <file_path> -t unicodemath
128
+ ----
129
+
130
+ For more detailed information and additional options, use:
131
+
132
+ [source,bash]
133
+ ----
134
+ plurimath help convert
135
+ ----
136
+
137
+
138
+ == Ruby API
139
+
65
140
 
66
141
  The central data model in Plurimath is the `Plurimath::Formula` class, which
67
142
  allows you to transform any math representation language into any other
68
143
  representation language.
69
144
 
70
145
 
71
- === Conversion Examples
146
+ === Conversion examples
72
147
 
73
- ==== AsciiMath Formula Example
148
+ ==== AsciiMath Formula example
74
149
 
75
150
  [source,ruby]
76
151
  ----
@@ -78,7 +153,7 @@ asciimath = "sin(1)"
78
153
  formula = Plurimath::Math.parse(asciimath, :asciimath)
79
154
  ----
80
155
 
81
- ==== MathML Formula Example
156
+ ==== MathML Formula example
82
157
 
83
158
  [source,ruby]
84
159
  ----
@@ -93,7 +168,7 @@ MATHML
93
168
  formula = Plurimath::Math.parse(mathml, :mathml)
94
169
  ----
95
170
 
96
- ==== LaTeX Formula Example
171
+ ==== LaTeX Formula example
97
172
 
98
173
  [source,ruby]
99
174
  ----
@@ -101,7 +176,7 @@ latex = "\\sin{1}"
101
176
  formula = Plurimath::Math.parse(latex, :latex)
102
177
  ----
103
178
 
104
- ==== UnicodeMath Formula Example
179
+ ==== UnicodeMath Formula example
105
180
 
106
181
  [source,ruby]
107
182
  ----
@@ -109,7 +184,7 @@ unicodemath = "sin(1)"
109
184
  formula = Plurimath::Math.parse(unicodemath, :unicodemath)
110
185
  ----
111
186
 
112
- ==== OMML Formula Example
187
+ ==== OMML Formula example
113
188
 
114
189
  [source,ruby]
115
190
  ----
@@ -137,13 +212,14 @@ OMML
137
212
  formula = Plurimath::Math.parse(omml, :omml)
138
213
  ----
139
214
 
140
- === Converting to Other Formats
215
+
216
+ === Converting to other formats
141
217
 
142
218
  Once you have a `Plurimath::Math::Formula` object, you can convert it to
143
219
  AsciiMath, MathML, LaTeX, UnicodeMath, or OMML by calling the respective
144
220
  conversion function on the `Formula` object.
145
221
 
146
- ==== AsciiMath Output Conversion
222
+ ==== AsciiMath output conversion
147
223
 
148
224
  [source,ruby]
149
225
  ----
@@ -157,7 +233,7 @@ that LaTeX does. During conversion from LaTeX to AsciiMath, if a symbol is not
157
233
  supported in AsciiMath, the LaTeX symbol will be returned.
158
234
 
159
235
 
160
- ==== LaTeX Output Conversion
236
+ ==== LaTeX output conversion
161
237
 
162
238
  [source,ruby]
163
239
  ----
@@ -165,7 +241,7 @@ formula.to_latex
165
241
  # => "\\sin1"
166
242
  ----
167
243
 
168
- ==== MathML Output Conversion
244
+ ==== MathML output conversion
169
245
 
170
246
  [source,ruby]
171
247
  ----
@@ -173,7 +249,7 @@ formula.to_mathml
173
249
  # => "<math xmlns='http://www.w3.org/1998/Math/MathML'><mstyle displaystyle='true'><mi>sin</mi><mn>1</mn></mstyle></math>"
174
250
  ----
175
251
 
176
- ==== UnicodeMath Output Conversion
252
+ ==== UnicodeMath output conversion
177
253
 
178
254
  [source,ruby]
179
255
  ----
@@ -181,7 +257,7 @@ formula.to_unicodemath
181
257
  # => "sin(1)"
182
258
  ----
183
259
 
184
- ==== OMML Output Conversion
260
+ ==== OMML output conversion
185
261
 
186
262
  [source,ruby]
187
263
  ----
@@ -189,7 +265,8 @@ formula.to_omml
189
265
  # => "<m:oMathPara xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"><m:oMath><m:f><m:fPr><m:ctrlPr /></m:fPr><m:num><m:r><m:t>sin</m:t></m:r></m:num><m:den><m:r><m:t>1</m:t></m:r></m:den></m:f></m:oMath></m:oMathPara>"
190
266
  ----
191
267
 
192
- == Handling Complex Mathematical Expressions
268
+
269
+ ==== Complex mathematical expressions
193
270
 
194
271
  Plurimath is capable of handling complex mathematical expressions with nested
195
272
  functions and operators.
@@ -197,9 +274,7 @@ functions and operators.
197
274
  This feature is particularly useful for application that requires consistent and
198
275
  accurate conversion of intricate mathematical content.
199
276
 
200
- === Example of a Complex Expression
201
-
202
- Consider the following complex LaTeX expression:
277
+ Example. Consider the following complex LaTeX expression:
203
278
 
204
279
  [source,latex]
205
280
  ----
@@ -232,13 +307,14 @@ omml = formula.to_omml
232
307
 
233
308
 
234
309
 
310
+ == Math parse trees
235
311
 
236
- == Displaying the Math Parse Tree
312
+ === General
237
313
 
238
314
  Plurimath allows you to display the math parse tree both as `Formula` objects
239
315
  and in the math language of expression.
240
316
 
241
- === Displaying as Formula Objects
317
+ === Displaying as Formula objects
242
318
 
243
319
  You can display the parse tree as `Formula` objects to understand the structure
244
320
  of the parsed mathematical expression.
@@ -246,14 +322,11 @@ of the parsed mathematical expression.
246
322
  [source,ruby]
247
323
  ----
248
324
  formula = Plurimath::Math.parse("sin(1)", :asciimath)
249
- formula.to_display(:asciimath)
250
- # |_ Math zone
251
- # |_ "sin(1)"
252
- # |_ "sin" function apply
253
- # |_ "1" argument
325
+ formula.to_display(:formula)
326
+ # ...
254
327
  ----
255
328
 
256
- === Displaying in the Math Language of Expression
329
+ === Displaying in the math language of expression
257
330
 
258
331
  You can also display the parse tree in the math language of expression to see
259
332
  how the expression is represented in that language.
@@ -261,11 +334,25 @@ how the expression is represented in that language.
261
334
  [source,ruby]
262
335
  ----
263
336
  formula = Plurimath::Math.parse("sin(1)", :asciimath)
337
+ formula.to_display(:asciimath)
338
+ # |_ Math zone
339
+ # |_ "sin(1)"
340
+ # |_ "sin" function apply
341
+ # |_ "1" argument
342
+
264
343
  formula.to_display(:latex)
265
344
  # |_ Math zone
266
345
  # |_ "\\sin1"
267
346
  # |_ "sin" function apply
268
347
  # |_ "1" argument
348
+
349
+ formula.to_display(:mathml)
350
+ # |_ Math zone
351
+ # |_ "<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mstyle displaystyle="true"><mrow><mi>sin</mi><mrow><mo>(</mo><mn>1</mn><mo>)</mo></mrow></mrow></mstyle></math>"
352
+ # |_ "<mrow><mi>sin</mi><mrow><mo>(</mo><mn>1</mn><mo>)</mo></mrow></mrow>" function apply
353
+ # |_ "sin" function name
354
+ # |_ "<mrow><mo>(</mo><mn>1</mn><mo>)</mo></mrow>" argument
355
+ # |_ "<mtext>1</mtext>" text
269
356
  ----
270
357
 
271
358
  // == Integration
@@ -311,11 +398,11 @@ h = 6.62607015 xx 10^(-34) "unitsml(kg*m^2*s^(-1))"
311
398
 
312
399
  ==== Step-by-Step Customization
313
400
 
314
- . **Parse the UnitsML Expression**
315
- . **Customize and Convert to AsciiMath**
316
- . **Customize and Convert to MathML**
317
- . **Customize and Convert to UnicodeMath**
318
- . **Customize and Convert to OMML**
401
+ . Parse the UnitsML Expression
402
+ . Customize and Convert to AsciiMath
403
+ . Customize and Convert to MathML
404
+ . Customize and Convert to UnicodeMath
405
+ . Customize and Convert to OMML
319
406
 
320
407
  ==== Parse the UnitsML Expression
321
408
 
@@ -341,7 +428,7 @@ puts asciimath
341
428
  # Output: 'h = 6.62607015 xx 10^(-34) "unitsml(kg*m^2*s^(-1))"'
342
429
  ----
343
430
 
344
- ==== Customize and Convert to MathML
431
+ ==== Customize and convert to MathML
345
432
 
346
433
  To customize the MathML output, you can use additional attributes and options:
347
434
 
@@ -353,7 +440,7 @@ puts mathml
353
440
  # Output: "<math xmlns='http://www.w3.org/1998/Math/MathML'><mrow><mi>h</mi><mo>=</mo><mn>6.62607015</mn><mo>×</mo><msup><mn>10</mn><mrow><mo>−</mo><mn>34</mn></mrow></msup><mtext>kg·m²·s⁻¹</mtext></mrow></math>"
354
441
  ----
355
442
 
356
- ==== Customize and Convert to UnicodeMath
443
+ ==== Customize and convert to UnicodeMath
357
444
 
358
445
  Similarly, customize the UnicodeMath output:
359
446
 
@@ -365,7 +452,7 @@ puts unicodemath
365
452
  # Output: 'h = 6.62607015 × 10^(−34) kg·m²·s⁻¹'
366
453
  ----
367
454
 
368
- ==== Customize and Convert to OMML
455
+ ==== Customize and convert to OMML
369
456
 
370
457
  For OMML output, you can customize the XML structure:
371
458
 
@@ -377,7 +464,7 @@ puts omml
377
464
  # Output: "<m:oMathPara xmlns:m='http://schemas.openxmlformats.org/officeDocument/2006/math'><m:oMath><m:r><m:t>h</m:t></m:r><m:r><m:t>=</m:t></m:r><m:r><m:t>6.62607015</m:t></m:r><m:r><m:t>×</m:t></m:r><m:sSup><m:sSupPr><m:ctrlPr /></m:sSupPr><m:e><m:r><m:t>10</m:t></m:r></m:e><m:sup><m:r><m:t>−34</m:t></m:r></m:sup></m:sSup><m:r><m:t>kg·m²·s⁻¹</m:t></m:r></m:oMath></m:oMathPara>"
378
465
  ----
379
466
 
380
- === Complete Example Code with Customization
467
+ === Complete example code with customization
381
468
 
382
469
  Here's the complete code for parsing, converting, and customizing the UnitsML
383
470
  expression between different formats:
@@ -434,7 +521,7 @@ as a text string of `"__{symbol-name}"`. Plurimath can recognize it, but other
434
521
  renderers or processors would treat it as a single symbol, which is accurate.
435
522
 
436
523
 
437
- === Example of Compatibility Wrapper
524
+ === Usage of the compatibility wrapper
438
525
 
439
526
  For a symbol like `backepsilon`.
440
527
 
@@ -466,12 +553,13 @@ In MathML:
466
553
  <mi>∍</mi>
467
554
  ----
468
555
 
469
- == XML Engines
470
556
 
471
- **Plurimath** supports two XML engines:
557
+ == XML engines
558
+
559
+ Plurimath supports two XML engines:
472
560
 
561
+ . **Ox**: (default) A fast XML parser
473
562
  . **Oga**: A pure Ruby XML parser
474
- . **Ox**: A fast XML parser
475
563
 
476
564
  By default, **Ox** is used.
477
565
 
@@ -479,12 +567,13 @@ To switch to **Oga**, use the following syntax:
479
567
 
480
568
  [source,ruby]
481
569
  ----
482
- require "plurimath/xml_engines/oga" = load files related to Oga
483
- Plurimath.xml_engine = Plurimath::XmlEngine::Oga = set Oga as Plurimath XML engine
570
+ require "plurimath/xml_engines/oga"
571
+ Plurimath.xml_engine = Plurimath::XmlEngine::Oga
484
572
  ----
485
573
 
486
574
  You can switch back to **Ox** similarly.
487
575
 
576
+
488
577
  === Supported content
489
578
 
490
579
  === General
data/exe/plurimath ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require "plurimath/cli"
3
+
4
+ Plurimath::Cli.start(ARGV)
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ module Plurimath
6
+ self.autoload :Math, "plurimath/math"
7
+
8
+ class Cli < Thor
9
+ desc "convert", "Convert between math formats"
10
+
11
+ option :input,
12
+ aliases: "-i",
13
+ desc: "Input value should be in quoted string"
14
+
15
+ option :input_format,
16
+ aliases: "-f",
17
+ default: "asciimath",
18
+ desc: "Input format should be in quoted string => \"asciimath\""
19
+
20
+ option :file_path,
21
+ aliases: "-p",
22
+ desc: "Reads input from a file instead of the command line input. Use this for larger inputs or when input contains special characters.",
23
+ force: :boolean
24
+
25
+ option :output_format,
26
+ aliases: "-t",
27
+ default: "mathml",
28
+ desc: "Convert to language type, Output format should be in quoted string"
29
+
30
+ option :math_rendering,
31
+ aliases: "-m",
32
+ force: :boolean,
33
+ default: 'false',
34
+ desc: "Render converted equation as math zone display tree, Boolean only"
35
+
36
+ option :display_style,
37
+ aliases: "-d",
38
+ desc: "DisplayStyle is only supported for OMML and MathML conversion, Boolean only",
39
+ force: :boolean
40
+
41
+ option :split_on_linebreak,
42
+ aliases: "-s",
43
+ desc: "Splits only MathML and OMML equations into multiple equations, Boolean only",
44
+ force: :boolean
45
+
46
+ def convert
47
+ input = options[:input]
48
+ input_string = options[:file_path] ? File.read(options[:file_path]) : input
49
+ warn_and_exit("missing generator argument --input or --file-input") unless input_string
50
+
51
+ input_format = options[:input_format]
52
+ output_format = options[:output_format]
53
+ formula = Plurimath::Math.parse(input_string, input_format)
54
+ return puts formula.to_display(output_format.to_sym) if YAML.safe_load(options[:math_rendering])
55
+
56
+ display_style = options[:display_style]
57
+ split = options[:split_on_linebreak]
58
+ style = display_style.to_s.empty? ? "true" : display_style
59
+ output_text = case output_format
60
+ when "unicodemath"
61
+ formula.to_unicodemath
62
+ when "asciimath"
63
+ formula.to_asciimath
64
+ when "mathml"
65
+ formula.to_mathml(display_style: style, split_on_linebreak: split)
66
+ when "latex"
67
+ formula.to_latex
68
+ when "omml"
69
+ formula.to_omml(display_style: style, split_on_linebreak: split)
70
+ else
71
+ warn_and_exit("Invalid output format: #{output_format}")
72
+ end
73
+
74
+ puts output_text
75
+ end
76
+
77
+ no_commands do
78
+ def warn_and_exit(message)
79
+ warn(message)
80
+ exit 1
81
+ end
82
+ end
83
+ end
84
+ end
@@ -8,17 +8,10 @@ module Plurimath
8
8
  class Parser
9
9
  attr_accessor :text
10
10
 
11
+ TEXT_REGEX = %r(\\(?:mbox|text){[^}]+})
12
+
11
13
  def initialize(text)
12
- enti = HTMLEntities.new
13
- text = enti.encode(enti.decode(text), :hexadecimal)
14
- text = text
15
- .gsub(/((?<!\\) )|\n+/, "")
16
- .gsub(/\\\\ /, "\\\\\\\\")
17
- .gsub(/&#x26;/, "&")
18
- .gsub(/&#x22;/, "\"")
19
- .gsub(/(?<!\\\\)\\&#xa;/, "\\ ")
20
- .gsub(/&#xa;/, "")
21
- @text = text
14
+ @text = pre_processing(text)
22
15
  end
23
16
 
24
17
  def parse
@@ -28,6 +21,26 @@ module Plurimath
28
21
 
29
22
  Math::Formula.new(formula)
30
23
  end
24
+
25
+ private
26
+
27
+ def pre_processing(text)
28
+ text_functions = text.scan(TEXT_REGEX)
29
+ enti = HTMLEntities.new
30
+ text = enti.encode(enti.decode(text), :hexadecimal)
31
+ text = gsub_space_and_unicodes(text)
32
+ text.gsub(TEXT_REGEX) { |str| text_functions.shift }
33
+ end
34
+
35
+ def gsub_space_and_unicodes(text)
36
+ text
37
+ .gsub(/((?<!\\) )|\n+/, "")
38
+ .gsub(/\\\\ /, "\\\\\\\\")
39
+ .gsub(/&#x26;/, "&")
40
+ .gsub(/&#x22;/, "\"")
41
+ .gsub(/(?<!\\\\)\\&#xa;/, "\\ ")
42
+ .gsub(/&#xa;/, "")
43
+ end
31
44
  end
32
45
  end
33
46
  end
@@ -116,6 +116,16 @@ module Plurimath
116
116
  options[:array] << field&.to_omml_math_zone(hashed[:function_spacing], hashed[:last], hashed[:indent], display_style: display_style)
117
117
  end
118
118
 
119
+ def unicodemath_fields_to_print(field, options = {})
120
+ return if field.nil?
121
+
122
+ hashed = common_math_zone_conversion(field, options)
123
+ options[:array] << "#{hashed[:spacing]}|_ \"#{field&.to_unicodemath}\"#{hashed[:field_name]}\n"
124
+ return unless Utility.validate_math_zone(field, lang: :unicodemath)
125
+
126
+ options[:array] << field&.to_unicodemath_math_zone(hashed[:function_spacing], hashed[:last], hashed[:indent])
127
+ end
128
+
119
129
  def dump_mathml(field, intent = false)
120
130
  dump_ox_nodes(field.to_mathml_without_math_tag(intent)).gsub(/\n\s*/, "")
121
131
  end
@@ -10,6 +10,7 @@ module Plurimath
10
10
  latex
11
11
  mathml
12
12
  asciimath
13
+ unicodemath
13
14
  ].freeze
14
15
  POWER_BASE_CLASSES = %w[powerbase power base].freeze
15
16
  DERIVATIVE_CONSTS = [
@@ -165,6 +166,8 @@ module Plurimath
165
166
  " |_ \"#{to_mathml.gsub(/\n\s*/, "")}\"\n#{to_mathml_math_zone(" ").join}"
166
167
  when :omml
167
168
  " |_ \"#{to_omml.gsub(/\n\s*/, "")}\"\n#{to_omml_math_zone(" ", display_style: displaystyle).join}"
169
+ when :unicodemath
170
+ " |_ \"#{to_unicodemath}\"\n#{to_unicodemath_math_zone(" ").join}"
168
171
  end
169
172
  <<~MATHZONE.sub(/\n$/, "")
170
173
  |_ Math zone
@@ -200,6 +203,13 @@ module Plurimath
200
203
  end
201
204
  end
202
205
 
206
+ def to_unicodemath_math_zone(spacing = "", last = false, indent = true)
207
+ filtered_values(value, lang: :unicodemath).map.with_index(1) do |object, index|
208
+ last = index == @values.length
209
+ object.to_unicodemath_math_zone(new_space(spacing, indent), last, indent)
210
+ end
211
+ end
212
+
203
213
  def extract_class_name_from_text
204
214
  return unless value.length < 2 && value.first.is_a?(Function::Text)
205
215
 
@@ -100,6 +100,15 @@ module Plurimath
100
100
  new_arr
101
101
  end
102
102
 
103
+ def to_unicodemath_math_zone(spacing, last = false, _)
104
+ parameters = self.class::FUNCTION
105
+ new_spacing = gsub_spacing(spacing, last)
106
+ new_arr = ["#{spacing}\"#{to_unicodemath}\" #{parameters[:name]}\n"]
107
+ unicodemath_fields_to_print(parameter_one, { spacing: new_spacing, field_name: parameters[:first_value], additional_space: "| |_ " , array: new_arr })
108
+ unicodemath_fields_to_print(parameter_two, { spacing: new_spacing, field_name: parameters[:second_value], additional_space: " |_ " , array: new_arr })
109
+ new_arr
110
+ end
111
+
103
112
  protected
104
113
 
105
114
  def latex_wrapped(field)
@@ -31,7 +31,7 @@ module Plurimath
31
31
  def to_mathml_without_math_tag(intent)
32
32
  first_value = ox_element("mo", attributes: options&.dig(:open_paren)) << (mathml_paren(parameter_one, intent) || "")
33
33
  third_value = ox_element("mo", attributes: options&.dig(:close_paren)) << (mathml_paren(parameter_three, intent) || "")
34
- mrow_value = mathml_value(intent).insert(0, first_value) << third_value
34
+ mrow_value = Array(mathml_value(intent)).insert(0, first_value) << third_value
35
35
  fenced = Utility.update_nodes(ox_element("mrow"), mrow_value)
36
36
  intentify(
37
37
  fenced,
@@ -93,22 +93,22 @@ module Plurimath
93
93
 
94
94
  def to_asciimath_math_zone(spacing, last = false, indent = true)
95
95
  filtered_values(parameter_two, lang: :asciimath).map.with_index(1) do |object, index|
96
- last = index == @values.length
97
- object.to_asciimath_math_zone(spacing, last, indent)
96
+ new_last = index == @values.length && last
97
+ object.to_asciimath_math_zone(spacing, new_last, indent)
98
98
  end
99
99
  end
100
100
 
101
101
  def to_latex_math_zone(spacing, last = false, indent = true)
102
102
  filtered_values(parameter_two, lang: :latex).map.with_index(1) do |object, index|
103
- last = index == @values.length
104
- object.to_latex_math_zone(spacing, last, indent)
103
+ new_last = index == @values.length && last
104
+ object.to_latex_math_zone(spacing, new_last, indent)
105
105
  end
106
106
  end
107
107
 
108
108
  def to_mathml_math_zone(spacing, last = false, indent = true)
109
109
  filtered_values(parameter_two, lang: :mathml).map.with_index(1) do |object, index|
110
- last = index == @values.length
111
- object.to_mathml_math_zone(spacing, last, indent)
110
+ new_last = index == @values.length && last
111
+ object.to_mathml_math_zone(spacing, new_last, indent)
112
112
  end
113
113
  end
114
114
 
@@ -118,6 +118,13 @@ module Plurimath
118
118
  end
119
119
  end
120
120
 
121
+ def to_unicodemath_math_zone(spacing, last = false, indent = true)
122
+ filtered_values(parameter_two, lang: :unicodemath).map.with_index(1) do |object, index|
123
+ new_last = index == @values.length && last
124
+ object.to_unicodemath_math_zone(spacing, new_last, indent)
125
+ end
126
+ end
127
+
121
128
  def line_breaking(obj)
122
129
  field_values = result(Array(parameter_two))
123
130
  return unless field_values.length > 1
@@ -254,7 +261,7 @@ module Plurimath
254
261
  end
255
262
 
256
263
  def binomial_coefficient?(value)
257
- parameter_two.first.is_a?(Frac) &&
264
+ parameter_two&.first&.is_a?(Frac) &&
258
265
  parameter_two&.first&.options&.dig(:choose)
259
266
  end
260
267
 
@@ -120,6 +120,16 @@ module Plurimath
120
120
  end
121
121
  end
122
122
 
123
+ def to_unicodemath_math_zone(spacing, last = false, _)
124
+ new_spacing = gsub_spacing(spacing, last)
125
+ new_arr = [
126
+ "#{spacing}\"#{dump_unicodemath(self)}\" function apply\n",
127
+ "#{new_spacing}|_ \"#{font_family(unicode: true)}\" font family\n",
128
+ ]
129
+ unicodemath_fields_to_print(parameter_one, { spacing: new_spacing, field_name: "argument", additional_space: "| |_ ", array: new_arr })
130
+ new_arr
131
+ end
132
+
123
133
  def line_breaking(obj)
124
134
  parameter_one&.line_breaking(obj)
125
135
  return unless obj.value_exist?
@@ -59,6 +59,10 @@ module Plurimath
59
59
  "#{spacing}\"#{dump_ox_nodes(t_tag).gsub(/\s+/, "")}\" left\n"
60
60
  end
61
61
 
62
+ def to_unicodemath_math_zone(spacing = "", _, _)
63
+ "#{spacing}\"#{parameter_one}\" left\n"
64
+ end
65
+
62
66
  protected
63
67
 
64
68
  def left_paren
@@ -57,6 +57,13 @@ module Plurimath
57
57
  ]
58
58
  end
59
59
 
60
+ def to_unicodemath_math_zone(spacing, last = false, indent = true)
61
+ [
62
+ "#{spacing}\"msgroup\" function apply\n",
63
+ Formula.new(parameter_one).to_unicodemath_math_zone(gsub_spacing(spacing, last), last, indent),
64
+ ]
65
+ end
66
+
60
67
  def to_unicodemath
61
68
  parameter_one.map(&:to_unicodemath).join
62
69
  end
@@ -59,6 +59,10 @@ module Plurimath
59
59
  "#{spacing}\"#{dump_ox_nodes(t_tag).gsub(/\s+/, "")}\" right\n"
60
60
  end
61
61
 
62
+ def to_unicodemath_math_zone(spacing = "", _, _)
63
+ "#{spacing}\"#{parameter_one}\" right\n"
64
+ end
65
+
62
66
  protected
63
67
 
64
68
  def right_paren
@@ -117,6 +117,13 @@ module Plurimath
117
117
  ]
118
118
  end
119
119
 
120
+ def to_unicodemath_math_zone(spacing, last = false, indent = true)
121
+ [
122
+ "#{spacing}\"table\" function apply\n",
123
+ Formula.new(value).to_unicodemath_math_zone(gsub_spacing(spacing, last), last, indent),
124
+ ]
125
+ end
126
+
120
127
  protected
121
128
 
122
129
  def mathml_parenthesis(field, intent)
@@ -76,6 +76,20 @@ module Plurimath
76
76
  ]
77
77
  end
78
78
 
79
+ def to_unicodemath_math_zone(spacing, last = false, _)
80
+ [
81
+ "#{spacing}\"td\" function apply\n",
82
+ Formula.new(parameter_one).to_unicodemath_math_zone(gsub_spacing(spacing, last), last),
83
+ ]
84
+ end
85
+
86
+ def to_unicodemath_math_zone(spacing, last = false, _)
87
+ [
88
+ "#{spacing}\"td\" function apply\n",
89
+ Formula.new(parameter_one).to_unicodemath_math_zone(gsub_spacing(spacing, last), last),
90
+ ]
91
+ end
92
+
79
93
  def omml_content(display_style)
80
94
  parameter_one&.map { |val| val.insert_t_tag(display_style) }
81
95
  end
@@ -101,6 +101,16 @@ module Plurimath
101
101
  new_arr
102
102
  end
103
103
 
104
+ def to_unicodemath_math_zone(spacing, last = false, _)
105
+ parameters = self.class::FUNCTION
106
+ new_spacing = gsub_spacing(spacing, last)
107
+ new_arr = ["#{spacing}\"#{to_unicodemath}\" #{parameters[:name]}\n"]
108
+ unicodemath_fields_to_print(parameter_one, { spacing: new_spacing, field_name: parameters[:first_value], additional_space: "| |_ ", array: new_arr })
109
+ unicodemath_fields_to_print(parameter_two, { spacing: new_spacing, field_name: parameters[:second_value], additional_space: " |_ ", array: new_arr })
110
+ unicodemath_fields_to_print(parameter_three, { spacing: new_spacing, field_name: parameters[:third_value], additional_space: " |_ ", array: new_arr })
111
+ new_arr
112
+ end
113
+
104
114
  protected
105
115
 
106
116
  def latex_wrapped(field)
@@ -71,6 +71,10 @@ module Plurimath
71
71
  parameter_one
72
72
  end
73
73
 
74
+ def to_unicodemath_math_zone(spacing, _, _)
75
+ "#{spacing}#{to_unicodemath} text\n"
76
+ end
77
+
74
78
  protected
75
79
 
76
80
  def symbol_value(unicode)
@@ -80,6 +80,13 @@ module Plurimath
80
80
  ]
81
81
  end
82
82
 
83
+ def to_unicodemath_math_zone(spacing, last = false, indent = true)
84
+ [
85
+ "#{spacing}\"tr\" function apply\n",
86
+ Formula.new(parameter_one).to_unicodemath_math_zone(gsub_spacing(spacing, last), last, indent),
87
+ ]
88
+ end
89
+
83
90
  def remove_hline(first_value)
84
91
  row_lines = first_value.first.parameter_one
85
92
  row_lines.shift if row_lines.first.is_a?(Math::Symbols::Hline)
@@ -110,6 +110,16 @@ module Plurimath
110
110
  new_arr
111
111
  end
112
112
 
113
+ def to_unicodemath_math_zone(spacing, last = false, _)
114
+ new_spacing = gsub_spacing(spacing, last)
115
+ new_arr = [
116
+ "#{spacing}\"#{to_unicodemath}\" function apply\n",
117
+ "#{new_spacing}|_ \"#{class_name}\" function name\n",
118
+ ]
119
+ unicodemath_fields_to_print(parameter_one, { spacing: new_spacing, field_name: "argument", additional_space: " |_ " , array: new_arr })
120
+ new_arr
121
+ end
122
+
113
123
  def custom_array_line_breaking(obj)
114
124
  parameter_value = result(parameter_one)
115
125
  if parameter_value.size > 1
@@ -3,12 +3,12 @@ module Plurimath
3
3
  module Symbols
4
4
  class Pi < Symbol
5
5
  INPUT = {
6
- unicodemath: [["pi", "&#x3c0;"], parsing_wrapper(["uppi"])],
7
- asciimath: [["pi", "&#x3c0;"], parsing_wrapper(["uppi"])],
8
- mathml: [["&#x3c0;"]],
9
- latex: [["pi", "uppi", "&#x3c0;"]],
10
- omml: [["&#x3c0;"]],
11
- html: ["&#x3C0;"],
6
+ unicodemath: ["pi", "&#x3c0;", "&#x1d70b;", parsing_wrapper(["uppi"])],
7
+ asciimath: ["pi", "&#x3c0;", "&#x1d70b;", parsing_wrapper(["uppi"])],
8
+ mathml: ["&#x3c0;", "&#x1d70b;"],
9
+ latex: ["pi", "uppi", "&#x3c0;", "&#x1d70b;"],
10
+ omml: ["&#x3c0;", "&#x1d70b;"],
11
+ html: ["&#x3C0;", "&#x1d70b;"],
12
12
  }.freeze
13
13
 
14
14
  # output methods
@@ -127,6 +127,10 @@ module Plurimath
127
127
  "#{spacing}\"#{dump_mathml(self)}\" text\n"
128
128
  end
129
129
 
130
+ def to_unicodemath_math_zone(spacing = "", last = false, indent = true)
131
+ "#{spacing}\"#{to_unicodemath}\" text\n"
132
+ end
133
+
130
134
  def paren?
131
135
  false
132
136
  end
@@ -3,12 +3,12 @@ module Plurimath
3
3
  module Symbols
4
4
  class Theta < Symbol
5
5
  INPUT = {
6
- unicodemath: [["theta", "&#x3b8;"], parsing_wrapper(["uptheta"])],
7
- asciimath: [["theta", "&#x3b8;"], parsing_wrapper(["uptheta"])],
8
- mathml: ["&#x3b8;"],
9
- latex: [["uptheta", "theta", "&#x3b8;"]],
10
- omml: ["&#x3b8;"],
11
- html: ["&#x3b8;"],
6
+ unicodemath: ["theta", "&#x3b8;", "&#x1d703;", parsing_wrapper(["uptheta"])],
7
+ asciimath: ["theta", "&#x3b8;", "&#x1d703;", parsing_wrapper(["uptheta"])],
8
+ mathml: ["&#x3b8;", "&#x1d703;"],
9
+ latex: ["uptheta", "theta", "&#x3b8;", "&#x1d703;"],
10
+ omml: ["&#x3b8;", "&#x1d703;"],
11
+ html: ["&#x3b8;", "&#x1d703;"],
12
12
  }.freeze
13
13
 
14
14
  # output methods
@@ -19,6 +19,7 @@ module Plurimath
19
19
  notation
20
20
  bevelled
21
21
  rowlines
22
+ intent
22
23
  accent
23
24
  height
24
25
  frame
@@ -383,6 +383,7 @@ module Plurimath
383
383
  height
384
384
  accent
385
385
  height
386
+ intent
386
387
  width
387
388
  index
388
389
  depth
@@ -59,7 +59,7 @@ module Plurimath
59
59
  (operator.absent? >> naryand_values >> naryand_recursion.as(:naryand_recursion).maybe) |
60
60
  (slashed_operator >> naryand_recursion.as(:naryand_recursion).maybe)
61
61
  end
62
-
62
+
63
63
  rule(:baseless_sub) do
64
64
  (invisible_space? >> base_syntax >> op_size_overrides_symbols.absent? >> (operator_symbols.maybe >> baseless_sub_values(:sub_script))) |
65
65
  (invisible_space? >> base_syntax >> op_size_overrides_symbols.absent? >> (operator_symbols >> recursive_baseless_sub_exp.maybe)) |
@@ -220,8 +220,8 @@ module Plurimath
220
220
  (operator_symbols.as(:expr) >> (((mini_sub_sup | sub_or_sup) >> space?) >> bracketed_soperand.maybe)) |
221
221
  (operator_symbols.as(:expr) >> bracketed_soperand) |
222
222
  (((primes | prefixed_primes).as(:symbol).as(:first_value) >> repeated_accent_symbols).as(:accents) >> (sub_or_sup.maybe >> space? >> bracketed_soperand).maybe) |
223
- bracketed_soperand >> operator_symbols.absent? >> sub_sup_values.as(:expr).maybe |
224
- sub_sup_binary_absent >> operator_symbols.absent? >> sub_sup_values.as(:expr).maybe |
223
+ bracketed_soperand >> str("&#x2212;").absent? >> operator_symbols.absent? >> sub_sup_values.as(:expr).maybe |
224
+ sub_sup_binary_absent >> str("&#x2212;").absent? >> operator_symbols.absent? >> sub_sup_values.as(:expr).maybe |
225
225
  bracketed_soperand |
226
226
  prefixed_primes |
227
227
  primes |
@@ -172,7 +172,7 @@ module Plurimath
172
172
  else
173
173
  (Constants::NARY_CLASSES.invert[nary_class.to_s] || Constants::NARY_SYMBOLS[nary_class.to_sym] || nary_class)
174
174
  end
175
- Utility.get_class(nary_function).new
175
+ Utility.get_class(nary_function).new
176
176
  end
177
177
 
178
178
  rule(ordinary_negated_operator: simple(:operator)) do
@@ -518,6 +518,12 @@ module Plurimath
518
518
  [Utility.symbols_class(symbol, lang: :unicodemath), sup_script]
519
519
  end
520
520
 
521
+ rule(combined_symbols: simple(:combined_symbols),
522
+ exp: simple(:exp)) do
523
+ symbol = Constants::COMBINING_SYMBOLS[combined_symbols.to_sym]
524
+ [Utility.symbols_class(symbol, lang: :unicodemath), exp]
525
+ end
526
+
521
527
  rule(operator: simple(:operator),
522
528
  sub_script: simple(:sub_script)) do
523
529
  [Utility.symbols_class(operator, lang: :unicodemath), sub_script]
@@ -1531,17 +1537,6 @@ module Plurimath
1531
1537
  )
1532
1538
  end
1533
1539
 
1534
- rule(unary_functions: simple(:unary),
1535
- first_value: simple(:first_value)) do
1536
- if Constants::UNDEF_UNARY_FUNCTIONS.include?(unary.to_s)
1537
- Math::Formula.new([
1538
- Utility.symbols_class(unary, lang: :unicodemath),
1539
- first_value,
1540
- ])
1541
- else
1542
- Utility.get_class(unary).new(first_value)
1543
- end
1544
- end
1545
1540
 
1546
1541
  rule(unary_functions: simple(:unary),
1547
1542
  first_value: simple(:first_value)) do
@@ -1550,6 +1545,8 @@ module Plurimath
1550
1545
  Utility.symbols_class(unary, lang: :unicodemath),
1551
1546
  first_value,
1552
1547
  ])
1548
+ elsif unary == "mod"
1549
+ Math::Function::Mod.new(nil, first_value)
1553
1550
  else
1554
1551
  Utility.get_class(unary).new(first_value)
1555
1552
  end
@@ -3126,6 +3123,17 @@ module Plurimath
3126
3123
  [fenced] + naryand_recursion
3127
3124
  end
3128
3125
 
3126
+ rule(open_paren: simple(:open_paren),
3127
+ unary_subsup: simple(:unary_subsup),
3128
+ exp: simple(:exp),
3129
+ close_paren: simple(:close_paren)) do
3130
+ Math::Function::Fenced.new(
3131
+ open_paren.is_a?(Slice) ? Utility.symbols_class(open_paren, lang: :unicodemath) : open_paren,
3132
+ [unary_subsup, exp],
3133
+ close_paren.is_a?(Slice) ? Utility.symbols_class(close_paren, lang: :unicodemath) : close_paren,
3134
+ )
3135
+ end
3136
+
3129
3137
  rule(open_paren: simple(:open_paren),
3130
3138
  factor: simple(:factor),
3131
3139
  close_paren: simple(:close_paren),
@@ -3949,6 +3957,18 @@ module Plurimath
3949
3957
  )
3950
3958
  end
3951
3959
 
3960
+ rule(open_paren: simple(:open_paren),
3961
+ factor: sequence(:factor),
3962
+ operand: simple(:operand),
3963
+ exp: simple(:exp),
3964
+ close_paren: simple(:close_paren)) do
3965
+ Math::Function::Fenced.new(
3966
+ Utility.symbols_class(open_paren, lang: :unicodemath),
3967
+ factor + [operand, exp],
3968
+ Utility.symbols_class(close_paren, lang: :unicodemath),
3969
+ )
3970
+ end
3971
+
3952
3972
  rule(open_paren: simple(:open_paren),
3953
3973
  pre_subscript: simple(:pre_sub),
3954
3974
  pre_supscript: simple(:pre_sup),
@@ -482,7 +482,14 @@ module Plurimath
482
482
  end
483
483
 
484
484
  def join_attr_value(attrs, value, unicode_only: false, lang: :mathml)
485
- if value.any?(String)
485
+ if attrs&.is_a?(Hash) && attrs.key?(:intent)
486
+ [
487
+ Math::Function::Intent.new(
488
+ filter_values(join_attr_value(nil, value, unicode_only: unicode_only, lang: lang)),
489
+ Math::Function::Text.new(attrs[:intent]),
490
+ )
491
+ ]
492
+ elsif value.any?(String)
486
493
  new_value = mathml_unary_classes(value, unicode_only: unicode_only, lang: lang)
487
494
  array_value = Array(new_value)
488
495
  attrs.nil? ? array_value : join_attr_value(attrs, array_value, unicode_only: unicode_only)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plurimath
4
- VERSION = "0.8.11"
4
+ VERSION = "0.8.12"
5
5
  end
data/plurimath.gemspec CHANGED
@@ -26,5 +26,6 @@ Gem::Specification.new do |spec|
26
26
  spec.require_paths = ["lib"]
27
27
  spec.add_dependency 'twitter_cldr'
28
28
  spec.add_dependency 'parslet'
29
+ spec.add_dependency 'thor'
29
30
  spec.add_dependency 'ox'
30
31
  end
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.8.11
4
+ version: 0.8.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-18 00:00:00.000000000 Z
11
+ date: 2024-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: twitter_cldr
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: ox
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -55,7 +69,8 @@ dependencies:
55
69
  description: Converts LaTeX math into MathML.
56
70
  email:
57
71
  - open.source@ribose.com
58
- executables: []
72
+ executables:
73
+ - plurimath
59
74
  extensions: []
60
75
  extra_rdoc_files: []
61
76
  files:
@@ -79,12 +94,14 @@ files:
79
94
  - UnitsML-Supported-Data.adoc
80
95
  - bin/console
81
96
  - bin/setup
97
+ - exe/plurimath
82
98
  - lib/plurimath.rb
83
99
  - lib/plurimath/asciimath.rb
84
100
  - lib/plurimath/asciimath/constants.rb
85
101
  - lib/plurimath/asciimath/parse.rb
86
102
  - lib/plurimath/asciimath/parser.rb
87
103
  - lib/plurimath/asciimath/transform.rb
104
+ - lib/plurimath/cli.rb
88
105
  - lib/plurimath/formatter/localized_number.rb
89
106
  - lib/plurimath/formatter/number_data_reader.rb
90
107
  - lib/plurimath/formatter/number_formatter.rb