reduce-precision 1.0.0 → 1.0.2
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.
- package/README.md +10 -13
- package/lib/format/index.d.ts +43 -0
- package/lib/format/index.js +467 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +8 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ const formatter = new NumberFormatter();
|
|
|
41
41
|
formatter.setLanguage('en', { prefixMarker: 'strong', prefix: 'USD ' });
|
|
42
42
|
|
|
43
43
|
console.log(formatter.toHtmlString(123456789));
|
|
44
|
-
console.log(formatter.
|
|
44
|
+
console.log(formatter.toJson(123456789));
|
|
45
45
|
console.log(formatter.toString(123456789));
|
|
46
46
|
```
|
|
47
47
|
|
|
@@ -55,7 +55,7 @@ const formatter = new NumberFormatter();
|
|
|
55
55
|
formatter.setLanguage('en', { prefixMarker: 'strong', prefix: 'USD ' });
|
|
56
56
|
|
|
57
57
|
console.log(formatter.toHtmlString(123456789));
|
|
58
|
-
console.log(formatter.
|
|
58
|
+
console.log(formatter.toJson(123456789));
|
|
59
59
|
console.log(formatter.toString(123456789));
|
|
60
60
|
```
|
|
61
61
|
|
|
@@ -97,20 +97,20 @@ const formatterWithOptions = new NumberFormatter({
|
|
|
97
97
|
formatter.setLanguage('en');
|
|
98
98
|
|
|
99
99
|
// Basic number formatting
|
|
100
|
-
formatter.
|
|
100
|
+
formatter.toJson(1234.5678); // Output: { value: '1,234.6', ... }
|
|
101
101
|
|
|
102
102
|
// Formatting with medium precision
|
|
103
|
-
formatter.setTemplate('number', 'medium').
|
|
103
|
+
formatter.setTemplate('number', 'medium').toJson(1234.5678); // Output: { value: '1.23K', ... }
|
|
104
104
|
|
|
105
105
|
// Formatting as USD
|
|
106
|
-
formatter.setTemplate('usd', 'high').
|
|
106
|
+
formatter.setTemplate('usd', 'high').toJson(1234.5678); // Output: { value: '$1,234.6', ... }
|
|
107
107
|
|
|
108
108
|
// Formatting as Iranian Rial with Persian numerals
|
|
109
|
-
formatterWithOptions.
|
|
109
|
+
formatterWithOptions.toJson(1234.5678);
|
|
110
110
|
// Output: { value: 'مبلغ: ۱٫۲۳ هزار ت', ... }
|
|
111
111
|
|
|
112
112
|
// Formatting as a percentage with low precision
|
|
113
|
-
formatter.setTemplate('percent', 'low').
|
|
113
|
+
formatter.setTemplate('percent', 'low').toJson(0.1234); // Output: { value: '0.12%', ... }
|
|
114
114
|
|
|
115
115
|
// Formatting with HTML output and custom markers
|
|
116
116
|
|
|
@@ -119,7 +119,7 @@ formatter.setLanguage('en', { prefixMarker: 'strong', prefix: 'USD ' }).toHtmlSt
|
|
|
119
119
|
|
|
120
120
|
// Formatting with string input for small or big numbers
|
|
121
121
|
|
|
122
|
-
formatter.setTemplate('usd', 'medium').
|
|
122
|
+
formatter.setTemplate('usd', 'medium').toJson("0.00000000000000000000005678521");
|
|
123
123
|
// Output: { value: '$0.0₂₂5678', ... }
|
|
124
124
|
```
|
|
125
125
|
|
|
@@ -136,10 +136,6 @@ interface FormattedObject {
|
|
|
136
136
|
postfix: string; // The postfix string
|
|
137
137
|
sign: string; // The sign of the number (either an empty string or '-')
|
|
138
138
|
wholeNumber: string; // The whole number part of the value
|
|
139
|
-
fractionalPart: string; // The complete fractional part of the value
|
|
140
|
-
fractionalNonZeros: string; // The non-zero digits in the fractional part
|
|
141
|
-
fractionalZerosCount: number; // The count of zeros in the fractional part
|
|
142
|
-
unit: string; // The unit postfix
|
|
143
139
|
}
|
|
144
140
|
```
|
|
145
141
|
|
|
@@ -173,7 +169,7 @@ Sets the template and precision for the formatter.
|
|
|
173
169
|
|
|
174
170
|
Returns the `NumberFormatter` instance for method chaining.
|
|
175
171
|
|
|
176
|
-
#### `
|
|
172
|
+
#### `toJson(input: string | number): FormattedObject`
|
|
177
173
|
|
|
178
174
|
Formats the input number and returns the formatted object.
|
|
179
175
|
|
|
@@ -200,3 +196,4 @@ Contributions are welcome! If you find a bug or have a feature request, please o
|
|
|
200
196
|
## License
|
|
201
197
|
|
|
202
198
|
This project is licensed under the [MIT License](LICENSE).
|
|
199
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
declare type Template = 'number' | 'usd' | 'irt' | 'irr' | 'percent';
|
|
2
|
+
declare type Precision = 'auto' | 'high' | 'medium' | 'low';
|
|
3
|
+
declare type Language = 'en' | 'fa';
|
|
4
|
+
declare type OutputFormat = 'plain' | 'html' | 'markdown';
|
|
5
|
+
interface Options {
|
|
6
|
+
precision?: Precision;
|
|
7
|
+
template?: Template;
|
|
8
|
+
language?: Language;
|
|
9
|
+
outputFormat?: OutputFormat;
|
|
10
|
+
prefixMarker?: string;
|
|
11
|
+
postfixMarker?: string;
|
|
12
|
+
prefix?: string;
|
|
13
|
+
postfix?: string;
|
|
14
|
+
}
|
|
15
|
+
interface FormattedObject {
|
|
16
|
+
value?: string;
|
|
17
|
+
prefix: string;
|
|
18
|
+
postfix: string;
|
|
19
|
+
sign: string;
|
|
20
|
+
wholeNumber: string;
|
|
21
|
+
}
|
|
22
|
+
interface LanguageConfig {
|
|
23
|
+
prefixMarker?: string;
|
|
24
|
+
postfixMarker?: string;
|
|
25
|
+
prefix?: string;
|
|
26
|
+
postfix?: string;
|
|
27
|
+
}
|
|
28
|
+
declare class NumberFormatter {
|
|
29
|
+
private options;
|
|
30
|
+
constructor(options?: Options);
|
|
31
|
+
setLanguage(lang: Language, config?: LanguageConfig): NumberFormatter;
|
|
32
|
+
setTemplate(template: Template, precision: Precision): NumberFormatter;
|
|
33
|
+
toJson(input: string | number): FormattedObject;
|
|
34
|
+
toString(input: string | number): string;
|
|
35
|
+
toPlainString(input: string | number): string;
|
|
36
|
+
toHtmlString(input: string | number): string;
|
|
37
|
+
toMdString(input: string | number): string;
|
|
38
|
+
private isENotation;
|
|
39
|
+
private format;
|
|
40
|
+
private convertENotationToRegularNumber;
|
|
41
|
+
private reducePrecision;
|
|
42
|
+
}
|
|
43
|
+
export default NumberFormatter;
|
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class NumberFormatter {
|
|
4
|
+
constructor(options = {}) {
|
|
5
|
+
this.options = {
|
|
6
|
+
language: 'en',
|
|
7
|
+
template: 'number',
|
|
8
|
+
precision: 'high',
|
|
9
|
+
outputFormat: 'plain',
|
|
10
|
+
prefixMarker: 'i',
|
|
11
|
+
postfixMarker: 'i',
|
|
12
|
+
prefix: '',
|
|
13
|
+
postfix: '',
|
|
14
|
+
};
|
|
15
|
+
this.options = Object.assign(Object.assign({}, this.options), options);
|
|
16
|
+
}
|
|
17
|
+
setLanguage(lang, config = {}) {
|
|
18
|
+
this.options.language = lang;
|
|
19
|
+
this.options.prefixMarker =
|
|
20
|
+
config.prefixMarker || this.options.prefixMarker;
|
|
21
|
+
this.options.postfixMarker =
|
|
22
|
+
config.postfixMarker || this.options.postfixMarker;
|
|
23
|
+
this.options.prefix = config.prefix || this.options.prefix;
|
|
24
|
+
this.options.postfix = config.postfix || this.options.postfix;
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
setTemplate(template, precision) {
|
|
28
|
+
this.options.template = template;
|
|
29
|
+
this.options.precision = precision;
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
toJson(input) {
|
|
33
|
+
const formattedObject = this.format(input);
|
|
34
|
+
delete formattedObject.value;
|
|
35
|
+
return formattedObject;
|
|
36
|
+
}
|
|
37
|
+
toString(input) {
|
|
38
|
+
const formattedObject = this.format(input);
|
|
39
|
+
return formattedObject.value || '';
|
|
40
|
+
}
|
|
41
|
+
toPlainString(input) {
|
|
42
|
+
this.options.outputFormat = 'plain';
|
|
43
|
+
const formattedObject = this.format(input);
|
|
44
|
+
return formattedObject.value || '';
|
|
45
|
+
}
|
|
46
|
+
toHtmlString(input) {
|
|
47
|
+
this.options.outputFormat = 'html';
|
|
48
|
+
const formattedObject = this.format(input);
|
|
49
|
+
return formattedObject.value || '';
|
|
50
|
+
}
|
|
51
|
+
toMdString(input) {
|
|
52
|
+
this.options.outputFormat = 'markdown';
|
|
53
|
+
const formattedObject = this.format(input);
|
|
54
|
+
return formattedObject.value || '';
|
|
55
|
+
}
|
|
56
|
+
// Private methods...
|
|
57
|
+
isENotation(input) {
|
|
58
|
+
return /^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)$/.test(input);
|
|
59
|
+
}
|
|
60
|
+
format(input) {
|
|
61
|
+
let { precision, template } = this.options;
|
|
62
|
+
const { language, outputFormat, prefixMarker, postfixMarker, prefix, postfix, } = this.options;
|
|
63
|
+
if (!input)
|
|
64
|
+
return {};
|
|
65
|
+
if (!(template === null || template === void 0 ? void 0 : template.match(/^(number|usd|irt|irr|percent)$/g)))
|
|
66
|
+
template = 'number';
|
|
67
|
+
if (this.isENotation(input.toString())) {
|
|
68
|
+
input = this.convertENotationToRegularNumber(Number(input));
|
|
69
|
+
}
|
|
70
|
+
// Replace each Persian/Arabic numeral in the string with its English counterpart and strip all non-numeric chars
|
|
71
|
+
let numberString = input
|
|
72
|
+
.toString()
|
|
73
|
+
.replace(/[\u0660-\u0669\u06F0-\u06F9]/g, function (match) {
|
|
74
|
+
return String(match.charCodeAt(0) & 0xf);
|
|
75
|
+
})
|
|
76
|
+
.replace(/[^\d.-]/g, '');
|
|
77
|
+
// Stripping leading zeros and trailing zeros after a decimal point
|
|
78
|
+
numberString = numberString
|
|
79
|
+
.replace(/^0+(?=\d)/g, '')
|
|
80
|
+
.replace(/(?<=\.\d*)0+$|(?<=\.\d)0+\b/g, '');
|
|
81
|
+
const number = Math.abs(Number(numberString));
|
|
82
|
+
let p, d, r, c;
|
|
83
|
+
let f = 0;
|
|
84
|
+
// Auto precision selection
|
|
85
|
+
if (precision === 'auto') {
|
|
86
|
+
if (template.match(/^(usd|irt|irr)$/g)) {
|
|
87
|
+
if (number >= 0.0001 && number < 100000000000) {
|
|
88
|
+
precision = 'high';
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
precision = 'medium';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else if (template === 'number') {
|
|
95
|
+
precision = 'medium';
|
|
96
|
+
}
|
|
97
|
+
else if (template === 'percent') {
|
|
98
|
+
precision = 'low';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (precision === 'medium') {
|
|
102
|
+
if (number >= 0 && number < 0.0001) {
|
|
103
|
+
p = 33;
|
|
104
|
+
d = 4;
|
|
105
|
+
r = false;
|
|
106
|
+
c = true;
|
|
107
|
+
}
|
|
108
|
+
else if (number >= 0.0001 && number < 0.001) {
|
|
109
|
+
p = 7;
|
|
110
|
+
d = 4;
|
|
111
|
+
r = false;
|
|
112
|
+
c = false;
|
|
113
|
+
}
|
|
114
|
+
else if (number >= 0.001 && number < 0.01) {
|
|
115
|
+
p = 5;
|
|
116
|
+
d = 3;
|
|
117
|
+
r = false;
|
|
118
|
+
c = false;
|
|
119
|
+
}
|
|
120
|
+
else if (number >= 0.001 && number < 0.1) {
|
|
121
|
+
p = 3;
|
|
122
|
+
d = 2;
|
|
123
|
+
r = false;
|
|
124
|
+
c = false;
|
|
125
|
+
}
|
|
126
|
+
else if (number >= 0.1 && number < 1) {
|
|
127
|
+
p = 1;
|
|
128
|
+
d = 1;
|
|
129
|
+
r = false;
|
|
130
|
+
c = false;
|
|
131
|
+
}
|
|
132
|
+
else if (number >= 1 && number < 10) {
|
|
133
|
+
p = 3;
|
|
134
|
+
d = 3;
|
|
135
|
+
r = false;
|
|
136
|
+
c = false;
|
|
137
|
+
}
|
|
138
|
+
else if (number >= 10 && number < 100) {
|
|
139
|
+
p = 2;
|
|
140
|
+
d = 2;
|
|
141
|
+
r = false;
|
|
142
|
+
c = false;
|
|
143
|
+
}
|
|
144
|
+
else if (number >= 100 && number < 1000) {
|
|
145
|
+
p = 1;
|
|
146
|
+
d = 1;
|
|
147
|
+
r = false;
|
|
148
|
+
c = false;
|
|
149
|
+
}
|
|
150
|
+
else if (number >= 1000) {
|
|
151
|
+
const x = Math.floor(Math.log10(number)) % 3;
|
|
152
|
+
p = 2 - x;
|
|
153
|
+
d = 2 - x;
|
|
154
|
+
r = true;
|
|
155
|
+
c = true;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
p = 0;
|
|
159
|
+
d = 0;
|
|
160
|
+
r = true;
|
|
161
|
+
c = true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else if (precision === 'low') {
|
|
165
|
+
if (number >= 0 && number < 0.01) {
|
|
166
|
+
p = 2;
|
|
167
|
+
d = 0;
|
|
168
|
+
r = true;
|
|
169
|
+
c = false;
|
|
170
|
+
f = 2;
|
|
171
|
+
}
|
|
172
|
+
else if (number >= 0.01 && number < 0.1) {
|
|
173
|
+
p = 2;
|
|
174
|
+
d = 1;
|
|
175
|
+
r = true;
|
|
176
|
+
c = false;
|
|
177
|
+
}
|
|
178
|
+
else if (number >= 0.1 && number < 1) {
|
|
179
|
+
p = 2;
|
|
180
|
+
d = 2;
|
|
181
|
+
r = true;
|
|
182
|
+
c = false;
|
|
183
|
+
}
|
|
184
|
+
else if (number >= 1 && number < 10) {
|
|
185
|
+
p = 2;
|
|
186
|
+
d = 2;
|
|
187
|
+
r = true;
|
|
188
|
+
c = false;
|
|
189
|
+
f = 2;
|
|
190
|
+
}
|
|
191
|
+
else if (number >= 10 && number < 100) {
|
|
192
|
+
p = 1;
|
|
193
|
+
d = 1;
|
|
194
|
+
r = true;
|
|
195
|
+
c = false;
|
|
196
|
+
f = 1;
|
|
197
|
+
}
|
|
198
|
+
else if (number >= 100 && number < 1000) {
|
|
199
|
+
p = 0;
|
|
200
|
+
d = 0;
|
|
201
|
+
r = true;
|
|
202
|
+
c = false;
|
|
203
|
+
}
|
|
204
|
+
else if (number >= 1000) {
|
|
205
|
+
const x = Math.floor(Math.log10(number)) % 3;
|
|
206
|
+
p = 1 - x;
|
|
207
|
+
d = 1 - x;
|
|
208
|
+
r = true;
|
|
209
|
+
c = true;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
p = 0;
|
|
213
|
+
d = 0;
|
|
214
|
+
r = true;
|
|
215
|
+
c = true;
|
|
216
|
+
f = 2;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
// precision === "high"
|
|
221
|
+
if (number >= 0 && number < 1) {
|
|
222
|
+
p = 33;
|
|
223
|
+
d = 4;
|
|
224
|
+
r = false;
|
|
225
|
+
c = false;
|
|
226
|
+
}
|
|
227
|
+
else if (number >= 1 && number < 10) {
|
|
228
|
+
p = 3;
|
|
229
|
+
d = 3;
|
|
230
|
+
r = true;
|
|
231
|
+
c = false;
|
|
232
|
+
}
|
|
233
|
+
else if (number >= 10 && number < 100) {
|
|
234
|
+
p = 2;
|
|
235
|
+
d = 2;
|
|
236
|
+
r = true;
|
|
237
|
+
c = false;
|
|
238
|
+
}
|
|
239
|
+
else if (number >= 100 && number < 1000) {
|
|
240
|
+
p = 2;
|
|
241
|
+
d = 2;
|
|
242
|
+
r = true;
|
|
243
|
+
c = false;
|
|
244
|
+
}
|
|
245
|
+
else if (number >= 1000 && number < 10000) {
|
|
246
|
+
p = 1;
|
|
247
|
+
d = 1;
|
|
248
|
+
r = true;
|
|
249
|
+
c = false;
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
p = 0;
|
|
253
|
+
d = 0;
|
|
254
|
+
r = true;
|
|
255
|
+
c = false;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return this.reducePrecision(numberString, p, d, r, c, f, template, language, outputFormat, prefixMarker, postfixMarker, prefix, postfix);
|
|
259
|
+
}
|
|
260
|
+
convertENotationToRegularNumber(eNotation) {
|
|
261
|
+
const [coefficientStr, exponentStr] = eNotation.toString().split('e');
|
|
262
|
+
const coefficientLength = coefficientStr
|
|
263
|
+
.replace('.', '')
|
|
264
|
+
.replace('-', '').length;
|
|
265
|
+
const exponent = parseFloat(exponentStr);
|
|
266
|
+
const precision = Math.max(coefficientLength - exponent, 1);
|
|
267
|
+
return eNotation.toFixed(precision);
|
|
268
|
+
}
|
|
269
|
+
reducePrecision(numberString, precision = 30, nonZeroDigits = 4, round = false, compress = false, fixedDecimalZeros = 0, template = 'number', language = 'en', outputFormat = 'plain', prefixMarker = 'span', postfixMarker = 'span', prefix = '', postfix = '') {
|
|
270
|
+
var _a;
|
|
271
|
+
if (!numberString) {
|
|
272
|
+
return {};
|
|
273
|
+
}
|
|
274
|
+
numberString = numberString.toString();
|
|
275
|
+
const maxPrecision = 30;
|
|
276
|
+
const maxIntegerDigits = 21;
|
|
277
|
+
const scaleUnits = template.match(/^(number|percent)$/g)
|
|
278
|
+
? {
|
|
279
|
+
'': '',
|
|
280
|
+
K: ' هزار',
|
|
281
|
+
M: ' میلیون',
|
|
282
|
+
B: ' میلیارد',
|
|
283
|
+
T: ' تریلیون',
|
|
284
|
+
Qd: ' کادریلیون',
|
|
285
|
+
Qt: ' کنتیلیون',
|
|
286
|
+
}
|
|
287
|
+
: {
|
|
288
|
+
'': '',
|
|
289
|
+
K: ' هزار ت',
|
|
290
|
+
M: ' میلیون ت',
|
|
291
|
+
B: ' میلیارد ت',
|
|
292
|
+
T: ' همت',
|
|
293
|
+
Qd: ' هزار همت',
|
|
294
|
+
Qt: ' میلیون همت',
|
|
295
|
+
};
|
|
296
|
+
let parts = /^(-)?(\d+)\.?([0]*)(\d*)$/g.exec(numberString);
|
|
297
|
+
if (!parts) {
|
|
298
|
+
return {};
|
|
299
|
+
}
|
|
300
|
+
const sign = parts[1] || '';
|
|
301
|
+
let nonFractionalStr = parts[2];
|
|
302
|
+
let fractionalZeroStr = parts[3];
|
|
303
|
+
let fractionalNonZeroStr = parts[4];
|
|
304
|
+
let unitPrefix = '';
|
|
305
|
+
let unitPostfix = '';
|
|
306
|
+
if (fractionalZeroStr.length >= maxPrecision) {
|
|
307
|
+
// Number is smaller than maximum precision
|
|
308
|
+
fractionalZeroStr = '0'.padEnd(maxPrecision - 1, '0');
|
|
309
|
+
fractionalNonZeroStr = '1';
|
|
310
|
+
}
|
|
311
|
+
else if (fractionalZeroStr.length + nonZeroDigits > precision) {
|
|
312
|
+
// decrease non-zero digits
|
|
313
|
+
nonZeroDigits = precision - fractionalZeroStr.length;
|
|
314
|
+
if (nonZeroDigits < 1)
|
|
315
|
+
nonZeroDigits = 1;
|
|
316
|
+
}
|
|
317
|
+
else if (nonFractionalStr.length > maxIntegerDigits) {
|
|
318
|
+
nonFractionalStr = '0';
|
|
319
|
+
fractionalZeroStr = '';
|
|
320
|
+
fractionalNonZeroStr = '';
|
|
321
|
+
}
|
|
322
|
+
// compress large numbers
|
|
323
|
+
if (compress && nonFractionalStr.length >= 4) {
|
|
324
|
+
const scaleUnitKeys = Object.keys(scaleUnits);
|
|
325
|
+
let scaledWholeNumber = nonFractionalStr;
|
|
326
|
+
let unitIndex = 0;
|
|
327
|
+
while (+scaledWholeNumber > 999 && unitIndex < scaleUnitKeys.length - 1) {
|
|
328
|
+
scaledWholeNumber = (+scaledWholeNumber / 1000).toFixed(2);
|
|
329
|
+
unitIndex++;
|
|
330
|
+
}
|
|
331
|
+
unitPostfix = scaleUnitKeys[unitIndex];
|
|
332
|
+
parts = /^(-)?(\d+)\.?([0]*)(\d*)$/g.exec(scaledWholeNumber.toString());
|
|
333
|
+
if (!parts) {
|
|
334
|
+
return {};
|
|
335
|
+
}
|
|
336
|
+
// sign = parts[1] || "";
|
|
337
|
+
nonFractionalStr = parts[2];
|
|
338
|
+
fractionalZeroStr = parts[3];
|
|
339
|
+
fractionalNonZeroStr = parts[4];
|
|
340
|
+
}
|
|
341
|
+
// Truncate the fractional part or round it
|
|
342
|
+
// if (precision > 0 && nonZeroDigits > 0 && fractionalNonZeroStr.length > nonZeroDigits) {
|
|
343
|
+
if (fractionalNonZeroStr.length > nonZeroDigits) {
|
|
344
|
+
if (!round) {
|
|
345
|
+
fractionalNonZeroStr = fractionalNonZeroStr.substring(0, nonZeroDigits);
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
if (parseInt(fractionalNonZeroStr[nonZeroDigits]) < 5) {
|
|
349
|
+
fractionalNonZeroStr = fractionalNonZeroStr.substring(0, nonZeroDigits);
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
fractionalNonZeroStr = (parseInt(fractionalNonZeroStr.substring(0, nonZeroDigits)) + 1).toString();
|
|
353
|
+
// If overflow occurs (e.g., 999 + 1 = 1000), adjust the substring length
|
|
354
|
+
if (fractionalNonZeroStr.length > nonZeroDigits) {
|
|
355
|
+
if (fractionalZeroStr.length > 0) {
|
|
356
|
+
fractionalZeroStr = fractionalZeroStr.substring(0, fractionalZeroStr.length - 1);
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
nonFractionalStr = (Number(nonFractionalStr) + 1).toString();
|
|
360
|
+
fractionalNonZeroStr = fractionalNonZeroStr.substring(1);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// Using dex style
|
|
367
|
+
if (compress && fractionalZeroStr !== '' && unitPostfix === '') {
|
|
368
|
+
fractionalZeroStr =
|
|
369
|
+
'0' +
|
|
370
|
+
fractionalZeroStr.length.toString().replace(/\d/g, function (match) {
|
|
371
|
+
return [
|
|
372
|
+
'₀',
|
|
373
|
+
'₁',
|
|
374
|
+
'₂',
|
|
375
|
+
'₃',
|
|
376
|
+
'₄',
|
|
377
|
+
'₅',
|
|
378
|
+
'₆',
|
|
379
|
+
'₇',
|
|
380
|
+
'₈',
|
|
381
|
+
'₉',
|
|
382
|
+
][parseInt(match, 10)];
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
let fractionalPartStr = `${fractionalZeroStr}${fractionalNonZeroStr}`;
|
|
386
|
+
fractionalPartStr = fractionalPartStr.substring(0, precision);
|
|
387
|
+
fractionalPartStr = fractionalPartStr.replace(/^(\d*[1-9])0+$/g, '$1');
|
|
388
|
+
// Output Formating, Prefix, Postfix
|
|
389
|
+
if (template === 'usd') {
|
|
390
|
+
unitPrefix = language === 'en' ? '$' : '';
|
|
391
|
+
if (!unitPostfix)
|
|
392
|
+
unitPostfix = language === 'fa' ? ' دلار' : '';
|
|
393
|
+
}
|
|
394
|
+
else if (template === 'irr') {
|
|
395
|
+
if (!unitPostfix)
|
|
396
|
+
unitPostfix = language === 'fa' ? ' ر' : ' R';
|
|
397
|
+
}
|
|
398
|
+
else if (template === 'irt') {
|
|
399
|
+
if (!unitPostfix)
|
|
400
|
+
unitPostfix = language === 'fa' ? ' ت' : ' T';
|
|
401
|
+
}
|
|
402
|
+
else if (template === 'percent') {
|
|
403
|
+
if (language === 'en') {
|
|
404
|
+
unitPostfix += '%';
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
unitPostfix += !unitPostfix ? '٪' : ' درصد';
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
unitPrefix = prefix + unitPrefix;
|
|
411
|
+
unitPostfix += postfix;
|
|
412
|
+
if (outputFormat === 'html') {
|
|
413
|
+
if (unitPrefix)
|
|
414
|
+
unitPrefix = `<${prefixMarker}>${unitPrefix}</${prefixMarker}>`;
|
|
415
|
+
if (unitPostfix)
|
|
416
|
+
unitPostfix = `<${postfixMarker}>${unitPostfix}</${postfixMarker}>`;
|
|
417
|
+
}
|
|
418
|
+
else if (outputFormat === 'markdown') {
|
|
419
|
+
if (unitPrefix)
|
|
420
|
+
unitPrefix = `${prefixMarker}${unitPrefix}${prefixMarker}`;
|
|
421
|
+
if (unitPostfix)
|
|
422
|
+
unitPostfix = `${postfixMarker}${unitPostfix}${postfixMarker}`;
|
|
423
|
+
}
|
|
424
|
+
const thousandSeparatorRegex = /\B(?=(\d{3})+(?!\d))/g;
|
|
425
|
+
const fixedDecimalZeroStr = fixedDecimalZeros
|
|
426
|
+
? '.'.padEnd(fixedDecimalZeros + 1, '0')
|
|
427
|
+
: '';
|
|
428
|
+
let out = '';
|
|
429
|
+
let wholeNumberStr;
|
|
430
|
+
if (precision <= 0 || nonZeroDigits <= 0 || !fractionalNonZeroStr) {
|
|
431
|
+
wholeNumberStr = `${nonFractionalStr.replace(thousandSeparatorRegex, ',')}${fixedDecimalZeroStr}`;
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
wholeNumberStr = `${nonFractionalStr.replace(thousandSeparatorRegex, ',')}.${fractionalPartStr}`;
|
|
435
|
+
}
|
|
436
|
+
out = `${sign}${unitPrefix}${wholeNumberStr}${unitPostfix}`;
|
|
437
|
+
const formattedObject = {
|
|
438
|
+
value: out,
|
|
439
|
+
prefix: unitPrefix,
|
|
440
|
+
postfix: unitPostfix,
|
|
441
|
+
sign: sign,
|
|
442
|
+
wholeNumber: wholeNumberStr,
|
|
443
|
+
};
|
|
444
|
+
// Convert output to Persian numerals if language is "fa"
|
|
445
|
+
if (language === 'fa') {
|
|
446
|
+
formattedObject.value = ((_a = formattedObject === null || formattedObject === void 0 ? void 0 : formattedObject.value) !== null && _a !== void 0 ? _a : '')
|
|
447
|
+
.replace(/[0-9]/g, c => String.fromCharCode(c.charCodeAt(0) + 1728))
|
|
448
|
+
.replace(/,/g, '٬')
|
|
449
|
+
.replace(/\./g, '٫')
|
|
450
|
+
.replace(/(K|M|B|T|Qt|Qd)/g, function (c) {
|
|
451
|
+
return String(scaleUnits[c]);
|
|
452
|
+
});
|
|
453
|
+
formattedObject.postfix = formattedObject.postfix
|
|
454
|
+
.replace(/[0-9]/g, c => String.fromCharCode(c.charCodeAt(0) + 1728))
|
|
455
|
+
.replace(/(K|M|B|T|Qt|Qd)/g, function (c) {
|
|
456
|
+
return String(scaleUnits[c]);
|
|
457
|
+
});
|
|
458
|
+
formattedObject.wholeNumber = formattedObject.wholeNumber
|
|
459
|
+
.replace(/[0-9]/g, c => String.fromCharCode(c.charCodeAt(0) + 1728))
|
|
460
|
+
.replace(/(K|M|B|T|Qt|Qd)/g, function (c) {
|
|
461
|
+
return String(scaleUnits[c]);
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
return formattedObject;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
exports.default = NumberFormatter;
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.NumberFormatter = void 0;
|
|
7
|
+
const format_1 = __importDefault(require("./format"));
|
|
8
|
+
exports.NumberFormatter = format_1.default;
|