plurimath 0.11.1 → 0.11.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop_todo.yml +108 -175
  4. data/Gemfile +1 -0
  5. data/README.adoc +282 -6
  6. data/lib/plurimath/asciimath/parse.rb +6 -1
  7. data/lib/plurimath/asciimath/transform.rb +2 -0
  8. data/lib/plurimath/base_number_prefix.rb +43 -0
  9. data/lib/plurimath/cli.rb +1 -1
  10. data/lib/plurimath/configuration.rb +9 -1
  11. data/lib/plurimath/errors/evaluation/division_by_zero_error.rb +13 -0
  12. data/lib/plurimath/errors/evaluation/error.rb +9 -0
  13. data/lib/plurimath/errors/evaluation/invalid_binding_error.rb +14 -0
  14. data/lib/plurimath/errors/evaluation/invalid_binding_key_error.rb +14 -0
  15. data/lib/plurimath/errors/evaluation/math_domain_error.rb +9 -0
  16. data/lib/plurimath/errors/evaluation/missing_variable_error.rb +13 -0
  17. data/lib/plurimath/errors/evaluation/non_finite_result_error.rb +13 -0
  18. data/lib/plurimath/errors/evaluation/unsupported_expression_error.rb +13 -0
  19. data/lib/plurimath/errors/evaluation.rb +18 -0
  20. data/lib/plurimath/errors.rb +1 -0
  21. data/lib/plurimath/formatter/numbers/base_notation.rb +54 -31
  22. data/lib/plurimath/formatter/numbers/formatted_notation.rb +62 -0
  23. data/lib/plurimath/formatter/numbers/formatted_number.rb +87 -0
  24. data/lib/plurimath/formatter/numbers/fraction.rb +1 -1
  25. data/lib/plurimath/formatter/numbers/mathml_renderer.rb +56 -0
  26. data/lib/plurimath/formatter/numbers/notation_renderer.rb +30 -29
  27. data/lib/plurimath/formatter/numbers/number_renderer.rb +10 -9
  28. data/lib/plurimath/formatter/numbers/omml_renderer.rb +74 -0
  29. data/lib/plurimath/formatter/numbers/source.rb +29 -4
  30. data/lib/plurimath/formatter/numbers/text_renderer.rb +52 -0
  31. data/lib/plurimath/formatter/numbers.rb +6 -2
  32. data/lib/plurimath/html/parse.rb +5 -0
  33. data/lib/plurimath/html/transform.rb +2 -0
  34. data/lib/plurimath/latex/parse.rb +5 -0
  35. data/lib/plurimath/latex/transform.rb +2 -0
  36. data/lib/plurimath/math/core.rb +52 -0
  37. data/lib/plurimath/math/evaluation/evaluator.rb +147 -0
  38. data/lib/plurimath/math/evaluation/expression_parser.rb +215 -0
  39. data/lib/plurimath/math/evaluation/iteration.rb +63 -0
  40. data/lib/plurimath/math/evaluation.rb +13 -0
  41. data/lib/plurimath/math/formula.rb +10 -1
  42. data/lib/plurimath/math/function/abs.rb +4 -0
  43. data/lib/plurimath/math/function/arccos.rb +4 -0
  44. data/lib/plurimath/math/function/arcsin.rb +4 -0
  45. data/lib/plurimath/math/function/arctan.rb +4 -0
  46. data/lib/plurimath/math/function/ceil.rb +4 -0
  47. data/lib/plurimath/math/function/cos.rb +4 -0
  48. data/lib/plurimath/math/function/cosh.rb +4 -0
  49. data/lib/plurimath/math/function/cot.rb +4 -0
  50. data/lib/plurimath/math/function/coth.rb +4 -0
  51. data/lib/plurimath/math/function/csc.rb +4 -0
  52. data/lib/plurimath/math/function/csch.rb +4 -0
  53. data/lib/plurimath/math/function/exp.rb +4 -0
  54. data/lib/plurimath/math/function/fenced.rb +4 -0
  55. data/lib/plurimath/math/function/floor.rb +4 -0
  56. data/lib/plurimath/math/function/frac.rb +7 -0
  57. data/lib/plurimath/math/function/gcd.rb +9 -0
  58. data/lib/plurimath/math/function/lcm.rb +9 -0
  59. data/lib/plurimath/math/function/lg.rb +4 -0
  60. data/lib/plurimath/math/function/ln.rb +4 -0
  61. data/lib/plurimath/math/function/log.rb +19 -0
  62. data/lib/plurimath/math/function/max.rb +4 -0
  63. data/lib/plurimath/math/function/min.rb +4 -0
  64. data/lib/plurimath/math/function/mod.rb +15 -0
  65. data/lib/plurimath/math/function/power.rb +10 -0
  66. data/lib/plurimath/math/function/prod.rb +10 -0
  67. data/lib/plurimath/math/function/root.rb +7 -0
  68. data/lib/plurimath/math/function/sec.rb +4 -0
  69. data/lib/plurimath/math/function/sech.rb +4 -0
  70. data/lib/plurimath/math/function/sin.rb +4 -0
  71. data/lib/plurimath/math/function/sinh.rb +4 -0
  72. data/lib/plurimath/math/function/sqrt.rb +4 -0
  73. data/lib/plurimath/math/function/sum.rb +10 -0
  74. data/lib/plurimath/math/function/tan.rb +4 -0
  75. data/lib/plurimath/math/function/tanh.rb +4 -0
  76. data/lib/plurimath/math/function/text.rb +17 -0
  77. data/lib/plurimath/math/number.rb +40 -29
  78. data/lib/plurimath/math/symbols/cdot.rb +4 -0
  79. data/lib/plurimath/math/symbols/div.rb +4 -0
  80. data/lib/plurimath/math/symbols/hat.rb +4 -0
  81. data/lib/plurimath/math/symbols/minus.rb +4 -0
  82. data/lib/plurimath/math/symbols/pi.rb +5 -1
  83. data/lib/plurimath/math/symbols/plus.rb +4 -0
  84. data/lib/plurimath/math/symbols/slash.rb +4 -0
  85. data/lib/plurimath/math/symbols/symbol.rb +45 -0
  86. data/lib/plurimath/math/symbols/times.rb +4 -0
  87. data/lib/plurimath/math.rb +1 -0
  88. data/lib/plurimath/mathml/constants.rb +18 -0
  89. data/lib/plurimath/number_formatter.rb +47 -28
  90. data/lib/plurimath/omml/formula_transformation.rb +17 -2
  91. data/lib/plurimath/omml/translator.rb +2 -0
  92. data/lib/plurimath/setup/opal.rb.erb +13 -0
  93. data/lib/plurimath/unicode_math/parse.rb +5 -1
  94. data/lib/plurimath/unicode_math/transform.rb +469 -755
  95. data/lib/plurimath/utility.rb +2 -2
  96. data/lib/plurimath/version.rb +1 -1
  97. data/lib/plurimath.rb +1 -0
  98. data/plurimath.gemspec +1 -1
  99. metadata +23 -5
  100. data/lib/plurimath/formatter/numbers/parts_renderer.rb +0 -30
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Plurimath
4
4
  class NumberFormatter
