plurimath 0.8.13 → 0.8.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd471ff00338f1235d74433502b5589c0b95287f196c0088be89cbc91e65a456
4
- data.tar.gz: 3f30ce7bd235c3e9c07768240ffafea84e93f63c0da3ae442b2687ad7b2b7f95
3
+ metadata.gz: e4917de6263422b35cc5d2c04dd466d10e1c0f50f214d0c54753fcef4df826d6
4
+ data.tar.gz: 8c26d6c94f2ab39735cc1011bd155af5dc74b01d714abe7050d55eeac4edebfd
5
5
  SHA512:
6
- metadata.gz: 83007b138c9c86561350991289d7007d42b7aa24859f8039c961c7e2434f1f1b381d3e4f85f897bc3c5c1b1f4d22cb4ddf7257bb9f136a0c465695995ba72690
7
- data.tar.gz: 6b019a7ed611f78e28c0e62473b4e8ee0780568de8b304fed12f9957fde6aebc7f88f30c4656ddd6500f7ef298462616d5fba6fd6d2e9fc3b03f24be1ef8fde4
6
+ metadata.gz: 2e23d92d441333bee877fe164bcfd3405311a78c8e310bfbed17eaca66bcfefaa1020201b8f89c13064c7b0c32bcaec146c0667479e4b45ddedc30e93ac97055
7
+ data.tar.gz: ecd0a5db9719cabf0bd3256776b9874aa7c25092105430eb3fe84aff79e6b18a849ab4e41265fcfcb08eee08352886536936dc92552373068edf569baf3d3548
@@ -2,44 +2,70 @@
2
2
 
3
3
  module Plurimath
4
4
  module Formatter
5
- class NumberFormatter < TwitterCldr::Formatters::NumberFormatter
6
- def format(tokens, number, options = {})
7
- options[:precision] ||= precision_from(number)
8
- options[:type] ||= :decimal
5
+ class NumberFormatter
6
+ attr_reader :number, :data_reader
9
7
 
10
- prefix, suffix, integer_format, fraction_format, signif_format = *partition_tokens(tokens)
11
- number = truncate_number(number, integer_format.format.length)
8
+ STRING_SYMBOLS = {
9
+ dot: ".".freeze,
10
+ f: "F".freeze,
11
+ }.freeze
12
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
13
+ def initialize(number, data_reader = {})
14
+ @number = number
15
+ @data_reader = data_reader
16
+ end
17
+
18
+ def format(precision: nil)
19
+ data_reader[:precision] = precision || precision_from(number)
20
+ int, frac, integer_format, fraction_format, signif_format = *partition_tokens(number)
21
+ result = integer_format.apply(int, data_reader)
22
+ result << fraction_format.apply(frac, data_reader, int) if frac
16
23
 
17
24
  result = signif_format.apply(result, integer_format, fraction_format)
18
25
 
19
- number_system.transliterate(
20
- "#{prefix.to_s}#{result}#{suffix.to_s}"
21
- )
26
+ result
22
27
  end
23
28
 
24
29
  private
25
30
 
26
- def partition_tokens(tokens)
31
+ def partition_tokens(number)
32
+ int, fraction = parse_number(number, data_reader)
27
33
  [
28
- token_val_from(tokens[0]),
29
- token_val_from(tokens[2]),
30
- Numbers::Integer.new(
31
- tokens[1],
32
- data_reader.symbols
33
- ),
34
- Numbers::Fraction.new(
35
- tokens[1],
36
- data_reader.symbols
37
- ),
38
- Numbers::Significant.new(
39
- data_reader.symbols,
40
- )
34
+ int,
35
+ fraction,
36
+ Numbers::Integer.new(data_reader),
37
+ Numbers::Fraction.new(data_reader),
38
+ Numbers::Significant.new(data_reader),
41
39
  ]
42
40
  end
