1
0
forked from Yara724/api
Files
yara724-api/src/utils/unicode-digits.ts
2026-05-20 11:08:47 +03:30

55 lines
1.9 KiB
TypeScript

function unicodeCharToAsciiDigit(ch: string): string {
if (ch >= "0" && ch <= "9") return ch;
const cp = ch.codePointAt(0)!;
if (cp >= 0x06f0 && cp <= 0x06f9) return String(cp - 0x06f0);
if (cp >= 0x0660 && cp <= 0x0669) return String(cp - 0x0660);
if (cp >= 0x0966 && cp <= 0x096f) return String(cp - 0x0966);
if (cp >= 0xff10 && cp <= 0xff19) return String(cp - 0xff10);
const folded = ch.normalize("NFKC");
if (folded.length === 1 && folded >= "0" && folded <= "9") return folded;
return ch;
}
/**
* Convert decimal digits in any Unicode script (Persian, Arabic-Indic, etc.)
* to ASCII `0-9`. Other characters are left unchanged.
*/
export function normalizeUnicodeDigitsToEnglish(input: string): string {
return Array.from(input).map(unicodeCharToAsciiDigit).join("");
}
/** Strip grouping separators after digit normalization (for money fields). */
export function normalizeMoneyAmountString(input: string): string {
return normalizeUnicodeDigitsToEnglish(input)
.trim()
.replace(/[,،\u066C\u060C]/g, "");
}
/** Parse a money string to a whole **Toman** amount, or `null` if invalid. */
export function parseMoneyAmountToman(value: unknown): number | null {
if (value == null || value === "") return null;
const n = normalizeMoneyAmountString(String(value));
if (!/^\d+$/.test(n)) return null;
const num = Number(n);
if (!Number.isFinite(num)) return null;
return num;
}
export function normalizeUnicodeDigitsDeep<T>(value: T): T {
if (value == null) return value;
if (typeof value === "string") {
return normalizeUnicodeDigitsToEnglish(value) as T;
}
if (Array.isArray(value)) {
return value.map((item) => normalizeUnicodeDigitsDeep(item)) as T;
}
if (typeof value === "object") {
const out: Record<string, unknown> = {};
for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
out[k] = normalizeUnicodeDigitsDeep(v);
}
return out as T;
}
return value;
}