5
- attr_accessor :locale, :precision, :localize_number, :localizer_symbols
5
+ attr_accessor :locale, :localize_number, :localizer_symbols, :precision
6
6
 
7
7
  def initialize(
8
8
  locale = "en",
@@ -21,11 +21,27 @@ module Plurimath
21
21
  locale: @locale,
22
22
  precision: @precision,
23
23
  format: {}
24
+ )
25
+ result = formatted_number(
26
+ number_string,
27
+ locale: locale,
28
+ precision: precision,
29
+ format: format,
30
+ )
31
+ result.to_s
32
+ end
33
+
34
+ def formatted_number(
35
+ number_string,
36
+ locale: @locale,
37
+ precision: @precision,
38
+ format: {}
24
39
  )
25
40
  locale = supported_locale(locale)
26
- source = Formatter::Numbers::Source.new(number_string)
27
- options = format_options(source, locale, precision,
28
- validated_format(format))
41
+ format = validated_format(format)
42
+ base = format.fetch(:base, Formatter::Numbers::Base::DEFAULT_BASE)
43
+ source = Formatter::Numbers::Source.new(number_string, base: base)
44
+ options = format_options(source, locale, precision, format)
29
45
 
30
46
  if options.notation_supported?
31
47
  return notation_renderer(options).render(source, options.notation)