41
+
42
+ def precision_from(number)
43
+ return 0 if number.fix == number
44
+
45
+ parts = number.to_s(STRING_SYMBOLS[:f]).split(STRING_SYMBOLS[:dot])
46
+ parts.size == 2 ? parts[1].size : 0
47
+ end
48
+
49
+ def parse_number(number, options = {})
50
+ precision = options[:precision] || precision_from(number)
51
+
52
+ num = if precision == 0
53
+ round_to(number, precision).abs.fix.to_s(STRING_SYMBOLS[:f])
54
+ else
55
+ round_to(number, precision).abs.round(precision).to_s(STRING_SYMBOLS[:f])
56
+ end
57
+ num.split(STRING_SYMBOLS[:dot])
58
+ end
59
+
60
+ def round_to(number, precision)
61
+ factor = 10 ** precision
62
+ result = if number.is_a?(BigDecimal)
63
+ ((number * factor).fix / factor)
64
+ else
65
+ ((number * factor).round.to_f / factor)
66
+ end
67
+ result
68
+ end
43
69
  end
44
70
  end
45
71
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plurimath
4
+ module Formatter
5
+ module Numbers
6
+ class Base
7
+ def interpolate(string, value, orientation = :right)
8
+ value = value.to_s
9
+ length = value.length
10
+ start = orientation == :left ? 0 : -length
11
+
12
+ string = string.dup
13
+ string = string.ljust(length, '#') if string.length < length
14
+ string[start, length] = value
15
+ string.gsub('#', '')
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -3,20 +3,19 @@
3
3
  module Plurimath
4
4
  module Formatter
5
5
  module Numbers
6
- class Fraction < TwitterCldr::Formatters::Numbers::Fraction
7
- attr_reader :format, :decimal, :precision, :separator, :group
6
+ class Fraction < Base
7
+ attr_reader :decimal, :precision, :separator, :group
8
8
 
9
- def initialize(token, symbols = {})
10
- @format = token ? token.value.split('.').pop : ''
9
+ def initialize(symbols = {})
10
+ @precision = 3
11
11
  @decimal = symbols[:decimal] || '.'
12
12
  @separator = symbols[:fraction_group].to_s
13
13
  @group = symbols[:fraction_group_digits]
14
14
  @digit_count = symbols[:digit_count] || nil
15
- @precision = @format.length
16
15
  end
17
16
 
18
17
  def apply(fraction, options = {}, int = "")
19
- precision = options[:precision] || self.precision
18
+ precision = options[:precision] || @precision
20
19
  return "" unless precision > 0
21
20
 
22
21
  number = interpolate(format(options), fraction, :left)
@@ -26,7 +25,7 @@ module Plurimath
26
25
  end
27
26
 
28
27
  def format(options)
29
- precision = options[:precision] || self.precision
28
+ precision = options[:precision] || @precision
30
29
  precision ? '0' * precision : @format
31
30
  end
32
31
 
@@ -66,13 +65,13 @@ module Plurimath
66
65
  end
67
66
 
68
67
  def update_digit_count(number)
69
- return @digit_count unless all_zeros?(number) == @precision
68
+ return @digit_count unless zeros_count_in(number) == @precision
70
69
 
71
70
  @digit_count - @precision + 1
72
71
  end
73
72
 
74
- def all_zeros?(number)
75
- return unless number.split('').all? { |dig| dig == "0" }
73
+ def zeros_count_in(number)
74
+ return unless number.split('').all? { |digit| digit == "0" }
76
75
 
77
76
  number.length
78
77
  end
@@ -3,13 +3,32 @@
3
3
  module Plurimath
4
4
  module Formatter
5
5
  module Numbers
6
- class Integer < TwitterCldr::Formatters::Numbers::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))
6
+ class Integer < Base
7
+ attr_reader :format, :separator, :groups
8
+
9
+ def initialize(symbols = {})
10
+ @groups = Array(symbols[:group_digits] || 3)
11
11
  @separator = symbols[:group] || ','
12
12
  end
13
+
14
+ def apply(number, options = {})
15
+ format_groups(interpolate(number, number.to_i))
16
+ end
17
+
18
+ def format_groups(string)
19
+ return string if groups.empty?
20
+
21
+ tokens = []
22
+
23
+ tokens << chop_group(string, groups.first)
24
+ tokens << chop_group(string, groups.last) until string.empty?
25
+
26
+ tokens.compact.reverse.join(separator)
27
+ end
28
+
29
+ def chop_group(string, size)
30
+ string.slice!([string.size - size, 0].max, size)
31
+ end
13
32
  end
