minting 1.7.0 → 1.7.3
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 +4 -4
- data/README.md +80 -112
- data/Rakefile +13 -1
- data/bin/bench_check +46 -0
- data/doc/Mint/Currency.html +446 -46
- data/doc/Mint/CurrencyRegistry.html +7 -7
- data/doc/Mint/Money.html +203 -177
- data/doc/Mint/RangeStepPatch.html +277 -0
- data/doc/Mint/Registry.html +842 -0
- data/doc/Mint/UnknownCurrency.html +2 -2
- data/doc/Mint.html +385 -66
- data/doc/Minting.html +3 -3
- data/doc/_index.html +24 -9
- data/doc/agents/api_review-2026-06-15.md +342 -0
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +97 -89
- data/doc/index.html +97 -89
- data/doc/method_list.html +97 -25
- data/doc/top-level-namespace.html +13 -5
- data/lib/minting/currency/currency.rb +75 -0
- data/lib/minting/mint/aliases.rb +3 -0
- data/lib/minting/mint/dsl/{refinements.rb → numeric.rb} +6 -5
- data/lib/minting/mint/dsl/range.rb +31 -18
- data/lib/minting/mint/dsl/string.rb +12 -0
- data/lib/minting/mint/dsl/top_level.rb +3 -0
- data/lib/minting/mint/locale_backend.rb +29 -0
- data/lib/minting/mint/mint.rb +28 -12
- data/lib/minting/mint/parser/parser.rb +62 -0
- data/lib/minting/mint/parser/separators.rb +39 -0
- data/lib/minting/mint/registry/registration.rb +33 -0
- data/lib/minting/mint/registry/registry.rb +38 -0
- data/lib/minting/mint/registry/symbols.rb +49 -0
- data/lib/minting/mint/registry/zeros.rb +18 -0
- data/lib/minting/mint.rb +13 -16
- data/lib/minting/money/allocation/allocation.rb +25 -0
- data/lib/minting/money/{allocation.rb → allocation/split.rb} +1 -19
- data/lib/minting/money/arithmetics/methods.rb +27 -0
- data/lib/minting/money/{arithmetics.rb → arithmetics/operators.rb} +0 -21
- data/lib/minting/money/clamp.rb +66 -0
- data/lib/minting/money/coercion.rb +10 -0
- data/lib/minting/money/comparable.rb +6 -0
- data/lib/minting/money/constructors.rb +14 -9
- data/lib/minting/money/format/formatting.rb +60 -0
- data/lib/minting/money/{formatting.rb → format/to_s.rb} +13 -36
- data/lib/minting/money/money.rb +12 -58
- data/lib/minting/version.rb +1 -1
- metadata +29 -19
- data/lib/minting/mint/currency/currency.rb +0 -36
- data/lib/minting/mint/currency/currency_registry.rb +0 -67
- data/lib/minting/mint/currency/world_currencies.rb +0 -16
- data/lib/minting/mint/parser.rb +0 -85
- /data/doc/agents/{AGENTS.md → expired/AGENTS.md} +0 -0
- /data/doc/agents/{copilot-instructions.md → expired/copilot-instructions.md} +0 -0
- /data/doc/agents/{gemini_gem_evaluation.md → expired/gemini_gem_evaluation.md} +0 -0
- /data/doc/agents/{recommendations.md → expired/recommendations.md} +0 -0
- /data/doc/agents/{rubocop-issues.md → expired/rubocop-issues.md} +0 -0
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'yaml'
|
|
4
|
-
|
|
5
|
-
# Mint currency store (internal)
|
|
6
|
-
module Mint
|
|
7
|
-
# Internal currency registry
|
|
8
|
-
# Manages the registry cache and currency symbol lookups.
|
|
9
|
-
module CurrencyRegistry
|
|
10
|
-
extend self
|
|
11
|
-
|
|
12
|
-
# Returns the hash of all registered currencies.
|
|
13
|
-
#
|
|
14
|
-
# @return [Hash{String => Currency}] registered currencies mapped by code
|
|
15
|
-
# @api private
|
|
16
|
-
def currencies
|
|
17
|
-
@currencies ||= Mint.world_currencies.dup
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Registered symbols sorted for detection: longest match wins, then parser priority.
|
|
21
|
-
#
|
|
22
|
-
# @return [Array<Array<String, Currency>>] sorted symbol-to-currency mappings
|
|
23
|
-
# @api private
|
|
24
|
-
def currency_symbols
|
|
25
|
-
@currency_symbols ||= begin
|
|
26
|
-
currencies.values
|
|
27
|
-
.reject { |c| c.symbol.empty? }
|
|
28
|
-
.map { |currency| [currency.symbol, currency] }
|
|
29
|
-
.sort_by { |symbol, currency| [-symbol.length, -currency.priority] }
|
|
30
|
-
end.freeze
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Registers a new currency, raising a KeyError if already registered.
|
|
34
|
-
#
|
|
35
|
-
# @param code [String] the unique currency code
|
|
36
|
-
# @param subunit [Integer] the decimal subunit precision, defaults to 0
|
|
37
|
-
# @param symbol [String] the display symbol
|
|
38
|
-
# @param priority [Integer] parser precedence priority
|
|
39
|
-
# @return [Currency] the newly registered Currency instance
|
|
40
|
-
# @raise [ArgumentError] if the code contains invalid characters
|
|
41
|
-
# @raise [KeyError] if the currency code is already registered
|
|
42
|
-
def register(code:, subunit: 0, symbol: '', priority: 0)
|
|
43
|
-
raise ArgumentError, 'Currency code must be String' unless code.is_a? String
|
|
44
|
-
unless code.match?(/^[A-Z_]+$/)
|
|
45
|
-
raise ArgumentError,
|
|
46
|
-
"Currency code must have only letters or '_' ('USD',, 'MY_COIN')"
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
currencies = CurrencyRegistry.currencies
|
|
50
|
-
raise KeyError, "Currency: #{code} already registered" if currencies[code]
|
|
51
|
-
|
|
52
|
-
currency = currencies[code] = Currency.new(code:, subunit:, symbol:, priority:)
|
|
53
|
-
invalidate_symbols_cache
|
|
54
|
-
currency
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
private
|
|
58
|
-
|
|
59
|
-
# Clears and refreshes the currency symbol cache.
|
|
60
|
-
# Called when currencies are registered.
|
|
61
|
-
#
|
|
62
|
-
# @api private
|
|
63
|
-
def invalidate_symbols_cache
|
|
64
|
-
@currency_symbols = nil
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Mint list of world currencies
|
|
4
|
-
module Mint
|
|
5
|
-
# Loads ISO world currencies from YAML file into the registry.
|
|
6
|
-
#
|
|
7
|
-
# @return [Hash{String => Currency}] ISO-4217 world currencies mapped by code
|
|
8
|
-
# @api private
|
|
9
|
-
def self.world_currencies
|
|
10
|
-
@world_currencies ||= begin
|
|
11
|
-
path = File.join(File.expand_path('../../data', __dir__), 'world-currencies.yaml')
|
|
12
|
-
|
|
13
|
-
YAML.load_file(path).to_h { |entry| [entry['code'], Currency.new(**entry.transform_keys(&:to_sym))] }
|
|
14
|
-
end.freeze
|
|
15
|
-
end
|
|
16
|
-
end
|
data/lib/minting/mint/parser.rb
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Mint Money parsing
|
|
4
|
-
module Mint
|
|
5
|
-
extend self
|
|
6
|
-
|
|
7
|
-
# Parses a human-readable money string into a {Money} object.
|
|
8
|
-
#
|
|
9
|
-
# @param input [String] Amount input, optionally including a currency symbol or code
|
|
10
|
-
# @param currency [String, Symbol, Currency, nil] ISO code when not present in +input+
|
|
11
|
-
# @return [Money]
|
|
12
|
-
# @raise [ArgumentError] when +input+ is invalid or currency cannot be determined
|
|
13
|
-
#
|
|
14
|
-
# @example With explicit currency
|
|
15
|
-
# Money.parse('19.99', 'USD') #=> [USD 19.99]
|
|
16
|
-
# Money.parse('1.234,56', 'EUR') #=> [EUR 1234.56]
|
|
17
|
-
#
|
|
18
|
-
# @example With symbol or code in the string
|
|
19
|
-
# Money.parse('$19.99') #=> [USD 19.99]
|
|
20
|
-
# Money.parse('19,99 €') #=> [EUR 19.99]
|
|
21
|
-
# Money.parse('USD 1,234.56') #=> [USD 1234.56]
|
|
22
|
-
def parse(input, currency = nil)
|
|
23
|
-
raise ArgumentError, 'input must be a String' unless input.is_a?(String)
|
|
24
|
-
|
|
25
|
-
input = input.strip
|
|
26
|
-
raise ArgumentError, 'input cannot be empty' if input.empty?
|
|
27
|
-
|
|
28
|
-
currency = Mint.currency(currency) || parse_currency(input)
|
|
29
|
-
raise ArgumentError, "Currency [#{currency}] not registered" unless currency
|
|
30
|
-
|
|
31
|
-
amount = currency.normalize_amount(parse_amount(input))
|
|
32
|
-
Mint::Money.new(amount, currency)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
# Extracts a numeric value from input that should only contain an amount.
|
|
38
|
-
def parse_amount(input)
|
|
39
|
-
# Remove any charater that is not a digit, comma or period
|
|
40
|
-
numeric = input.scan(/[\d.,-]/).join
|
|
41
|
-
numeric = normalize_separators(numeric)
|
|
42
|
-
Rational(numeric)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def classify_separators(numeric)
|
|
46
|
-
case [numeric.count(','), numeric.count('.')]
|
|
47
|
-
in [0, 0] | [0, 1] then :decimal_period # e.g. "1500" or "34.21".
|
|
48
|
-
in [1, 0] then :decimal_comma # Only one comma: decimal (e.g. 19,99 or 1,234).
|
|
49
|
-
in [c, p] if c > 1 && p > 1 then :ambiguous # Both separators appear multiple times
|
|
50
|
-
in [c, p] if c > 0 && p > 0 then :mixed # Commas and dots: the rightmost one is the decimal separator.
|
|
51
|
-
else :thousands_only # Multiple of the same separator only (e.g. 1,234,567)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# Converts locale-specific decimal/thousand separators into a plain decimal string.
|
|
56
|
-
def normalize_separators(numeric)
|
|
57
|
-
case classify_separators(numeric)
|
|
58
|
-
when :decimal_period then numeric # Nothing to normalize (e.g. "1500" or "34.21").
|
|
59
|
-
when :decimal_comma then numeric.tr(',', '.') # Only one comma: decimal (e.g. 19,99 or 1,234).
|
|
60
|
-
when :thousands_only then numeric.delete(',.')
|
|
61
|
-
when :ambiguous then raise ArgumentError, "could not distinguish decimal and thousand separators in '#{numeric}'"
|
|
62
|
-
when :mixed # Commas and dots: the rightmost one is the decimal separator.
|
|
63
|
-
if numeric.rindex(',') > numeric.rindex('.')
|
|
64
|
-
numeric.delete('.').tr(',', '.')
|
|
65
|
-
else
|
|
66
|
-
numeric.delete(',')
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def parse_currency(input)
|
|
72
|
-
case input
|
|
73
|
-
when String
|
|
74
|
-
# Prefer an explicit ISO 4217 code (e.g. "USD 1,234.56") over symbol matching.
|
|
75
|
-
currency = Mint.currency(input[/\b([A-Z_]+)\b/, 1])
|
|
76
|
-
return currency if currency
|
|
77
|
-
|
|
78
|
-
# Fall back to registered symbols, longest first (HK$ before $).
|
|
79
|
-
CurrencyRegistry.currency_symbols.each do |symbol, currency|
|
|
80
|
-
return currency if input.include?(symbol)
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
raise ArgumentError, 'Currency could not be detected'
|
|
84
|
-
end
|
|
85
|
-
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|