plurimath 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/Latex-Supported-Data.adoc +1 -0
  4. data/lib/plurimath/asciimath/parse.rb +1 -1
  5. data/lib/plurimath/asciimath/transform.rb +2 -6
  6. data/lib/plurimath/latex/constants.rb +2 -0
  7. data/lib/plurimath/math/core.rb +38 -6
  8. data/lib/plurimath/math/formula.rb +60 -6
  9. data/lib/plurimath/math/function/abs.rb +4 -0
  10. data/lib/plurimath/math/function/arg.rb +22 -0
  11. data/lib/plurimath/math/function/bar.rb +4 -0
  12. data/lib/plurimath/math/function/base.rb +49 -0
  13. data/lib/plurimath/math/function/binary_function.rb +6 -0
  14. data/lib/plurimath/math/function/cancel.rb +5 -0
  15. data/lib/plurimath/math/function/ceil.rb +6 -0
  16. data/lib/plurimath/math/function/color.rb +20 -1
  17. data/lib/plurimath/math/function/ddot.rb +4 -0
  18. data/lib/plurimath/math/function/dot.rb +5 -0
  19. data/lib/plurimath/math/function/fenced.rb +98 -7
  20. data/lib/plurimath/math/function/floor.rb +6 -0
  21. data/lib/plurimath/math/function/font_style/monospace.rb +4 -0
  22. data/lib/plurimath/math/function/font_style.rb +31 -6
  23. data/lib/plurimath/math/function/frac.rb +69 -15
  24. data/lib/plurimath/math/function/hat.rb +4 -0
  25. data/lib/plurimath/math/function/inf.rb +30 -0
  26. data/lib/plurimath/math/function/int.rb +47 -1
  27. data/lib/plurimath/math/function/intent.rb +22 -0
  28. data/lib/plurimath/math/function/left.rb +4 -0
  29. data/lib/plurimath/math/function/lim.rb +6 -0
  30. data/lib/plurimath/math/function/limits.rb +28 -0
  31. data/lib/plurimath/math/function/linebreak.rb +5 -0
  32. data/lib/plurimath/math/function/log.rb +27 -20
  33. data/lib/plurimath/math/function/longdiv.rb +4 -0
  34. data/lib/plurimath/math/function/mbox.rb +4 -0
  35. data/lib/plurimath/math/function/menclose.rb +74 -5
  36. data/lib/plurimath/math/function/merror.rb +2 -0
  37. data/lib/plurimath/math/function/mglyph.rb +64 -0
  38. data/lib/plurimath/math/function/mlabeledtr.rb +29 -0
  39. data/lib/plurimath/math/function/mod.rb +4 -0
  40. data/lib/plurimath/math/function/mpadded.rb +84 -0
  41. data/lib/plurimath/math/function/ms.rb +33 -0
  42. data/lib/plurimath/math/function/msgroup.rb +4 -0
  43. data/lib/plurimath/math/function/msline.rb +2 -4
  44. data/lib/plurimath/math/function/multiscript.rb +70 -6
  45. data/lib/plurimath/math/function/nary.rb +69 -10
  46. data/lib/plurimath/math/function/none.rb +25 -0
  47. data/lib/plurimath/math/function/norm.rb +6 -0
  48. data/lib/plurimath/math/function/obrace.rb +4 -0
  49. data/lib/plurimath/math/function/oint.rb +25 -1
  50. data/lib/plurimath/math/function/over.rb +6 -0
  51. data/lib/plurimath/math/function/overset.rb +46 -1
  52. data/lib/plurimath/math/function/phantom.rb +18 -2
  53. data/lib/plurimath/math/function/power.rb +37 -0
  54. data/lib/plurimath/math/function/power_base.rb +45 -18
  55. data/lib/plurimath/math/function/prod.rb +46 -0
  56. data/lib/plurimath/math/function/right.rb +4 -0
  57. data/lib/plurimath/math/function/root.rb +9 -1
  58. data/lib/plurimath/math/function/rule.rb +4 -0
  59. data/lib/plurimath/math/function/sqrt.rb +7 -1
  60. data/lib/plurimath/math/function/stackrel.rb +6 -0
  61. data/lib/plurimath/math/function/substack.rb +4 -0
  62. data/lib/plurimath/math/function/sum.rb +45 -24
  63. data/lib/plurimath/math/function/table/bmatrix.rb +18 -5
  64. data/lib/plurimath/math/function/table/cases.rb +24 -0
  65. data/lib/plurimath/math/function/table/eqarray.rb +24 -0
  66. data/lib/plurimath/math/function/table/matrix.rb +23 -3
  67. data/lib/plurimath/math/function/table/pmatrix.rb +4 -0
  68. data/lib/plurimath/math/function/table/vmatrix.rb +10 -0
  69. data/lib/plurimath/math/function/table.rb +58 -7
  70. data/lib/plurimath/math/function/td.rb +9 -0
  71. data/lib/plurimath/math/function/ternary_function.rb +14 -1
  72. data/lib/plurimath/math/function/text.rb +6 -0
  73. data/lib/plurimath/math/function/tilde.rb +4 -0
  74. data/lib/plurimath/math/function/tr.rb +9 -0
  75. data/lib/plurimath/math/function/ubrace.rb +5 -0
  76. data/lib/plurimath/math/function/ul.rb +4 -0
  77. data/lib/plurimath/math/function/unary_function.rb +4 -0
  78. data/lib/plurimath/math/function/underover.rb +14 -0
  79. data/lib/plurimath/math/function/underset.rb +49 -1
  80. data/lib/plurimath/math/function/vec.rb +4 -0
  81. data/lib/plurimath/math/number.rb +33 -3
  82. data/lib/plurimath/math/symbol.rb +68 -3
  83. data/lib/plurimath/math.rb +3 -2
  84. data/lib/plurimath/mathml/constants.rb +16 -0
  85. data/lib/plurimath/mathml/parser.rb +42 -2
  86. data/lib/plurimath/mathml/transform.rb +80 -29
  87. data/lib/plurimath/omml/parser.rb +8 -0
  88. data/lib/plurimath/omml/transform.rb +29 -26
  89. data/lib/plurimath/unicode_math/constants.rb +1015 -0
  90. data/lib/plurimath/unicode_math/parse.rb +233 -0
  91. data/lib/plurimath/unicode_math/parser.rb +58 -0
  92. data/lib/plurimath/unicode_math/parsing_rules/absence_rules.rb +138 -0
  93. data/lib/plurimath/unicode_math/parsing_rules/common_rules.rb +114 -0
  94. data/lib/plurimath/unicode_math/parsing_rules/constants_rules.rb +102 -0
  95. data/lib/plurimath/unicode_math/parsing_rules/helper.rb +19 -0
  96. data/lib/plurimath/unicode_math/parsing_rules/masked.rb +62 -0
  97. data/lib/plurimath/unicode_math/parsing_rules/sub_sup.rb +254 -0
  98. data/lib/plurimath/unicode_math/transform.rb +3831 -0
  99. data/lib/plurimath/{unicode.rb → unicode_math.rb} +2 -2
  100. data/lib/plurimath/unitsml.rb +14 -1
  101. data/lib/plurimath/utility.rb +346 -11
  102. data/lib/plurimath/version.rb +1 -1
  103. data/lib/plurimath/xml_engine/oga.rb +5 -0
  104. data/lib/plurimath/xml_engine/ox.rb +5 -0
  105. metadata +23 -3
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plurimath
4
- class Unicode
4
+ class UnicodeMath
5
5
  attr_accessor :text