14
33
  end
15
34
  end
@@ -1,10 +1,9 @@
1
- require "twitter_cldr"
1
+ require_relative "supported_locales"
2
+ require_relative "numbers/base"
2
3
  require_relative "numbers/integer"
3
4
  require_relative "numbers/fraction"
4
5
  require_relative "numbers/significant"
5
6
  require_relative "number_formatter"
6
- require_relative "number_data_reader"
7
- require_relative "localized_number"
8
7
 
9
8
  module Plurimath
10
9
  module Formatter
@@ -32,8 +31,8 @@ module Plurimath
32
31
  private
33
32
 
34
33
  def twitter_cldr_reader_lookup
35
- num = TwitterCldr::DataReaders::NumberDataReader.new(locale)
36
- num.symbols
34
+ symbols = Formatter::SupportedLocales::LOCALES[locale.to_sym]
35
+ symbols
37
36
  .merge!(@localizer_symbols)
38
37
  .merge!(parse_localize_number)
39
38
  end
@@ -51,10 +50,12 @@ module Plurimath
51
50
  end
52
51
 
53
52
  def localize_number(num)
54
- localized = localize(BigDecimal(num.to_s))
55
- return localized.to_s if @precision.zero?
56
-
57
- localized.to_decimal.to_s(precision: @precision)
53
+ Formatter::NumberFormatter.new(
54
+ BigDecimal(num),
55
+ @twitter_cldr_reader,
56
+ ).format(
57
+ precision: @precision
58
+ )
58
59
  end
59
60
 
60
61
  def e_format(num_str)
@@ -122,10 +123,6 @@ module Plurimath
122
123
  chars.first.insert(index + 1, ".") unless chars.first[index + 2].nil?
123
124
  chars[-1] = (chars[-1].to_i - index).to_s
124
125
  end
125
-
126
- def localize(value)
127
- LocalizedNumber.new(value, @locale, type: :decimal)
128
- end
129
126
  end
130
127
  end
131
128
  end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plurimath