@@ -34,34 +50,20 @@ module Plurimath
34
50
  render_localized_number(source, options)
35
51
  end
36
52
 
53
+ # Formula-aware entry point. Returns a FormattedNumber,
54
+ # FormattedNotation, or String. Override in subclasses that need the
55
+ # Formula/Number context for rendering decisions; the default delegates
56
+ # to #formatted_number with the merged format hash.
57
+ def format_number(_formula, number, format: {})
58
+ formatted_number(number.value.to_s, format: format)
59
+ end
60
+
37
61
  def twitter_cldr_reader(locale: @locale)
38
62
  symbols_for(supported_locale(locale), {})
39
63
  end
40
64
 
41
65
  private
42
66
 
43
- # localize_number/localizer_symbols are not per-option-hardened — they feed
44
- # SymbolResolver directly — so validate their types at the point of use (see
45
- # #symbol_resolver). That single check covers the constructor, the public
46
- # writers, and any later mutation, raising a clean ConfigurationError
47
- # instead of leaking a TypeError out of SymbolResolver.
48
- def validated_localize_number(value)
49
- return value if value.nil? || value.is_a?(String)
50
-
51
- raise Plurimath::ConfigurationError.new(
52
- :invalid_formatter_option, option: :localize_number, value: value, supported: "a String"
53
- )
54
- end
55
-
56
- def validated_localizer_symbols(value)
57
- return {} if value.nil?
58
- return value if value.is_a?(Hash)
59
-
60
- raise Plurimath::ConfigurationError.new(
61
- :invalid_formatter_option, option: :localizer_symbols, value: value, supported: "a Hash"
62
- )
63
- end
64
-
65
67
  def format_options(source, locale, precision, format)