6
6
 
7
7
  def initialize(text)
@@ -9,7 +9,7 @@ module Plurimath
9
9
  end
10
10
 
11
11
  def to_formula
12
- # TODO: Will be implemented soon
12
+ Parser.new(text).parse
13
13
  end
14
14
  end
15
15
  end
@@ -7,10 +7,23 @@ module Plurimath
7
7
 
8
8
  def initialize(text)
9
9
  @text = text
10
+ raise Math::ParseError.new(error_message) if text.match?(/\^(([^\s].*?[a-z]+)|(\([^-\d]+\)|[^\(\d-]+))/)
10
11
  end
11
12
 
12
13
  def to_formula
13
- ::Unitsml.parse(text).to_plurimath
14
+ formula = ::Unitsml.parse(text).to_plurimath
15
+ formula.unitsml = true
16
+ formula.input_string = text
17
+ formula
18
+ end
19
+
20
+ def error_message
21
+ <<~MESSAGE
22
+ [plurimath] Invalid formula `#{@text}`.
23
+ [plurimath] The use of a variable as an exponent is not valid.
24
+ [plurimath] If this is a bug, please report the formula at our issue tracker at:
25
+ [plurimath] https://github.com/plurimath/plurimath/issues
26
+ MESSAGE
14
27
  end
15
28
  end
16
29
  end
@@ -11,11 +11,17 @@ module Plurimath
11
11
  "bold-fraktur": Math::Function::FontStyle::BoldFraktur,
12
12
  "bold-italic": Math::Function::FontStyle::BoldItalic,
13
13
  "bold-script": Math::Function::FontStyle::BoldScript,
14
+ mbfitsans: Math::Function::FontStyle::SansSerifBoldItalic,
14
15
  monospace: Math::Function::FontStyle::Monospace,
15
16
  mathfrak: Math::Function::FontStyle::Fraktur,
17
+ mitsans: Math::Function::FontStyle::SansSerifItalic,
18
+ mbfsans: Math::Function::FontStyle::BoldSansSerif,
19
+ mbffrak: Math::Function::FontStyle::BoldFraktur,
16
20
  mathcal: Math::Function::FontStyle::Script,
17
21
  fraktur: Math::Function::FontStyle::Fraktur,
22
+ mbfscr: Math::Function::FontStyle::BoldScript,
18
23
  mathbb: Math::Function::FontStyle::DoubleStruck,
24
+ double: Math::Function::FontStyle::DoubleStruck,
19
25
  mathtt: Math::Function::FontStyle::Monospace,
20
26
  mathsf: Math::Function::FontStyle::SansSerif,
21
27
  mathrm: Math::Function::FontStyle::Normal,
@@ -26,9 +32,18 @@ module Plurimath
26
32
  textbf: Math::Function::FontStyle::Bold,
27
33
  script: Math::Function::FontStyle::Script,
28
34
  normal: Math::Function::FontStyle::Normal,
35
+ mbfit: Math::Function::FontStyle::BoldItalic,
36
+ msans: Math::Function::FontStyle::SansSerif,
37
+ mfrak: Math::Function::FontStyle::Fraktur,
38
+ mscr: Math::Function::FontStyle::Script,
29
39
  bold: Math::Function::FontStyle::Bold,
30
40
  bbb: Math::Function::FontStyle::DoubleStruck,
41
+ Bbb: Math::Function::FontStyle::DoubleStruck,
42
+ mtt: Math::Function::FontStyle::Monospace,
31
43
  cal: Math::Function::FontStyle::Script,
44
+ mit: Math::Function::FontStyle::Italic,
45
+ mup: Math::Function::FontStyle::Normal,
46
+ mbf: Math::Function::FontStyle::Bold,
32
47
  sf: Math::Function::FontStyle::SansSerif,
33
48
  tt: Math::Function::FontStyle::Monospace,
34
49
  fr: Math::Function::FontStyle::Fraktur,
@@ -103,6 +118,45 @@ module Plurimath
103
118
  number
104
119
  text
105
120
  ].freeze