4
+ module Formatter
5
+ class SupportedLocales
6
+ LOCALES = {
7
+ "sr-Cyrl-ME": { decimal: ",", group: "." },
8
+ "sr-Latn-ME": { decimal: ",", group: "." },
9
+ "zh-Hant": { decimal: ".", group: "," },
10
+ "en-001": { decimal: ".", group: "," },
11
+ "en-150": { decimal: ".", group: "," },
12
+ "pt-PT": { decimal: ",", group: " " },
13
+ "nl-BE": { decimal: ",", group: "." },
14
+ "it-CH": { decimal: ".", group: "’" },
15
+ "fr-BE": { decimal: ",", group: " " },
16
+ "fr-CA": { decimal: ",", group: " " },
17
+ "fr-CH": { decimal: ",", group: " " },
18
+ "de-AT": { decimal: ",", group: " " },
19
+ "de-CH": { decimal: ".", group: "’" },
20
+ "en-AU": { decimal: ".", group: "," },
21
+ "en-CA": { decimal: ".", group: "," },
22
+ "en-GB": { decimal: ".", group: "," },
23
+ "en-IE": { decimal: ".", group: "," },
24
+ "en-IN": { decimal: ".", group: "," },
25
+ "en-NZ": { decimal: ".", group: "," },
26
+ "en-SG": { decimal: ".", group: "," },
27
+ "en-US": { decimal: ".", group: "," },
28
+ "en-ZA": { decimal: ".", group: "," },
29
+ "es-419": { decimal: ".", group: "," },
30
+ "es-AR": { decimal: ",", group: "." },
31
+ "es-CO": { decimal: ",", group: "." },
32
+ "es-MX": { decimal: ".", group: "," },
33
+ "es-US": { decimal: ".", group: "," },
34
+ fil: { decimal: ".", group: "," },
35
+ af: { decimal: ",", group: " " },
36
+ ar: { decimal: "٫", group: "٬" },
37
+ az: { decimal: ",", group: "." },
38
+ be: { decimal: ",", group: " " },
39
+ bg: { decimal: ",", group: " " },
40
+ bn: { decimal: ".", group: "," },
41
+ bo: { decimal: ".", group: "," },
42
+ bs: { decimal: ",", group: "." },
43
+ ca: { decimal: ",", group: "." },
44
+ cs: { decimal: ",", group: " " },
45
+ cy: { decimal: ".", group: "," },
46
+ da: { decimal: ",", group: "." },
47
+ de: { decimal: ",", group: "." },
48
+ el: { decimal: ",", group: "." },
49
+ en: { decimal: ".", group: "," },
50
+ eo: { decimal: ",", group: " " },
51
+ es: { decimal: ",", group: "." },
52
+ et: { decimal: ",", group: " " },
53
+ eu: { decimal: ",", group: "." },
54
+ fa: { decimal: "٫", group: "٬" },
55
+ fi: { decimal: ",", group: " " },
56
+ fr: { decimal: ",", group: " " },
57
+ ga: { decimal: ".", group: "," },
58
+ gl: { decimal: ",", group: "." },
59
+ gu: { decimal: ".", group: "," },
60
+ he: { decimal: ".", group: "," },
61
+ hi: { decimal: ".", group: "," },
62
+ hr: { decimal: ",", group: "." },
63
+ hu: { decimal: ",", group: " " },
64
+ hy: { decimal: ",", group: " " },
65
+ id: { decimal: ",", group: "." },
66
+ is: { decimal: ",", group: "." },
67
+ it: { decimal: ",", group: "." },
68
+ ja: { decimal: ".", group: "," },
69
+ ka: { decimal: ",", group: " " },
70
+ kk: { decimal: ",", group: " " },
71
+ km: { decimal: ",", group: "." },
72
+ kn: { decimal: ".", group: "," },
73
+ ko: { decimal: ".", group: "," },
74
+ lo: { decimal: ",", group: "." },
75
+ lt: { decimal: ",", group: " " },
76
+ lv: { decimal: ",", group: " " },
77
+ mk: { decimal: ",", group: "." },
78
+ mr: { decimal: ".", group: "," },
79
+ ms: { decimal: ".", group: "," },
80
+ mt: { decimal: ".", group: "," },
81
+ my: { decimal: ".", group: "," },
82
+ nb: { decimal: ",", group: " " },
83
+ nl: { decimal: ",", group: "." },
84
+ pl: { decimal: ",", group: " " },
85
+ pt: { decimal: ",", group: "." },
86
+ ro: { decimal: ",", group: "." },
87
+ ru: { decimal: ",", group: " " },
88
+ sk: { decimal: ",", group: " " },
89
+ sl: { decimal: ",", group: "." },
90
+ sq: { decimal: ",", group: " " },
91
+ sr: { decimal: ",", group: "." },
92
+ sv: { decimal: ",", group: " " },
93
+ sw: { decimal: ".", group: "," },
94
+ ta: { decimal: ".", group: "," },
95
+ th: { decimal: ".", group: "," },
96
+ tr: { decimal: ",", group: "." },
97
+ uk: { decimal: ",", group: " " },
98
+ ur: { decimal: ".", group: "," },
99
+ vi: { decimal: ",", group: "." },
100
+ xh: { decimal: ".", group: " " },
101
+ zh: { decimal: ".", group: "," },
102
+ zu: { decimal: ".", group: "," },
103
+ }
104
+ end
105
+ end
106
+ end
@@ -8,7 +8,7 @@ module Plurimath
8
8
  class Parser
9
9
  attr_accessor :text
10
10
 
11
- TEXT_REGEX = %r(\\(?:mbox|text){[^}]+})
11
+ TEXT_REGEX = %r(\\(?:mbox|text)\{[^\}]+\})
12
12
 
13
13
  def initialize(text)
14
14
  @text = pre_processing(text)
@@ -1,4 +1,5 @@
1
- require "plurimath/formatter/numeric_formatter"
1
+ require_relative "formatter/numeric_formatter"
2
+ require_relative "formatter/supported_locales"
2
3
 
3
4
  module Plurimath
4
5
  class NumberFormatter
@@ -37,11 +38,11 @@ module Plurimath
37
38
  private
38
39
 
39
40
  def supported_locale(locale)