66
68
  Formatter::Numbers::FormatOptions.new(
67
69
  source,
@@ -98,9 +100,9 @@ module Plurimath
98
100
  symbol_resolver(locale).resolve.merge(format)
99
101
  end
100
102
 
103
+ # Locale always falls back to :en for any unsupported value, including
104
+ # nil and non-string/symbol types; it never raises.
101
105
  def supported_locale(locale)
102
- # Locale always falls back to :en for any unsupported value, including
103
- # nil and non-string/symbol types; it never raises.
104
106
  return :en unless locale.is_a?(String) || locale.is_a?(Symbol)
105
107
 
106
108
  Formatter::SupportedLocales::LOCALES.key?(locale.to_sym) ? locale.to_sym : :en
@@ -119,5 +121,22 @@ module Plurimath
119
121
 
120
122
  format
121
123
  end
124
+
125
+ def validated_localize_number(value)
126
+ return value if value.nil? || value.is_a?(String)
127
+
128
+ raise Plurimath::ConfigurationError.new(
129
+ :invalid_formatter_option, option: :localize_number, value: value, supported: "a String"
130
+ )
131
+ end
132
+
133
+ def validated_localizer_symbols(value)
134
+ return {} if value.nil?
135
+ return value if value.is_a?(Hash)
136
+
137
+ raise Plurimath::ConfigurationError.new(
138
+ :invalid_formatter_option, option: :localizer_symbols, value: value, supported: "a Hash"
139
+ )
140
+ end
122
141
  end
123
142
  end
@@ -102,21 +102,36 @@ module Plurimath
102
102
  end
103
103
 
104
104
  def linebreak_child?(node, child)
105
+ return true if ct_br_child?(child)
106
+
105
107
  child == "" && node.respond_to?(:br) && node.br == ""
106
108
  end
107
109
 
110
+ def ct_br_child?(child)
111
+ return false unless child.is_a?(Object)
112
+
113
+ Lutaml::Model::Utils.base_class_name(child.class.name) == "CTBr"
114
+ end
115
+
108
116
  def styled_run?(children)
109
117
  children.length > 1 && !children.first.is_a?(Math::Core)
110
118
  end
111
119
 
112
120
  def styled_run_value(children)
113
- font = children.first
121
+ fonts, content = children.partition do |child|
122
+ font_style_class?(child)
123
+ end
124
+ font = fonts.first
114
125
  font.new(
115
- Utility.filter_values(children.drop(1)),
126
+ Utility.filter_values(content),
116
127
  Utility::FONT_STYLES.key(font).to_s,
117
128
  )
118
129
  end
119
130
 
131
+ def font_style_class?(value)
132
+ value.is_a?(Class) && value <= Math::Function::FontStyle
133
+ end
134
+
120
135
  def script_function_value(script_class, node)
121
136
  script_class.new(
122
137
  omml_argument_value(node.sub),
@@ -58,6 +58,8 @@ module Plurimath
58
58
  "CTCtrlPr", "CTBoxPr" then nil
59
59
  when "CTRPr" then word_run_properties_to_plurimath(node)
60
60
  when "CTRPR" then math_run_properties_to_plurimath(node)
61
+ when "CTBr" then Math::Function::Linebreak.new
62
+ when "CTWordprocessingEmpty", "CTWordprocessingText" then nil
61
63
  else
62
64
  unsupported_node!(node)
63
65
  end
@@ -1,6 +1,19 @@
1
1
  # Preload Math namespace/core so symbol classes resolve correctly in Opal.
2
2
  require 'plurimath/math'
3
3
  require 'plurimath/math/core'
4
+ require 'plurimath/math/evaluation'
5
+ require 'plurimath/errors/evaluation'
6
+ require 'plurimath/errors/evaluation/error'
7
+ require 'plurimath/errors/evaluation/missing_variable_error'
8
+ require 'plurimath/errors/evaluation/unsupported_expression_error'
9
+ require 'plurimath/errors/evaluation/division_by_zero_error'
10
+ require 'plurimath/errors/evaluation/invalid_binding_error'
11
+ require 'plurimath/errors/evaluation/invalid_binding_key_error'
12
+ require 'plurimath/errors/evaluation/math_domain_error'
13
+ require 'plurimath/errors/evaluation/non_finite_result_error'
14
+ require 'plurimath/math/evaluation/evaluator'
15
+ require 'plurimath/math/evaluation/expression_parser'
16
+ require 'plurimath/math/evaluation/iteration'
4
17
  require 'plurimath/math/symbols/symbol'
5
18
  require 'plurimath/math/symbols/paren'
6
19
 
@@ -3,6 +3,7 @@
3
3
  module Plurimath
4
4
  class UnicodeMath
5
5
  class Parse < Parslet::Parser
6
+ include Plurimath::BaseNumberPrefix::Parser
6
7
  include ParsingRules::Masked
7
8
  include ParsingRules::SubSup
8
9
  include ParsingRules::CommonRules
@@ -162,7 +163,10 @@ module Plurimath
162
163
  end
163
164
 
164
165
  rule(:number) do
165
- (digits.as(:whole) >> op_decimal.as(:decimal) >> digits.as(:fractional)).as(:decimal_number) |
166
+ hex_number |
167
+ binary_number |
168
+ octal_number |
169
+ (digits.as(:whole) >> op_decimal.as(:decimal) >> digits.as(:fractional)).as(:decimal_number) |
166
170
  (op_decimal.as(:decimal) >> digits.as(:whole) >> space?).as(:decimal_number) |
167
171
  digits.as(:digit)
168
172
  end