121
+ TABLE_SUPPORTED_ATTRS = %i[
122
+ columnlines
123
+ rowlines
124
+ frame
125
+ ].freeze
126
+ MPADDED_ATTRS = %i[
127
+ height
128
+ depth
129
+ width
130
+ ].freeze
131
+ MGLYPH_ATTRS = %i[
132
+ height
133
+ width
134
+ index
135
+ alt
136
+ src
137
+ ].freeze
138
+ UNICODEMATH_MENCLOSE_FUNCTIONS = {
139
+ underline: "bottom",
140
+ underbar: "bottom",
141
+ longdiv: "longdiv",
142
+ xcancel: "updiagonalstrike downdiagonalstrike",
143
+ bcancel: "updiagonalstrike",
144
+ ellipse: "circle",
145
+ circle: "circle",
146
+ cancel: "downdiagonalstrike",
147
+ rrect: "roundedbox",
148
+ rect: "box",
149
+ }.freeze
150
+ MASK_CLASSES = {
151
+ 1 => 'top',
152
+ 2 => 'bottom',
153
+ 4 => 'left',
154
+ 8 => 'right',
155
+ 16 => 'horizontalstrike',
156
+ 32 => 'verticalstrike',
157
+ 64 => 'downdiagonalstrike',
158
+ 128 => 'updiagonalstrike'
159
+ }.freeze
106
160
 
