plurimath 0.8.2 → 0.8.3

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: f961f580d6f46c943b805f8c2f2a77281151ddcb76eab4a7e7adabbfe61b2b6b
4
- data.tar.gz: fbe6a5651b11576a161fe0620780aa359151688d97fac674874679d138c8c34d
3
+ metadata.gz: def00e41e6010e06ea7df51573e342c4ed8b815e079bcbad3a7776cc5d625e02
4
+ data.tar.gz: d46595b7a57d2a391e849d58a6b23f7e449e042e891797967f13cee0364c32df
5
5
  SHA512:
6
- metadata.gz: badfd5bd7eb9f2b84ef7604c21ab4f82fa93de5c52df760ee2fcc7ade85cd6900dbc527d41faf2c2521ae6dfbeb2cf79f8af0028927c6a1049bd921836fdec41
7
- data.tar.gz: 886be496741ca30633f2ca6d25a5d39f1e5986065adb07cbc961a08ebb6fc04f4d060037afaafec59fb4fbcc5510c968aa1b06bfec366388d7bab1eaad2add99
6
+ metadata.gz: 5e5c0c02a41fcd2fdbebbd11ca103228ec5c9a2b4e68e98a364c39d988540ebfa844ad06785ced1538186ae7a0583978fe8c1a548c1da135d243d633557cc298
7
+ data.tar.gz: 15463a536fac275fe0935b360dd754ed787a202d4d77b4ef3f4934359e45ec4393e0c95bd6a7ce7f02a9e655f21eeeec312f932462354965a287e08e92b55e89
@@ -0,0 +1,114 @@
1
+ require "twitter_cldr"
2
+ require_relative "twitter_cldr_rb/integer"
3
+ require_relative "twitter_cldr_rb/fraction"
4
+ require_relative "twitter_cldr_rb/number_formatter"
5
+
6
+ module Plurimath
7
+ module Formatter
8
+ class NumberFormatter
9
+ attr_accessor :locale, :localize_number, :localizer_symbols
10
+
11
+ LOCALIZE_NUMBER_REGEX = %r{(?<group>[^#])?(?<groupdigits>#+0)(?<decimal>.)(?<fractdigits>#+)(?<fractgroup>[^#])?}
12
+ SUPPORTED_NOTATIONS = %i[e scientific engineering].freeze
13
+
14
+ def initialize(locale, localize_number:, localizer_symbols:)
15
+ @locale = locale
16
+ @localize_number = localize_number
17
+ @localizer_symbols = localizer_symbols
18
+ @twitter_cldr_reader = twitter_cldr_reader(locale)
19
+ end
20
+
21
+ def localized_number(number_string, locale:, precision:, format:)
22
+ options_instance_variables(number_string, format, precision)
23
+ @twitter_cldr_reader.merge!(format)
24
+ return send("#{@notation}_format", number_string) if SUPPORTED_NOTATIONS.include?(@notation&.to_sym)
25
+
26
+ localize_number(number_string)
27
+ end
28
+
29
+ private
30
+
31
+ def twitter_cldr_reader(locale)
32
+ num = TwitterCldr::DataReaders::NumberDataReader.new(locale)
33
+ num.symbols
34
+ .merge!(@localizer_symbols)
35
+ .merge!(parse_localize_number)
36
+ end
37
+
38
+ def parse_localize_number
39
+ @localize_number or return {}
40
+ m = LOCALIZE_NUMBER_REGEX.match(@localize_number) or return {}
41
+ ret = {
42
+ decimal: m[:decimal],
43
+ group_digits: m[:groupdigits].size,
44
+ fraction_group_digits: m[:fractdigits].size,
45
+ group: m[:group] == " " ? "\u00A0" : (m[:group] || ""),
46
+ fraction_group: m[:fractgroup] == " " ? "\u00A0" : (m[:fractgroup] || "")
47
+ }.compact
48
+ end
49
+
50
+ def localize_number(num)
51
+ num = num.match?(/\./) ? num.to_f : num.to_i
52
+ localized = BigDecimal(num.to_s).localize(@locale)
53
+ return localized.to_s if @precision.zero?
54
+
55
+ localized.to_decimal.to_s(precision: @precision)
56
+ end
57
+
58
+ def e_format(num_str)
59
+ notations_formatting(num_str).join(@e.to_s)
60
+ end
61
+
62
+ def scientific_format(num_str)
63
+ notations_formatting(num_str).join(" #{@times} 10^")
64
+ end
65
+
66
+ def engineering_format(num_str)
67
+ @precision = num_str.length - 1 unless @precision > 0
68
+ chars = notation_chars(num_str)
69
+ update_string_index(chars, chars.last.to_i % 3)
70
+ chars[0] = localize_number(chars[0])
71
+ chars.join(" #{@times} 10^")
72
+ end
73
+
74
+ def update_exponent_sign(str)
75
+ str.gsub!("e", "e+") if @exponent_sign == :plus
76
+ end
77
+
78
+ def notation_chars(num_str)
79
+ notation_number = ("%.#{@precision}e" %num_str)
80
+ update_exponent_sign(notation_number.gsub!("+0", ""))
81
+ notation_number.split("e")
82
+ end
83
+
84
+ def notations_formatting(num_str)
85
+ chars = notation_chars(num_str)
86
+ chars[0] = localize_number(chars[0])
87
+ chars
88
+ end
89
+
90
+ def options_instance_variables(string, format, precision)
91
+ @e = format.delete(:e)&.to_sym || :e
92
+ @times = format.delete(:times)&.to_sym || "\u{d7}"
93
+ @notation = format.delete(:notation)&.to_sym || nil
94
+ @precision = update_precision(string, precision)
95
+ @exponent_sign = format.delete(:exponent_sign)&.to_sym || nil
96
+ end
97
+
98
+ def update_precision(num, precision)
99
+ return precision if precision
100
+ return num.sub(/\./, "").size - 1 if SUPPORTED_NOTATIONS.include?(@notation&.to_sym)
101
+
102
+ /\./.match?(num) ? num.sub(/^.*\./, "").size : 0
103
+ end
104
+
105
+ def update_string_index(chars, index)
106
+ return if index.zero?
107
+
108
+ chars.first.delete!(".")
109
+ chars.first.insert(index + 1, ".")
110
+ chars[-1] = (chars[-1].to_i - index).to_s
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TwitterCldr
4
+ module Formatters
5
+ module Numbers
6
+ class Fraction
7
+ attr_reader :format, :decimal, :precision, :separator, :group
8
+
9
+ def initialize(token, symbols = {})
10
+ @format = token ? token.value.split('.').pop : ''
11
+ @decimal = symbols[:decimal] || '.'
12
+ @separator = symbols[:fraction_group] || " "
13
+ @group = symbols[:fraction_group_digits] || 3
14
+ @digit_count = symbols[:digit_count] || nil
15
+ @precision = @format.length
16
+ end
17
+
18
+ def apply(fraction, options = {}, int = "")
19
+ precision = options[:precision] || self.precision
20
+ return "" unless precision > 0
21
+
22
+ number = interpolate(format(options), fraction, :left)
23
+ number = digit_count_format(int, fraction, number) if @digit_count
24
+ decimal + change_format(precision, number)
25
+ end
26
+
27
+ def format(options)
28
+ precision = options[:precision] || self.precision
29
+ precision ? '0' * precision : @format
30
+ end
31
+
32
+ protected
33
+
34
+ def change_format(precision, string)
35
+ tokens = []
36
+ tokens << string&.slice!(0, group) until string&.empty?
37
+ tokens.compact.join(separator)
38
+ end
39
+
40
+ def digit_count_format(int, fraction, number)
41
+ integer = int + "." + fraction
42
+ float = integer.to_f
43
+ int_length = integer.length - 1
44
+ @digit_count ||= int_length
45
+ if int_length > @digit_count
46
+ float.round(@digit_count - int.length).to_s.split(".").last
47
+ elsif int_length < @digit_count
48
+ number += "0" * (@digit_count - int_length)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TwitterCldr
4
+ module Formatters
5
+ module Numbers
6
+ class Integer
7
+ def initialize(token, symbols = {})
8
+ format = token.value.split('.')[0]
9
+ @format = prepare_format(format, symbols)
10
+ @groups = Array(symbols[:group_digits] || parse_groups(format))
11
+ @separator = symbols[:group] || ','
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TwitterCldr
4
+ module Formatters
5
+ class NumberFormatter
6
+ def format(tokens, number, options = {})
7
+ options[:precision] ||= precision_from(number)
8
+ options[:type] ||= :decimal
9
+
10
+ prefix, suffix, integer_format, fraction_format = *partition_tokens(tokens)
11
+ number = truncate_number(number, integer_format.format.length)
12
+
13
+ int, fraction = parse_number(number, options)
14
+ result = integer_format.apply(int, options)
15
+ result << fraction_format.apply(fraction, options, int) if fraction
16
+
17
+ number_system.transliterate(
18
+ "#{prefix.to_s}#{result}#{suffix.to_s}"
19
+ )
20
+ end
21
+ end
22
+ end
23
+ end
@@ -7,6 +7,7 @@ require_relative "mathml"
7
7
  require_relative "html"
8
8
  require_relative "latex"
9
9
  require_relative "unitsml"
10
+ require_relative "number_formatter"
10
11
  require_relative "math/core"
11
12
  require_relative "math/number"
12
13
  require_relative "math/symbol"
@@ -0,0 +1,32 @@
1
+ require "plurimath/formatter/number_formatter"
2
+
3
+ module Plurimath
4
+ class NumberFormatter
5
+ attr_accessor :locale, :localize_number, :localizer_symbols
6
+
7
+ def initialize(locale = "en", localize_number: nil, localizer_symbols: {})
8
+ @locale = supported_locale(locale)
9
+ @localize_number = localize_number
10
+ @localizer_symbols = localizer_symbols
11
+ end
12
+
13
+ def localized_number(number_string, locale: @locale, precision: nil, format: {})
14
+ Formatter::NumberFormatter.new(
15
+ supported_locale(locale),
16
+ localize_number: localize_number,
17
+ localizer_symbols: localizer_symbols,
18
+ ).localized_number(
19
+ number_string,
20
+ locale: supported_locale(locale),
21
+ precision: precision,
22
+ format: format,
23
+ )
24
+ end
25
+
26
+ private
27
+
28
+ def supported_locale(locale)
29
+ TwitterCldr.supported_locale?(locale.to_sym) ? locale.to_sym : :en
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plurimath
4
- VERSION = "0.8.2"
4
+ VERSION = "0.8.3"
5
5
  end
data/plurimath.gemspec CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.bindir = "exe"
25
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
26
  spec.require_paths = ["lib"]
27
+ spec.add_dependency 'twitter_cldr'
27
28
  spec.add_dependency 'parslet'
28
29
  spec.add_dependency 'ox'
29
30
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plurimath
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
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-04-16 00:00:00.000000000 Z
11
+ date: 2024-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: twitter_cldr
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: parslet
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -70,6 +84,10 @@ files:
70
84
  - lib/plurimath/asciimath/parse.rb
71
85
  - lib/plurimath/asciimath/parser.rb
72
86
  - lib/plurimath/asciimath/transform.rb
87
+ - lib/plurimath/formatter/number_formatter.rb
88
+ - lib/plurimath/formatter/twitter_cldr_rb/fraction.rb
89
+ - lib/plurimath/formatter/twitter_cldr_rb/integer.rb
90
+ - lib/plurimath/formatter/twitter_cldr_rb/number_formatter.rb
73
91
  - lib/plurimath/html.rb
74
92
  - lib/plurimath/html/constants.rb
75
93
  - lib/plurimath/html/parse.rb
@@ -214,6 +232,7 @@ files:
214
232
  - lib/plurimath/mathml/constants.rb
215
233
  - lib/plurimath/mathml/parser.rb
216
234
  - lib/plurimath/mathml/transform.rb
235
+ - lib/plurimath/number_formatter.rb
217
236
  - lib/plurimath/omml.rb
218
237
  - lib/plurimath/omml/parser.rb
219
238
  - lib/plurimath/omml/transform.rb
@@ -259,7 +278,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
259
278
  - !ruby/object:Gem::Version
260
279
  version: '0'
261
280
  requirements: []
262
- rubygems_version: 3.3.26
281
+ rubygems_version: 3.3.27
263
282
  signing_key:
264
283
  specification_version: 4
265
284
  summary: Converts LaTeX math into MathML.