ui-formatter 0.1.0 โ 0.1.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 +446 -1
- package/lib/index.js +94 -31
- package/package.json +1 -1
- package/src/index.ts +122 -29
package/README.md
CHANGED
|
@@ -1 +1,446 @@
|
|
|
1
|
-
# ui-formatter
|
|
1
|
+
# ui-formatter
|
|
2
|
+
|
|
3
|
+
A lightweight, zero-dependency TypeScript utility library for formatting dates, times, numbers, and phone numbers.
|
|
4
|
+
|
|
5
|
+
Designed for applications that require **high performance**, **small bundle size**, and **no external dependencies**.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- ๐ Zero dependencies
|
|
12
|
+
- โก High-performance implementations
|
|
13
|
+
- ๐
Date formatting
|
|
14
|
+
- ๐ Time formatting
|
|
15
|
+
- ๐ข Number formatting
|
|
16
|
+
- โ๏ธ Phone/Fax formatting
|
|
17
|
+
- ๐งน Phone normalization
|
|
18
|
+
- ๐ฏ TypeScript support
|
|
19
|
+
- ๐ Works in Browser and Node.js
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install ui-formatter
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
or
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
yarn add ui-formatter
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Quick Example
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import {
|
|
41
|
+
formatDate,
|
|
42
|
+
formatDateTime,
|
|
43
|
+
formatNumber,
|
|
44
|
+
formatInteger,
|
|
45
|
+
formatPhone
|
|
46
|
+
} from "ui-formatter"
|
|
47
|
+
|
|
48
|
+
const date = new Date()
|
|
49
|
+
|
|
50
|
+
formatDate(date, "MM/dd/yyyy")
|
|
51
|
+
// 07/02/2026
|
|
52
|
+
|
|
53
|
+
formatDateTime(date, "yyyy-MM-dd")
|
|
54
|
+
// 2026-07-02 14:35
|
|
55
|
+
|
|
56
|
+
formatNumber(1234567.89, 2)
|
|
57
|
+
// 1,234,567.89
|
|
58
|
+
|
|
59
|
+
formatInteger(1000000)
|
|
60
|
+
// 1,000,000
|
|
61
|
+
|
|
62
|
+
formatPhone("8005551234")
|
|
63
|
+
// 800 555-1234
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
# API
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Date Utilities
|
|
73
|
+
|
|
74
|
+
### getDateFormat()
|
|
75
|
+
|
|
76
|
+
Returns the default date format.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
const format = getDateFormat()
|
|
80
|
+
|
|
81
|
+
// M/d/yyyy
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### addDays()
|
|
87
|
+
|
|
88
|
+
Returns a new date with the specified number of days added.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const tomorrow = addDays(new Date(), 1)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
### formatDate()
|
|
97
|
+
|
|
98
|
+
Formats a Date using a custom format.
|
|
99
|
+
|
|
100
|
+
Supported tokens:
|
|
101
|
+
|
|
102
|
+
| Token | Description |
|
|
103
|
+
|--------|-------------|
|
|
104
|
+
| yyyy | 4-digit year |
|
|
105
|
+
| yy | 2-digit year |
|
|
106
|
+
| MM | 2-digit month |
|
|
107
|
+
| M | Month |
|
|
108
|
+
| dd | 2-digit day |
|
|
109
|
+
| d | Day |
|
|
110
|
+
|
|
111
|
+
Example
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
formatDate(new Date(), "yyyy-MM-dd")
|
|
115
|
+
|
|
116
|
+
// 2026-07-02
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### formatTime()
|
|
122
|
+
|
|
123
|
+
Returns
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
HH:mm
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Example
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
formatTime(new Date())
|
|
133
|
+
|
|
134
|
+
// 15:30
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
### formatLongTime()
|
|
140
|
+
|
|
141
|
+
Returns
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
HH:mm:ss
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Example
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
formatLongTime(new Date())
|
|
151
|
+
|
|
152
|
+
// 15:30:45
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
### formatFullTime()
|
|
158
|
+
|
|
159
|
+
Returns
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
HH:mm:ss.SSS
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Example
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
formatFullTime(new Date())
|
|
169
|
+
|
|
170
|
+
// 15:30:45.123
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### formatDateTime()
|
|
176
|
+
|
|
177
|
+
Formats
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
<Date> <HH:mm>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Example
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
formatDateTime(new Date(), "yyyy-MM-dd")
|
|
187
|
+
|
|
188
|
+
// 2026-07-02 15:30
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
### formatLongDateTime()
|
|
194
|
+
|
|
195
|
+
Formats
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
<Date> <HH:mm:ss>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
### formatFullDateTime()
|
|
204
|
+
|
|
205
|
+
Formats
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
<Date> <HH:mm:ss.SSS>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
### datetimeToString()
|
|
214
|
+
|
|
215
|
+
Converts a Date into ISO-like format.
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
datetimeToString(new Date())
|
|
219
|
+
|
|
220
|
+
// 2026-07-02T15:30:45
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### dateToString()
|
|
226
|
+
|
|
227
|
+
Returns a compact timestamp.
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
dateToString(new Date())
|
|
231
|
+
|
|
232
|
+
// 20260702153045
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Milliseconds may be included.
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
dateToString(new Date(), true)
|
|
239
|
+
|
|
240
|
+
// 20260702153045123
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
# Number Utilities
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### formatInteger()
|
|
250
|
+
|
|
251
|
+
Formats an integer with thousands separators.
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
formatInteger(123456789)
|
|
255
|
+
|
|
256
|
+
// 123,456,789
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Custom separator
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
formatInteger(123456789, ".")
|
|
263
|
+
|
|
264
|
+
// 123.456.789
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
### formatNumber()
|
|
270
|
+
|
|
271
|
+
Formats decimal numbers.
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
formatNumber(1234567.89, 2)
|
|
275
|
+
|
|
276
|
+
// 1,234,567.89
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Custom separators
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
formatNumber(
|
|
283
|
+
1234567.89,
|
|
284
|
+
2,
|
|
285
|
+
",",
|
|
286
|
+
"."
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
// 1.234.567,89
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
# Phone Utilities
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
### normalizePhone()
|
|
299
|
+
|
|
300
|
+
Removes all characters except digits and `+`.
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
normalizePhone("(800) 555-1234")
|
|
304
|
+
|
|
305
|
+
// 8005551234
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
### normalizeFax()
|
|
311
|
+
|
|
312
|
+
Alias of
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
normalizePhone()
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
### formatPhone()
|
|
321
|
+
|
|
322
|
+
Formats phone numbers into a readable representation.
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
formatPhone("8005551234")
|
|
326
|
+
|
|
327
|
+
// 800 555-1234
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Supports
|
|
331
|
+
|
|
332
|
+
- US numbers
|
|
333
|
+
- international numbers
|
|
334
|
+
- partial numbers
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
### formatFax()
|
|
339
|
+
|
|
340
|
+
Formats fax numbers.
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
formatFax("0212345678")
|
|
344
|
+
|
|
345
|
+
// 02-12345678
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
# Utility Functions
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
### isNotEmpty()
|
|
355
|
+
|
|
356
|
+
Checks whether an array or string is not empty.
|
|
357
|
+
|
|
358
|
+
```ts
|
|
359
|
+
isNotEmpty([])
|
|
360
|
+
|
|
361
|
+
// false
|
|
362
|
+
|
|
363
|
+
isNotEmpty("hello")
|
|
364
|
+
|
|
365
|
+
// true
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
### isChecked()
|
|
371
|
+
|
|
372
|
+
Utility for HTML templates.
|
|
373
|
+
|
|
374
|
+
```ts
|
|
375
|
+
isChecked(true)
|
|
376
|
+
|
|
377
|
+
// checked
|
|
378
|
+
|
|
379
|
+
isChecked(false)
|
|
380
|
+
|
|
381
|
+
// ""
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Can also compare string values.
|
|
385
|
+
|
|
386
|
+
```ts
|
|
387
|
+
isChecked("admin", "admin")
|
|
388
|
+
|
|
389
|
+
// checked
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
# Design Goals
|
|
395
|
+
|
|
396
|
+
This library is designed with the following principles:
|
|
397
|
+
|
|
398
|
+
- Zero runtime dependencies
|
|
399
|
+
- High performance
|
|
400
|
+
- Minimal allocations
|
|
401
|
+
- Small bundle size
|
|
402
|
+
- Predictable behavior
|
|
403
|
+
- Browser and Node compatibility
|
|
404
|
+
|
|
405
|
+
Several implementations avoid regular expressions and repeated string concatenation in favor of allocation-friendly algorithms.
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
# Performance
|
|
410
|
+
|
|
411
|
+
The library includes optimized implementations for:
|
|
412
|
+
|
|
413
|
+
- Manual date parsing
|
|
414
|
+
- Number formatting
|
|
415
|
+
- Integer formatting
|
|
416
|
+
- Phone normalization
|
|
417
|
+
|
|
418
|
+
Many functions use:
|
|
419
|
+
|
|
420
|
+
- single-pass parsing
|
|
421
|
+
- preallocated buffers
|
|
422
|
+
- minimal temporary objects
|
|
423
|
+
|
|
424
|
+
making them suitable for high-throughput applications.
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
# Browser Support
|
|
429
|
+
|
|
430
|
+
Works in:
|
|
431
|
+
|
|
432
|
+
- Chrome
|
|
433
|
+
- Firefox
|
|
434
|
+
- Safari
|
|
435
|
+
- Edge
|
|
436
|
+
- Node.js
|
|
437
|
+
- Bun
|
|
438
|
+
- Deno
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
# TypeScript
|
|
443
|
+
|
|
444
|
+
Fully written in TypeScript.
|
|
445
|
+
|
|
446
|
+
No additional typings are required.
|
package/lib/index.js
CHANGED
|
@@ -141,35 +141,88 @@ function pad3(n) {
|
|
|
141
141
|
}
|
|
142
142
|
return n < 10 ? "00" + n : "0" + n.toString();
|
|
143
143
|
}
|
|
144
|
-
function
|
|
145
|
-
if (
|
|
144
|
+
function formatInteger(v, groupSeparator) {
|
|
145
|
+
if (groupSeparator === void 0) { groupSeparator = ","; }
|
|
146
|
+
if (v == null || !Number.isFinite(v)) {
|
|
146
147
|
return "";
|
|
147
148
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
var isNegative = v < 0;
|
|
150
|
+
var n = Math.abs(Math.trunc(v));
|
|
151
|
+
if (n < 1000) {
|
|
152
|
+
return isNegative ? "-" + n : "" + n;
|
|
151
153
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
var buffer = new Array(32);
|
|
155
|
+
var i = buffer.length;
|
|
156
|
+
var digitCount = 0;
|
|
157
|
+
while (n > 0) {
|
|
158
|
+
if (digitCount > 0 && digitCount % 3 === 0) {
|
|
159
|
+
buffer[--i] = groupSeparator;
|
|
160
|
+
}
|
|
161
|
+
var digit = n % 10;
|
|
162
|
+
buffer[--i] = String.fromCharCode(48 + digit);
|
|
163
|
+
n = Math.floor(n / 10);
|
|
164
|
+
digitCount++;
|
|
165
|
+
}
|
|
166
|
+
if (isNegative) {
|
|
167
|
+
buffer[--i] = "-";
|
|
168
|
+
}
|
|
169
|
+
return buffer.slice(i).join("");
|
|
170
|
+
}
|
|
171
|
+
exports.formatInteger = formatInteger;
|
|
172
|
+
function formatNumber(v, precision, decimalSeparator, groupSeparator) {
|
|
173
|
+
if (precision === void 0) { precision = 0; }
|
|
174
|
+
if (v == null || !Number.isFinite(v)) {
|
|
175
|
+
return "";
|
|
154
176
|
}
|
|
155
|
-
var
|
|
156
|
-
var
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
177
|
+
var d = ".";
|
|
178
|
+
var g = ",";
|
|
179
|
+
if (decimalSeparator && groupSeparator) {
|
|
180
|
+
d = decimalSeparator;
|
|
181
|
+
g = groupSeparator;
|
|
182
|
+
}
|
|
183
|
+
else if (decimalSeparator && !groupSeparator) {
|
|
184
|
+
d = decimalSeparator;
|
|
185
|
+
if (d === "ูซ") {
|
|
186
|
+
g = "ูฌ";
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
g = d === "," ? "." : ",";
|
|
164
190
|
}
|
|
165
191
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
192
|
+
var negative = v < 0;
|
|
193
|
+
var s = Math.abs(v).toFixed(precision);
|
|
194
|
+
var dot = s.indexOf(".");
|
|
195
|
+
var intEnd = dot >= 0 ? dot : s.length;
|
|
196
|
+
var fracLen = dot >= 0 ? s.length - dot - 1 : 0;
|
|
197
|
+
var intLen = intEnd;
|
|
198
|
+
var groups = intLen > 3 ? ((intLen - 1) / 3) | 0 : 0;
|
|
199
|
+
var outLen = (negative ? 1 : 0) + intLen + groups * g.length + (fracLen > 0 ? d.length + fracLen : 0);
|
|
200
|
+
var out = new Array(outLen);
|
|
201
|
+
var p = 0;
|
|
202
|
+
if (negative) {
|
|
203
|
+
out[p++] = "-";
|
|
204
|
+
}
|
|
205
|
+
var firstGroup = intLen % 3;
|
|
206
|
+
if (firstGroup === 0) {
|
|
207
|
+
firstGroup = 3;
|
|
169
208
|
}
|
|
170
|
-
|
|
171
|
-
|
|
209
|
+
for (var i = 0; i < intLen; i++) {
|
|
210
|
+
if (i > 0 && (i === firstGroup || (i > firstGroup && (i - firstGroup) % 3 === 0))) {
|
|
211
|
+
for (var j = 0; j < g.length; j++) {
|
|
212
|
+
out[p++] = g[j];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
out[p++] = s[i];
|
|
216
|
+
}
|
|
217
|
+
if (fracLen > 0) {
|
|
218
|
+
for (var j = 0; j < d.length; j++) {
|
|
219
|
+
out[p++] = d[j];
|
|
220
|
+
}
|
|
221
|
+
for (var i = dot + 1; i < s.length; i++) {
|
|
222
|
+
out[p++] = s[i];
|
|
223
|
+
}
|
|
172
224
|
}
|
|
225
|
+
return out.join("");
|
|
173
226
|
}
|
|
174
227
|
exports.formatNumber = formatNumber;
|
|
175
228
|
var formatter = (function () {
|
|
@@ -180,7 +233,7 @@ var formatter = (function () {
|
|
|
180
233
|
return "";
|
|
181
234
|
}
|
|
182
235
|
var s = phone;
|
|
183
|
-
var x =
|
|
236
|
+
var x = normalizePhone(phone);
|
|
184
237
|
if (x.length === 10) {
|
|
185
238
|
var USNumber = x.match(formatter.usPhone);
|
|
186
239
|
if (USNumber != null) {
|
|
@@ -207,7 +260,7 @@ var formatter = (function () {
|
|
|
207
260
|
return "";
|
|
208
261
|
}
|
|
209
262
|
var s = fax;
|
|
210
|
-
var x =
|
|
263
|
+
var x = normalizeFax(fax);
|
|
211
264
|
var l = x.length;
|
|
212
265
|
if (l <= 6) {
|
|
213
266
|
s = x;
|
|
@@ -232,20 +285,30 @@ var formatter = (function () {
|
|
|
232
285
|
}
|
|
233
286
|
return s;
|
|
234
287
|
};
|
|
235
|
-
formatter.fax = / |\-|\.|\(|\)/g;
|
|
236
|
-
formatter.phone = / |\-|\.|\(|\)/g;
|
|
237
288
|
formatter.usPhone = /(\d{3})(\d{3})(\d{4})/;
|
|
238
289
|
return formatter;
|
|
239
290
|
}());
|
|
240
291
|
exports.formatter = formatter;
|
|
241
|
-
function
|
|
242
|
-
|
|
292
|
+
function normalizePhone(s) {
|
|
293
|
+
if (!s) {
|
|
294
|
+
return "";
|
|
295
|
+
}
|
|
296
|
+
var len = s.length;
|
|
297
|
+
var buf = new Array(len);
|
|
298
|
+
var j = 0;
|
|
299
|
+
for (var i = 0; i < len; i++) {
|
|
300
|
+
var c = s.charCodeAt(i);
|
|
301
|
+
if ((c >= 48 && c <= 57) || c === 43) {
|
|
302
|
+
buf[j++] = s[i];
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return j === len ? buf.join("") : buf.slice(0, j).join("");
|
|
243
306
|
}
|
|
244
|
-
exports.
|
|
245
|
-
function
|
|
246
|
-
return
|
|
307
|
+
exports.normalizePhone = normalizePhone;
|
|
308
|
+
function normalizeFax(fax) {
|
|
309
|
+
return normalizePhone(fax);
|
|
247
310
|
}
|
|
248
|
-
exports.
|
|
311
|
+
exports.normalizeFax = normalizeFax;
|
|
249
312
|
function formatPhone(phone) {
|
|
250
313
|
return formatter.formatPhone(phone);
|
|
251
314
|
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -140,40 +140,121 @@ function pad3(n: number): string {
|
|
|
140
140
|
return n < 10 ? "00" + n : "0" + n.toString()
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
export function
|
|
144
|
-
if (v == null) {
|
|
143
|
+
export function formatInteger(v: number | null | undefined, groupSeparator: string = ","): any {
|
|
144
|
+
if (v == null || !Number.isFinite(v)) {
|
|
145
145
|
return ""
|
|
146
146
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
|
|
148
|
+
const isNegative = v < 0
|
|
149
|
+
let n = Math.abs(Math.trunc(v))
|
|
150
|
+
|
|
151
|
+
// Fast path
|
|
152
|
+
if (n < 1000) {
|
|
153
|
+
return isNegative ? `-${n}` : `${n}`
|
|
152
154
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
155
|
+
|
|
156
|
+
// Max length:
|
|
157
|
+
// digits (up to 16 for JS safe int) + separators (~5) + sign
|
|
158
|
+
const buffer = new Array(32)
|
|
159
|
+
let i = buffer.length
|
|
160
|
+
|
|
161
|
+
let digitCount = 0
|
|
162
|
+
|
|
163
|
+
while (n > 0) {
|
|
164
|
+
// Insert separator every 3 digits
|
|
165
|
+
if (digitCount > 0 && digitCount % 3 === 0) {
|
|
166
|
+
buffer[--i] = groupSeparator
|
|
162
167
|
}
|
|
168
|
+
|
|
169
|
+
const digit = n % 10
|
|
170
|
+
buffer[--i] = String.fromCharCode(48 + digit)
|
|
171
|
+
|
|
172
|
+
n = Math.floor(n / 10) // safe version
|
|
173
|
+
digitCount++
|
|
163
174
|
}
|
|
164
|
-
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
} else {
|
|
168
|
-
return arr.reverse().join("") + d + x[1]
|
|
175
|
+
|
|
176
|
+
if (isNegative) {
|
|
177
|
+
buffer[--i] = "-"
|
|
169
178
|
}
|
|
179
|
+
|
|
180
|
+
// Slice only used portion and join once
|
|
181
|
+
return buffer.slice(i).join("")
|
|
182
|
+
}
|
|
183
|
+
export function formatNumber(v?: number | null, precision = 0, decimalSeparator?: string | null, groupSeparator?: string | null): any {
|
|
184
|
+
if (v == null || !Number.isFinite(v)) {
|
|
185
|
+
return ""
|
|
186
|
+
}
|
|
187
|
+
let d = "."
|
|
188
|
+
let g = ","
|
|
189
|
+
if (decimalSeparator && groupSeparator) {
|
|
190
|
+
d = decimalSeparator
|
|
191
|
+
g = groupSeparator
|
|
192
|
+
} else if (decimalSeparator && !groupSeparator) {
|
|
193
|
+
d = decimalSeparator
|
|
194
|
+
if (d === "ูซ") {
|
|
195
|
+
g = "ูฌ"
|
|
196
|
+
} else {
|
|
197
|
+
g = d === "," ? "." : ","
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const negative = v < 0
|
|
201
|
+
|
|
202
|
+
// unavoidable allocation
|
|
203
|
+
const s = Math.abs(v).toFixed(precision)
|
|
204
|
+
|
|
205
|
+
const dot = s.indexOf(".")
|
|
206
|
+
|
|
207
|
+
const intEnd = dot >= 0 ? dot : s.length
|
|
208
|
+
const fracLen = dot >= 0 ? s.length - dot - 1 : 0
|
|
209
|
+
|
|
210
|
+
const intLen = intEnd
|
|
211
|
+
const groups = intLen > 3 ? ((intLen - 1) / 3) | 0 : 0
|
|
212
|
+
|
|
213
|
+
const outLen = (negative ? 1 : 0) + intLen + groups * g.length + (fracLen > 0 ? d.length + fracLen : 0)
|
|
214
|
+
|
|
215
|
+
const out = new Array<string>(outLen)
|
|
216
|
+
|
|
217
|
+
let p = 0
|
|
218
|
+
|
|
219
|
+
if (negative) {
|
|
220
|
+
out[p++] = "-"
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// integer part
|
|
224
|
+
let firstGroup = intLen % 3
|
|
225
|
+
if (firstGroup === 0) {
|
|
226
|
+
firstGroup = 3
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
for (let i = 0; i < intLen; i++) {
|
|
230
|
+
if (i > 0 && (i === firstGroup || (i > firstGroup && (i - firstGroup) % 3 === 0))) {
|
|
231
|
+
for (let j = 0; j < g.length; j++) {
|
|
232
|
+
out[p++] = g[j]
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
out[p++] = s[i]
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// fractional part
|
|
240
|
+
if (fracLen > 0) {
|
|
241
|
+
for (let j = 0; j < d.length; j++) {
|
|
242
|
+
out[p++] = d[j]
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
for (let i = dot + 1; i < s.length; i++) {
|
|
246
|
+
out[p++] = s[i]
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return out.join("")
|
|
170
251
|
}
|
|
171
252
|
|
|
172
253
|
// tslint:disable-next-line:class-name
|
|
173
254
|
export class formatter {
|
|
174
255
|
// private static _preg = / |\+|\-|\.|\(|\)/g;
|
|
175
|
-
static fax = / |\-|\.|\(|\)/g
|
|
176
|
-
static phone = / |\-|\.|\(|\)/g
|
|
256
|
+
// static fax = / |\-|\.|\(|\)/g
|
|
257
|
+
// static phone = / |\-|\.|\(|\)/g
|
|
177
258
|
static usPhone = /(\d{3})(\d{3})(\d{4})/
|
|
178
259
|
static formatPhone(phone?: string | null): string {
|
|
179
260
|
if (!phone) {
|
|
@@ -182,7 +263,7 @@ export class formatter {
|
|
|
182
263
|
// reformat phone number
|
|
183
264
|
// 555 123-4567 or (+1) 555 123-4567
|
|
184
265
|
let s = phone
|
|
185
|
-
const x =
|
|
266
|
+
const x = normalizePhone(phone)
|
|
186
267
|
if (x.length === 10) {
|
|
187
268
|
const USNumber = x.match(formatter.usPhone)
|
|
188
269
|
if (USNumber != null) {
|
|
@@ -208,7 +289,7 @@ export class formatter {
|
|
|
208
289
|
// reformat phone number
|
|
209
290
|
// 035-456745 or 02-1234567
|
|
210
291
|
let s = fax
|
|
211
|
-
const x =
|
|
292
|
+
const x = normalizeFax(fax)
|
|
212
293
|
const l = x.length
|
|
213
294
|
if (l <= 6) {
|
|
214
295
|
s = x
|
|
@@ -230,11 +311,23 @@ export class formatter {
|
|
|
230
311
|
return s
|
|
231
312
|
}
|
|
232
313
|
}
|
|
233
|
-
export function
|
|
234
|
-
|
|
314
|
+
export function normalizePhone(s?: string | null): string {
|
|
315
|
+
if (!s) {
|
|
316
|
+
return ""
|
|
317
|
+
}
|
|
318
|
+
const len = s.length
|
|
319
|
+
const buf = new Array<string>(len)
|
|
320
|
+
let j = 0
|
|
321
|
+
for (let i = 0; i < len; i++) {
|
|
322
|
+
const c = s.charCodeAt(i)
|
|
323
|
+
if ((c >= 48 && c <= 57) || c === 43) {
|
|
324
|
+
buf[j++] = s[i]
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return j === len ? buf.join("") : buf.slice(0, j).join("")
|
|
235
328
|
}
|
|
236
|
-
export function
|
|
237
|
-
return
|
|
329
|
+
export function normalizeFax(fax?: string): string {
|
|
330
|
+
return normalizePhone(fax)
|
|
238
331
|
}
|
|
239
332
|
export function formatPhone(phone?: string | null): string {
|
|
240
333
|
return formatter.formatPhone(phone)
|