107
161
  class << self
108
162
  def organize_table(array, column_align: nil, options: nil)
@@ -244,14 +298,23 @@ module Plurimath
244
298
  end
245
299
 
246
300
  def text_classes(text)
247
- return nil if text&.empty?
301
+ return nil unless text
248
302
 
249
303
  text = filter_values(text) unless text.is_a?(String)
304
+ return text if text.is_a?(Math::Core)
305
+
250
306
  if text&.scan(/[[:digit:]]/)&.length == text&.length
251
307
  Math::Number.new(text)
252
308
  elsif text&.match?(/[a-zA-Z]/)
253
309
  Math::Function::Text.new(text)
254
310
  else
311
+ text = string_to_html_entity(text)
312
+ .gsub("&#x26;", "&")
313
+ .gsub("&#x3c;", "<")
314
+ .gsub("&#x27;", "'")
315
+ .gsub("&#xa0;", " ")
316
+ .gsub("&#x3e;", ">")
317
+ .gsub("&#xa;", "\n")
255
318
  Math::Symbol.new(text)
256
319
  end
257
320
  end
@@ -358,6 +421,29 @@ module Plurimath
358
421
  attr_is_accent(attrs, value)
359
422
  elsif attrs.key?(:linebreak)
360
423
  Math::Function::Linebreak.new(value.first, attrs)
424
+ elsif attrs.key?(:bevelled) || attrs.key?(:linethickness)
425
+ Math::Function::Frac.new(value[0], value[1], attrs)
426
+ elsif attrs.key?(:notation)
427
+ value << attrs
428
+ elsif attrs.key?(:separators)
429
+ fenced = Math::Function::Fenced.new(
430
+ symbol_object(attrs[:open] || "("),
431
+ value,
432
+ symbol_object(attrs[:close] || ")"),
433
+ )
434
+ fenced.options = { separators: attrs[:separators] }
435
+ fenced
436
+ elsif TABLE_SUPPORTED_ATTRS.any? { |atr| attrs.key?(atr) }
437
+ Math::Function::Table.new(value, nil, nil, attrs)
438
+ elsif MPADDED_ATTRS.any? { |atr| attrs.key?(atr) }
439
+ Math::Function::Mpadded.new(
440
+ filter_values(value),
441
+ attrs,
442
+ )
443
+ elsif MGLYPH_ATTRS.any? { |atr| attrs.key?(atr) }
444
+ Math::Function::Mglyph.new(
445
+ attrs,
446
+ )
361
447
  end
362
448
  elsif attrs.is_a?(Math::Core)
363
449
  attr_is_function(attrs, value)
@@ -374,9 +460,6 @@ module Plurimath
374
460
 
375
461
  def attr_is_function(attrs, value)
376
462
  case attrs
377
- when Math::Function::Menclose
378
- attrs.parameter_two = filter_values(value)
379
- attrs
380
463
  when Math::Function::Fenced
381
464
  attrs.parameter_two = value.compact
382
465
  attrs
@@ -397,25 +480,40 @@ module Plurimath
397
480
  def multiscript(values)
398
481
  values.slice_before("mprescripts").map do |value|
399
482
  base_value = value.shift
483
+ value = nil_to_none_object(value)
400
484
  part_val = value.partition.with_index { |_, i| i.even? }
