-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Expand file tree
/
Copy pathisCurrency.js
More file actions
executable file
·105 lines (94 loc) · 3.73 KB
/
isCurrency.js
File metadata and controls
executable file
·105 lines (94 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import merge from './util/merge';
import assertString from './util/assertString';
/**
* Returns valid whole dollar amount patterns based on thousands_separator_mode.
* @param {string} mode - 'required', 'allowed', or 'forbidden'
* @param {string} withoutSep - regex pattern for amounts without separators
* @param {string} withSep - regex pattern for amounts with separators
* @returns {string[]} array of valid regex patterns
*/
function getValidWholeAmounts(mode, withoutSep, withSep) {
switch (mode) {
case 'required':
// For amounts >= 1000, require separators. Amounts 0-999 don't need them.
return ['0', '[1-9]\\d{0,2}', withSep];
case 'forbidden':
// Never allow thousands separators
return ['0', withoutSep];
case 'allowed':
default:
// Allow both with and without separators (current default behavior)
return ['0', withoutSep, withSep];
}
}
function currencyRegex(options) {
let decimal_digits = `\\d{${options.digits_after_decimal[0]}}`;
options.digits_after_decimal.forEach((digit, index) => { if (index !== 0) decimal_digits = `${decimal_digits}|\\d{${digit}}`; });
const symbol =
`(${options.symbol.replace(/\W/, m => `\\${m}`)})${(options.require_symbol ? '' : '?')}`,
negative = '-?',
whole_dollar_amount_without_sep = '[1-9]\\d*',
whole_dollar_amount_with_sep = `[1-9]\\d{0,2}(\\${options.thousands_separator}\\d{3})*`,
valid_whole_dollar_amounts = getValidWholeAmounts(
options.thousands_separator_mode,
whole_dollar_amount_without_sep,
whole_dollar_amount_with_sep
),
whole_dollar_amount = `(${valid_whole_dollar_amounts.join('|')})?`,
decimal_amount = `(\\${options.decimal_separator}(${decimal_digits}))${options.require_decimal ? '' : '?'}`;
let pattern = whole_dollar_amount + (options.allow_decimal || options.require_decimal ? decimal_amount : '');
// default is negative sign before symbol, but there are two other options (besides parens)
if (options.allow_negatives && !options.parens_for_negatives) {
if (options.negative_sign_after_digits) {
pattern += negative;
} else if (options.negative_sign_before_digits) {
pattern = negative + pattern;
}
}
// South African Rand, for example, uses R 123 (space) and R-123 (no space)
if (options.allow_negative_sign_placeholder) {
pattern = `( (?!\\-))?${pattern}`;
} else if (options.allow_space_after_symbol) {
pattern = ` ?${pattern}`;
} else if (options.allow_space_after_digits) {
pattern += '( (?!$))?';
}
if (options.symbol_after_digits) {
pattern += symbol;
} else {
pattern = symbol + pattern;
}
if (options.allow_negatives) {
if (options.parens_for_negatives) {
pattern = `(\\(${pattern}\\)|${pattern})`;
} else if (!(options.negative_sign_before_digits || options.negative_sign_after_digits)) {
pattern = negative + pattern;
}
}
// ensure there's a dollar and/or decimal amount, and that
// it doesn't start with a space or a negative sign followed by a space
return new RegExp(`^(?!-? )(?=.*\\d)${pattern}$`);
}
const default_currency_options = {
symbol: '$',
require_symbol: false,
allow_space_after_symbol: false,
symbol_after_digits: false,
allow_negatives: true,
parens_for_negatives: false,
negative_sign_before_digits: false,
negative_sign_after_digits: false,
allow_negative_sign_placeholder: false,
thousands_separator: ',',
decimal_separator: '.',
allow_decimal: true,
require_decimal: false,
digits_after_decimal: [2],
allow_space_after_digits: false,
thousands_separator_mode: 'allowed',
};
export default function isCurrency(str, options) {
assertString(str);
options = merge(options, default_currency_options);
return currencyRegex(options).test(str);
}