Skip to content

Commit ae5dd20

Browse files
committed
feat(mask): Transform unicode digits codepoint to ASCII numbers
1 parent 7962650 commit ae5dd20

File tree

1 file changed

+42
-20
lines changed

1 file changed

+42
-20
lines changed

src/components/mask-input/mask-parser.ts

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,47 @@ type MaskReplaceResult = {
3030
const MASK_FLAGS = new Set('aACL09#&?');
3131
const MASK_REQUIRED_FLAGS = new Set('0#LA&');
3232

33+
const DIGIT_ZERO_CODEPOINTS = [
34+
0x0030, // ASCII
35+
0x0660, // Arabic-Indic
36+
0x06f0, // Extended Arabic-Indic
37+
0x0966, // Devanagari
38+
0x09e6, // Bengali
39+
0x0a66, // Gurmukhi
40+
0x0ae6, // Gujarati
41+
0x0b66, // Oriya
42+
0x0c66, // Telugu
43+
0x0ce6, // Kannada
44+
0x0d66, // Malayalam
45+
0x0e50, // Thai
46+
0x0ed0, // Lao
47+
0x0f20, // Tibetan
48+
0x1040, // Myanmar
49+
0x17e0, // Khmer
50+
0x1810, // Mongolian
51+
0xff10, // Full-width
52+
] as const;
53+
54+
function replaceUnicodeNumbers(text: string): string {
55+
const matcher = /\p{Nd}/gu;
56+
const ascii_zero = 0x0030;
57+
58+
return text.replace(matcher, (digit) => {
59+
let digitValue = 0;
60+
const codePoint = digit.charCodeAt(0);
61+
62+
for (const zeroCodePoint of DIGIT_ZERO_CODEPOINTS) {
63+
if (codePoint >= zeroCodePoint && codePoint <= zeroCodePoint + 9) {
64+
digitValue = zeroCodePoint;
65+
break;
66+
}
67+
}
68+
69+
digitValue = codePoint - digitValue;
70+
return String.fromCharCode(ascii_zero + digitValue);
71+
});
72+
}
73+
3374
const MASK_PATTERNS = new Map([
3475
['C', /(?!^$)/u], // Non-empty (any character that is not an empty string)
3576
['&', /[^\p{Separator}]/u], // Any non-whitespace character (Unicode-aware)
@@ -42,25 +83,6 @@ const MASK_PATTERNS = new Map([
4283
['#', /[\p{Number}\-+]/u], // Numeric and sign characters (+, -)
4384
]);
4485

45-
function replaceIMENumbers(string: string): string {
46-
return string.replace(
47-
/[]/g,
48-
(num) =>
49-
({
50-
'1': '1',
51-
'2': '2',
52-
'3': '3',
53-
'4': '4',
54-
'5': '5',
55-
'6': '6',
56-
'7': '7',
57-
'8': '8',
58-
'9': '9',
59-
'0': '0',
60-
})[num] as string
61-
);
62-
}
63-
6486
function validate(char: string, flag: string): boolean {
6587
return MASK_PATTERNS.get(flag)?.test(char) ?? false;
6688
}
@@ -265,7 +287,7 @@ export class MaskParser {
265287
// Initialize the array for the masked string or get a fresh mask with prompts and/or literals
266288
const maskedChars = Array.from(maskString || this.apply(''));
267289

268-
const inputChars = Array.from(replaceIMENumbers(value));
290+
const inputChars = Array.from(replaceUnicodeNumbers(value));
269291
const inputLength = inputChars.length;
270292

271293
// Clear any non-literal positions from `start` to `endBoundary`

0 commit comments

Comments
 (0)