401
- first_value = part_val[0].empty? ? nil : filter_values(part_val[0])
402
- second_value = part_val[1].empty? ? nil : filter_values(part_val[1])
485
+ first_value = part_val[0].empty? ? nil : part_val[0]
486
+ second_value = part_val[1].empty? ? nil : part_val[1]
403
487
  if base_value.to_s.include?("mprescripts")
404
488
  [first_value, second_value]
405
489
  else
406
490
  Math::Function::PowerBase.new(
407
- base_value,
408
- first_value,
409
- second_value,
491
+ filter_values(base_value),
492
+ filter_values(first_value),
493
+ filter_values(second_value),
410
494
  )
411
495
  end
412
496
  end
413
497
  end
414
498
 
415
- def unfenced_value(object)
499
+ def nil_to_none_object(value)
500
+ return value unless value.any?(NilClass) || value.any? { |val| val.is_a?(Array) && val.empty? }
501
+
502
+ value.each.with_index do |val, index|
503
+ next unless val.nil? || val.is_a?(Array)
504
+
505
+ value[index] = Math::Function::None.new
506
+ end
507
+ end
508
+
509
+ def unfenced_value(object, paren_specific: false)
416
510
  case object
417
511
  when Math::Function::Fenced
418
- filter_values(object.parameter_two)
512
+ if !paren_specific || (paren_specific && valid_paren?(object))
513
+ filter_values(object.parameter_two)
514
+ else
515
+ object
516
+ end
419
517
  when Array
420
518
  filter_values(object)
421
519
  else
@@ -423,6 +521,15 @@ module Plurimath
423
521
  end
424
522
  end
425
523
 
524
+ def valid_paren?(object)
525
+ object.parameter_one.value == "(" &&
526
+ object.parameter_three.value == ")" &&
527
+ !object.options.keys.any? { |k| [:open_paren, :close_paren].any?(k.to_sym) } &&
528
+ !object.parameter_one.mini_sup_sized &&
529
+ !object.parameter_three.mini_sub_sized &&
530
+ object.options.empty?
531
+ end
532
+
426
533
  def frac_values(object)
427
534
  case object
428
535
  when Math::Formula
@@ -600,6 +707,234 @@ module Plurimath
600
707
  new_arr << Math::Function::Text.new(temp_array.join(" ")) if temp_array.any?
601
708
  new_arr
602
709
  end