40
- TwitterCldr.supported_locale?(locale.to_sym) ? locale.to_sym : :en
41
+ Formatter::SupportedLocales::LOCALES.key?(locale.to_sym) ? locale.to_sym : :en
41
42
  end
42
43
 
43
44
  def symbols(locale)
44
- TwitterCldr::DataReaders::NumberDataReader.new(locale).symbols
45
+ Formatter::SupportedLocales::LOCALES[locale]
45
46
  end
46
47
  end
47
48
  end
@@ -226,6 +226,7 @@ module Plurimath
226
226
  element_exp_script_validation? >> space? >> exp_script |
227
227
  unary_arg_functions |
228
228
  combined_symbols |
229
+ wrapper_symbols |
229
230
  operand |
230
231
  char |
231
232
  alphanumeric |
@@ -80,6 +80,7 @@ module Plurimath
80
80
  accents |
81
81
  negatable_symbols |
82
82
  fonts.as(:fonts) |
83
+ wrapper_symbols |
83
84
  ((parsing_text | factor.as(:factor)) >> operand.as(:operand).maybe)
84
85
  end
85
86
 
@@ -184,6 +184,7 @@ module Plurimath
184
184
  an_math |
185
185
  other |
186
186
  exp_bracket |
187
+ wrapper_symbols |
187
188
  parsing_text |
188
189
  negatable_symbols |
189
190
  soperand |
@@ -82,6 +82,7 @@ module Plurimath
82
82
  rule(sup_recursion: simple(:recursion)) { recursion }
83
83
  rule(nary_sub_sup: simple(:subsup_exp)) { subsup_exp }
84
84
  rule(open_paren: sequence(:open_paren)) { open_paren }
85
+ rule(subsup_exp: sequence(:subsup_exp)) { Utility.filter_values(subsup_exp) }
85
86
 
86
87
  rule(diacritics_accents: simple(:accent)) { accent }
87
88
  rule(mini_sub_sup: simple(:mini_sub_sup)) { mini_sub_sup }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Plurimath
4
- VERSION = "0.8.13"
4
+ VERSION = "0.8.14"
5
5
  end
data/plurimath.gemspec CHANGED
@@ -24,7 +24,6 @@ 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'
28
27
  spec.add_dependency 'parslet'
29
28
  spec.add_dependency 'thor'
30
29
  spec.add_dependency 'ox'
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plurimath
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.13
4
+ version: 0.8.14
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-08-23 00:00:00.000000000 Z
11
+ date: 2024-08-30 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'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: parslet
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -116,13 +102,13 @@ files:
116
102
  - lib/plurimath/asciimath/parser.rb
117
103
  - lib/plurimath/asciimath/transform.rb
118
104
  - lib/plurimath/cli.rb
119
- - lib/plurimath/formatter/localized_number.rb
120
- - lib/plurimath/formatter/number_data_reader.rb
121
105
  - lib/plurimath/formatter/number_formatter.rb
106
+ - lib/plurimath/formatter/numbers/base.rb
122
107
  - lib/plurimath/formatter/numbers/fraction.rb
123
108
  - lib/plurimath/formatter/numbers/integer.rb
124
109
  - lib/plurimath/formatter/numbers/significant.rb
125
110
  - lib/plurimath/formatter/numeric_formatter.rb
111
+ - lib/plurimath/formatter/supported_locales.rb
126
112
  - lib/plurimath/html.rb
127
113
  - lib/plurimath/html/constants.rb
128
114
  - lib/plurimath/html/parse.rb
@@ -1,13 +0,0 @@
1
- module Plurimath
2
- module Formatter
3
- class LocalizedNumber < TwitterCldr::Localized::LocalizedNumber
4
- def to_s(options = {})
5
- opts = { type: @type, format: @format }.merge(options)
6
-
7
- NumberDataReader
8
- .new(locale, opts)
9
- .format_number(base_obj, opts)
10
- end
11
- end
12
- end
13
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Plurimath
4
- module Formatter
5
- class NumberDataReader < TwitterCldr::DataReaders::NumberDataReader
6
- def formatter
7
- NumberFormatter.new(self)
8
- end
9
- end
10
- end
11
- end