40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
const PERSIAN_DIGITS = '۰۱۲۳۴۵۶۷۸۹';
|
||||
|
|
const ARABIC_DIGITS = '٠١٢٣٤٥٦٧٨٩';
|
|||
|
|
const INVISIBLE_CHARS = /[\u200c\u200d\u202a-\u202e\ufeff]/g;
|
|||
|
|
|
|||
|
|
export const IRAN_MOBILE_REGEX = /^09\d{9}$/;
|
|||
|
|
|
|||
|
|
function toAsciiDigits(value: string): string {
|
|||
|
|
return value.replace(/[۰-۹٠-٩]/g, (ch) => {
|
|||
|
|
const persian = PERSIAN_DIGITS.indexOf(ch);
|
|||
|
|
if (persian >= 0) return String(persian);
|
|||
|
|
const arabic = ARABIC_DIGITS.indexOf(ch);
|
|||
|
|
if (arabic >= 0) return String(arabic);
|
|||
|
|
return ch;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** Normalize Iranian mobile to 09xxxxxxxxx (11 digits). */
|
|||
|
|
export function normalizeIranMobile(raw: string): string {
|
|||
|
|
let mobile = toAsciiDigits(String(raw ?? '').trim());
|
|||
|
|
mobile = mobile.replace(INVISIBLE_CHARS, '');
|
|||
|
|
|
|||
|
|
let digits = mobile.replace(/\D/g, '');
|
|||
|
|
if (!digits) return '';
|
|||
|
|
|
|||
|
|
if (digits.startsWith('0098')) {
|
|||
|
|
digits = digits.slice(2);
|
|||
|
|
}
|
|||
|
|
if (digits.startsWith('98') && digits.length >= 12) {
|
|||
|
|
digits = `0${digits.slice(2)}`;
|
|||
|
|
} else if (digits.startsWith('9') && digits.length === 10) {
|
|||
|
|
digits = `0${digits}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return digits;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function isValidIranMobile(mobile: string): boolean {
|
|||
|
|
return IRAN_MOBILE_REGEX.test(mobile);
|
|||
|
|
}
|