710
+
711
+ def unicode_accents(accents)
712
+ if accents.is_a?(Math::Function::BinaryFunction)
713
+ accents
714
+ else
715
+ if accents.any? { |acc| acc&.dig(:first_value)&.is_a?(Array) }
716
+ accent_value = accents.first[:first_value].pop
717
+ first_value = accents.first[:first_value]
718
+ accents.first[:first_value] = accent_value
719
+ Math::Formula.new(
720
+ first_value + [transform_accents(accents)]
721
+ )
722
+ else
723
+ transform_accents(accents)
724
+ end
725
+ end
726
+ end
727
+
728
+ def transform_accents(accents)
729
+ accents.reduce do |function, accent|
730
+ if function.is_a?(Hash)
731
+ if function[:prime_accent_symbols]
732
+ Math::Function::Power.new(
733
+ unfenced_value(accent_value(function, function: true), paren_specific: true),
734
+ accent_value(accent),
735
+ )
736
+ else
737
+ Math::Function::Overset.new(
738
+ accent_value(accent),
739
+ unfenced_value(accent_value(function, function: true), paren_specific: true),
740
+ { accent: true }
741
+ )
742
+ end
743
+ else
744
+ if accent[:prime_accent_symbols]
745
+ Math::Function::Power.new(
746
+ unfenced_value(function, paren_specific: true),
747
+ accent_value(accent),
748
+ )
749
+ else
750
+ Math::Function::Overset.new(
751
+ accent_value(accent),
752
+ unfenced_value(function, paren_specific: true),
753
+ { accent: true }
754
+ )
755
+ end
756
+ end
757
+ end
758
+ end
759
+
760
+ def accent_value(accent, function: false)
761
+ if accent[:accent_symbols]
762
+ Math::Symbol.new(UnicodeMath::Constants::ACCENT_SYMBOLS[accent[:accent_symbols].to_sym] || accent[:accent_symbols])
763
+ else
764
+ accent[:first_value] || filter_values(accent[:prime_accent_symbols])
765
+ end
766
+ end
767
+
768
+ def unicode_fractions(fractions)
769
+ frac_arr = UnicodeMath::Constants::UNICODE_FRACTIONS[fractions.to_sym]
770
+ Math::Function::Frac.new(
771
+ Math::Number.new(frac_arr.first.to_s, ),
772
+ Math::Number.new(frac_arr.last.to_s, ),
773
+ { displaystyle: false, unicodemath_fraction: true }
774
+ )
775
+ end
776
+
777
+ def fractions(numerator, denominator, options = nil)
778
+ frac_class = Math::Function::Frac
779
+ if denominator.is_a?(frac_class)
780
+ if denominator.parameter_one.is_a?(frac_class)
781
+ recursion_fraction(denominator, numerator, options)
782
+ else
783
+ denominator.parameter_one = frac_class.new(
784
+ unfenced_value(numerator, paren_specific: true),
785
+ unfenced_value(denominator.parameter_one, paren_specific: true),
786
+ options
787
+ )
788
+ end
789
+ denominator
790
+ else
791
+ frac_class.new(
792
+ unfenced_value(numerator, paren_specific: true),
793
+ unfenced_value(denominator, paren_specific: true),
794
+ options
795
+ )
796
+ end
797
+ end
798
+
799
+ def recursion_fraction(frac, numerator, options)
800
+ frac_class = Math::Function::Frac
801
+ new_numerator = frac.parameter_one
802
+ if new_numerator.is_a?(frac_class)
803
+ recursion_fraction(new_numerator, numerator, options)
804
+ else
805
+ frac.parameter_one = frac_class.new(
806
+ unfenced_value(numerator, paren_specific: true),
807
+ unfenced_value(frac.parameter_one, paren_specific: true),
808
+ options
809
+ )
810
+ frac
811
+ end
812
+ end
813
+
814
+ def recursive_sub(sub_script, sub_recursion)
815
+ base_class = Math::Function::Base
816
+ if sub_recursion.is_a?(base_class)
817
+ if sub_recursion.parameter_one.is_a?(base_class)
818
+ base_recursion(sub_script, sub_recursion)
819
+ else
820
+ sub_recursion.parameter_one = base_class.new(sub_script, sub_recursion.parameter_one)
821
+ end
822
+ sub_recursion
823
+ else
824
+ base_class.new(
825
+ sub_script,
826
+ sub_recursion,
827
+ )
828
+ end
829
+ end
830
+
831
+ def base_recursion(sub_script, sub_recursion)
832
+ base_class = Math::Function::Base
833
+ new_sub = sub_recursion.parameter_one
834
+ if new_sub.is_a?(base_class)
835
+ base_recursion(sub_script, new_sub)
836
+ sub_recursion
837
+ else
838
+ sub_recursion.parameter_one = base_class.new(sub_script, new_sub)
839
+ sub_recursion
840
+ end
841
+ end
842
+
843
+ def recursive_sup(sup_script, sup_recursion)
844
+ power_class = Math::Function::Power
845
+ if sup_recursion.is_a?(power_class)
846
+ if sup_recursion.parameter_one.is_a?(power_class)
847
+ sup_recursion(sup_script, sup_recursion)
848
+ else
849
+ sup_recursion.parameter_one = power_class.new(sup_script, sup_recursion.parameter_one)
850
+ end
851
+ sup_recursion
852
+ else
853
+ power_class.new(
854
+ sup_script,
855
+ sup_recursion,
856
+ )
857
+ end
858
+ end
859
+
860
+ def sup_recursion(sup_script, sup_recursion)
861
+ power_class = Math::Function::Power
862
+ new_sup = sup_recursion.parameter_one
863
+ if new_sup.is_a?(power_class)
864
+ sup_recursion(sup_script, new_sup)
865
+ sup_recursion
866
+ else
867
+ sup_recursion.parameter_one = power_class.new(sup_script, new_sup)
868
+ sup_recursion
869
+ end
870
+ end
871
+
872
+ def base_is_prime?(base)
873
+ UnicodeMath::Constants::PREFIXED_PRIMES.key(base.parameter_two.value) ||
874
+ (base.parameter_two.value == "&#x27;")
875
+ end
876
+
877
+ def base_is_sub_or_sup?(base)
878
+ if base.is_a?(Math::Formula)
879
+ base_is_sub_or_sup?(base.value.first)
880
+ elsif base.is_a?(Math::Function::Fenced)
881
+ base_is_sub_or_sup?(base.parameter_two.first)
882
+ elsif base.is_a?(Math::Symbol) || base.is_a?(Math::Number)
883
+ base.mini_sub_sized || base_mini_sup_sized
884
+ end
885
+ end
886
+
887
+ def identity_matrix(size)
888
+ matrix = Array.new(size) { Array.new(size, 0) }
889
+ size.times { |i| matrix[i][i] = 1 }
890
+ matrix.map do |tr|
891
+ tr.map.with_index do |td, i|
892
+ tr[i] = Math::Function::Td.new([Math::Number.new(td.to_s)])
893
+ end
894
+ Math::Function::Tr.new(tr)
895
+ end
896
+ end
897
+
898
+ def enclosure_attrs(mask)
899
+ raise "enclosure mask is not between 0 and 255" if (mask.nil? || mask < 0 || mask > 255)
900
+
901
+ ret = ""
902
+ unless mask.nil?
903
+ mask ^= 15
904
+ bin_mask = mask.to_s(2).reverse
905
+ classes = bin_mask.chars.each_with_index.map { |bit, i| MASK_CLASSES[2**i] if bit == '1' }.compact
906
+ ret = classes.join(' ')
907
+ end
908
+ ret
909
+ end
910
+
911
+ def notations_to_mask(notations)
912
+ mask = []
913
+ notations.split(" ").each { |notation| mask << MASK_CLASSES.key(notation) }
914
+ mask.inject(*:+)^15
915
+ end
916
+
917
+ def slashed_values(value)
918
+ decoded = HTMLEntities.new.decode(value)
919
+ if decoded.to_s.match?(/^\w+/)
920
+ Math::Function::Text.new("\\#{decoded}")
921
+ else
922
+ Math::Symbol.new(decoded, true)
923
+ end
924
+ end
925
+
926
+ def sequence_slashed_values(values)
927
+ values.each.with_index do |value, index|
928
+ decoded = HTMLEntities.new.decode(value.value)
929
+ slashed = if index == 0
930
+ slashed_values(value.value)
931
+ else
932
+ decoded.match?(/[0-9]/) ? Math::Number.new(decoded) : Math::Symbol.new(decoded)
933
+ end
934
+ values[index] = slashed
935
+ end
936
+ values
937
+ end
603
938
  end
604
939
  end
605
940
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plurimath
4
- VERSION = "0.7.1"
4
+ VERSION = "0.8.0"
5
5
  end
@@ -30,6 +30,11 @@ module Plurimath
30
30
  node = node.unwrap if node.respond_to? :unwrap
31
31
  node.is_a?(Comment)
32
32
  end
33
+
34
+ def replace_nodes(root, nodes)
35
+ root.unwrap.children = ::Oga::XML::NodeSet.new([::Oga::XML::Text.new(text: nodes)])
36
+ root
37
+ end
33
38
  end
34
39
 
35
40
  # Create API compatible with Ox, per Plurimath usage
@@ -23,6 +23,11 @@ module Plurimath
23
23
  def is_xml_comment?(node)
24
24
  node.is_a?(::Ox::Comment)
25
25
  end
26
+
27
+ def replace_nodes(root, nodes)
28
+ root.nodes.replace(Array(nodes))
29
+ root
30
+ end
26
31
  end
27
32
  end
28
33
  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.7.1
4
+ version: 0.8.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-12-19 00:00:00.000000000 Z
11
+ date: 2024-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -48,6 +48,7 @@ files:
48
48
  - ".github/workflows/rake.yml"
49
49
  - ".github/workflows/release.yml"
50
50
  - ".gitignore"
51
+ - ".gitmodules"
51
52
  - ".hound.yml"
52
53
  - ".rspec"
53
54
  - ".rspec-opal"
@@ -85,6 +86,7 @@ files:
85
86
  - lib/plurimath/math/function/arccos.rb
86
87
  - lib/plurimath/math/function/arcsin.rb
87
88
  - lib/plurimath/math/function/arctan.rb
89
+ - lib/plurimath/math/function/arg.rb
88
90
  - lib/plurimath/math/function/bar.rb
89
91
  - lib/plurimath/math/function/base.rb
90
92
  - lib/plurimath/math/function/binary_function.rb
@@ -127,6 +129,7 @@ files:
127
129
  - lib/plurimath/math/function/hom.rb
128
130
  - lib/plurimath/math/function/inf.rb
129
131
  - lib/plurimath/math/function/int.rb
132
+ - lib/plurimath/math/function/intent.rb
130
133
  - lib/plurimath/math/function/ker.rb
131
134
  - lib/plurimath/math/function/lcm.rb
132
135
  - lib/plurimath/math/function/left.rb
@@ -144,12 +147,17 @@ files:
144
147
  - lib/plurimath/math/function/mbox.rb
145
148
  - lib/plurimath/math/function/menclose.rb
146
149
  - lib/plurimath/math/function/merror.rb
150
+ - lib/plurimath/math/function/mglyph.rb
147
151
  - lib/plurimath/math/function/min.rb
152
+ - lib/plurimath/math/function/mlabeledtr.rb
148
153
  - lib/plurimath/math/function/mod.rb
154
+ - lib/plurimath/math/function/mpadded.rb
155
+ - lib/plurimath/math/function/ms.rb
149
156
  - lib/plurimath/math/function/msgroup.rb
150
157
  - lib/plurimath/math/function/msline.rb
151
158
  - lib/plurimath/math/function/multiscript.rb
152
159
  - lib/plurimath/math/function/nary.rb
160
+ - lib/plurimath/math/function/none.rb
153
161
  - lib/plurimath/math/function/norm.rb
154
162
  - lib/plurimath/math/function/obrace.rb
155
163
  - lib/plurimath/math/function/oint.rb
@@ -177,6 +185,8 @@ files:
177
185
  - lib/plurimath/math/function/table/align.rb
178
186
  - lib/plurimath/math/function/table/array.rb
179
187
  - lib/plurimath/math/function/table/bmatrix.rb
188
+ - lib/plurimath/math/function/table/cases.rb
189
+ - lib/plurimath/math/function/table/eqarray.rb
180
190
  - lib/plurimath/math/function/table/matrix.rb
181
191
  - lib/plurimath/math/function/table/multline.rb
182
192
  - lib/plurimath/math/function/table/pmatrix.rb
@@ -208,7 +218,17 @@ files:
208
218
  - lib/plurimath/setup/oga.rb
209
219
  - lib/plurimath/setup/opal.rb.erb
210
220
  - lib/plurimath/setup/ox.rb
211
- - lib/plurimath/unicode.rb
221
+ - lib/plurimath/unicode_math.rb
222
+ - lib/plurimath/unicode_math/constants.rb
223
+ - lib/plurimath/unicode_math/parse.rb
224
+ - lib/plurimath/unicode_math/parser.rb
225
+ - lib/plurimath/unicode_math/parsing_rules/absence_rules.rb
226
+ - lib/plurimath/unicode_math/parsing_rules/common_rules.rb
227
+ - lib/plurimath/unicode_math/parsing_rules/constants_rules.rb
228
+ - lib/plurimath/unicode_math/parsing_rules/helper.rb
229
+ - lib/plurimath/unicode_math/parsing_rules/masked.rb
230
+ - lib/plurimath/unicode_math/parsing_rules/sub_sup.rb
231
+ - lib/plurimath/unicode_math/transform.rb
212
232
  - lib/plurimath/unitsml.rb
213
233
  - lib/plurimath/utility.rb
214
234
  - lib/plurimath/version.rb