UNPKG

@beenotung/tslib

Version:
403 lines (402 loc) 11.5 kB
"use strict"; /** ******************************** * Combined for multiple countries * ***********************************/ Object.defineProperty(exports, "__esModule", { value: true }); exports.is_mobile_phone = is_mobile_phone; exports.to_full_mobile_phone = to_full_mobile_phone; exports.format_mobile_phone = format_mobile_phone; exports.is_hk_mobile_phone_prefix = is_hk_mobile_phone_prefix; exports.is_hk_mobile_phone = is_hk_mobile_phone; exports.to_full_hk_mobile_phone = to_full_hk_mobile_phone; exports.format_hk_mobile_phone = format_hk_mobile_phone; exports.is_sg_mobile_phone_prefix = is_sg_mobile_phone_prefix; exports.is_sg_mobile_phone = is_sg_mobile_phone; exports.to_full_sg_mobile_phone = to_full_sg_mobile_phone; exports.format_sg_mobile_phone = format_sg_mobile_phone; exports.is_au_mobile_phone_prefix = is_au_mobile_phone_prefix; exports.is_au_mobile_phone = is_au_mobile_phone; exports.to_full_au_mobile_phone = to_full_au_mobile_phone; exports.format_au_mobile_phone = format_au_mobile_phone; exports.is_cn_mobile_phone_prefix = is_cn_mobile_phone_prefix; exports.is_cn_mobile_phone = is_cn_mobile_phone; exports.to_full_cn_mobile_phone = to_full_cn_mobile_phone; exports.format_cn_mobile_phone = format_cn_mobile_phone; exports.is_mo_mobile_phone_prefix = is_mo_mobile_phone_prefix; exports.is_mo_mobile_phone = is_mo_mobile_phone; exports.to_full_mo_mobile_phone = to_full_mo_mobile_phone; exports.format_mo_mobile_phone = format_mo_mobile_phone; exports.format_tel_with_pattern = format_tel_with_pattern; function is_mobile_phone(tel) { return to_full_mobile_phone(tel) !== ''; } /** * check if the tel is mobile phone number in: * - HK (Hong Kong) * - SG (Singapore) * - AU (Australia) * - CN (China Mainland) * - MO (Macau) * * @returns the full tel number with country code, or empty string if not valid */ function to_full_mobile_phone(tel) { return (to_full_hk_mobile_phone(tel) || to_full_sg_mobile_phone(tel) || to_full_au_mobile_phone(tel) || to_full_cn_mobile_phone(tel) || to_full_mo_mobile_phone(tel) || ''); } /** * format the mobile phone number with pattern if valid: * - HK: +852 xxxx yyyy * - SG: +65 xxxx yyyy * - AU: +61 4xx xxx xxx * - CN: +86 1nn xxxx xxxx * - MO: +853 xxxx yyyy */ function format_mobile_phone(tel) { tel = to_full_mobile_phone(tel); if (!tel) return tel; if (tel.startsWith('+852')) { return format_hk_mobile_phone(tel); } if (tel.startsWith('+65')) { return format_sg_mobile_phone(tel); } if (tel.startsWith('+61')) { return format_au_mobile_phone(tel); } if (tel.startsWith('+86')) { return format_cn_mobile_phone(tel); } if (tel.startsWith('+853')) { return format_mo_mobile_phone(tel); } throw new Error(`not supported mobile phone number: ${tel}`); } /** ****************************** * Hong Kong mobile phone number * *********************************/ /** * 4, 7, 8 heading are allowed since 2018 * news: https://skypost.ulifestyle.com.hk/article/2006268/ * */ function is_hk_mobile_phone_prefix(tel) { tel = tel.replace(/^\+852/, '').trim(); switch (tel[0]) { case '4': case '5': case '6': case '7': case '8': case '9': return true; default: return false; } } /** * with/without +852 prefix * */ function is_hk_mobile_phone(tel) { return to_full_hk_mobile_phone(tel) !== ''; } /** * very forgiving * * @return +852xxxxyyyy if valid * empty string if not valid * */ function to_full_hk_mobile_phone(tel) { if (typeof tel === 'number') { tel = tel.toString(); } tel = tel .split('') .filter(x => '0' <= x && x <= '9') .join(''); if (tel.length === 8 && is_hk_mobile_phone_prefix(tel)) { return '+852' + tel; } if (tel.length === 8 + 3 && tel.startsWith('852') && is_hk_mobile_phone_prefix(tel.substring(3))) { return '+' + tel; } if (tel.length === 8 + 4 && tel.startsWith('+852') && is_hk_mobile_phone_prefix(tel.substring(4))) { return tel; } return ''; } /** * @returns +852 xxxx yyyy if valid */ function format_hk_mobile_phone(tel) { tel = to_full_hk_mobile_phone(tel); if (!tel) return tel; return format_tel_with_pattern(tel, '+852 xxxx yyyy'); } /** ****************************** * Singapore mobile phone number * *********************************/ /** * starts with 8, 9 * reference: https://en.wikipedia.org/wiki/Telephone_numbers_in_Singapore */ function is_sg_mobile_phone_prefix(tel) { tel = tel.replace(/^\+65/, '').trim(); switch (tel[0]) { case '8': case '9': return true; default: return false; } } /** * with/without +65 prefix */ function is_sg_mobile_phone(tel) { return to_full_sg_mobile_phone(tel) !== ''; } /** * very forgiving * * @returns +65xxxxyyyy if valid * empty string if not valid */ function to_full_sg_mobile_phone(tel) { tel = to_tel_digits(tel); if (tel.length === 8 && is_sg_mobile_phone_prefix(tel)) { return '+65' + tel; } if (tel.length === 8 + 2 && tel.startsWith('65') && is_sg_mobile_phone_prefix(tel.substring(2))) { return '+' + tel; } if (tel.length === 8 + 3 && tel.startsWith('+65') && is_sg_mobile_phone_prefix(tel.substring(3))) { return tel; } return ''; } /** * @returns +65 xxxx yyyy if valid */ function format_sg_mobile_phone(tel) { tel = to_full_sg_mobile_phone(tel); if (!tel) return tel; return format_tel_with_pattern(tel, '+65 xxxx yyyy'); } /** ****************************** * Australia mobile phone number * *********************************/ function is_au_mobile_phone_prefix(tel) { tel = tel.replace(/^\+61/, '').trim(); return tel.startsWith('4') || tel.startsWith('04'); } /** * with/without +61 prefix */ function is_au_mobile_phone(tel) { return to_full_au_mobile_phone(tel) !== ''; } /** * landline number example: * excluding area code: xxxx xxxx * including area code: (07) xxxx xxxx * including country and area code: +61 7 xxxx xxxx * the area code can be 2-digit, being "0x", or 1 digit, being "1" * * mobile number example: * country code: +61 * mobile prefix: e.g. starting with 4 (area and operator code) * local number: 8 digits * * Within Australia, mobile phone numbers begin with 04– the Australian national trunk code 0, * plus the mobile indicator 4 – followed by eight digits. * * This is generally written as 04XX XXX XXX within Australia, * or as +61 4XX XXX XXX for an international audience. * * reference: https://en.wikipedia.org/wiki/Telephone_numbers_in_Australia */ function to_full_au_mobile_phone(tel) { tel = to_tel_digits(tel); if (tel.length == 8 + 4 && tel.startsWith('+614')) { return tel; } if (tel.length == 8 + 3 && tel.startsWith('614')) { return '+' + tel; } if (tel.length == 8 + 2 && tel.startsWith('04')) { return '+614' + tel.substring(2); } return ''; } function format_au_mobile_phone(tel) { tel = to_full_au_mobile_phone(tel); if (!tel) return tel; return format_tel_with_pattern(tel, '+61 4xx xxx xxx'); } /** ************************** * China mobile phone number * *****************************/ /** * starts with 1, second digit is 3,4, 5, 6, 7, 8 * reference: https://en.wikipedia.org/wiki/Telephone_numbers_in_China */ function is_cn_mobile_phone_prefix(tel) { tel = tel.replace(/^\+86/, '').trim(); if (tel.length < 2) return false; if (tel[0] !== '1') return false; const secondDigit = tel[1]; return ['3', '4', '5', '6', '7', '8', '9'].includes(secondDigit); } /** * with/without +86 prefix */ function is_cn_mobile_phone(tel) { return to_full_cn_mobile_phone(tel) !== ''; } /** * @returns +86xxxxxxxxxx if valid * empty string if not valid * * should be 1xx-XXXX-XXXX (except for 140–144, which are 13-digit IoT numbers) * in which the first three digits (13x to 19x) designate the mobile phone service provider. */ function to_full_cn_mobile_phone(tel) { tel = to_tel_digits(tel); // 11 digits starting with 1 (local format) if (tel.length === 11 && is_cn_mobile_phone_prefix(tel)) { return '+86' + tel; } // 11 digits with country code 86 (without +) if (tel.length === 11 + 2 && tel.startsWith('86') && is_cn_mobile_phone_prefix(tel.substring(2))) { return '+' + tel; } // 11 digits with country code +86 if (tel.length === 11 + 3 && tel.startsWith('+86') && is_cn_mobile_phone_prefix(tel.substring(3))) { return tel; } return ''; } /** * @returns +86 1nn xxxx xxxx if valid */ function format_cn_mobile_phone(tel) { tel = to_full_cn_mobile_phone(tel); if (!tel) return tel; return format_tel_with_pattern(tel, '+86 1nn xxxx xxxx'); } /** ****************************** * Macau mobile phone number * *********************************/ /** * starts with 6 * news: https://en.wikipedia.org/wiki/Telephone_numbers_in_Macau * */ function is_mo_mobile_phone_prefix(tel) { tel = tel.replace(/^\+853/, '').trim(); switch (tel[0]) { case '6': return true; default: return false; } } /** * with/without +853 prefix * */ function is_mo_mobile_phone(tel) { return to_full_mo_mobile_phone(tel) !== ''; } /** * very forgiving * * @return +853xxxxyyyy if valid * empty string if not valid * */ function to_full_mo_mobile_phone(tel) { tel = to_tel_digits(tel); if (tel.length === 8 && is_mo_mobile_phone_prefix(tel)) { return '+853' + tel; } if (tel.length === 8 + 3 && tel.startsWith('853') && is_mo_mobile_phone_prefix(tel.substring(3))) { return '+' + tel; } if (tel.length === 8 + 4 && tel.startsWith('+853') && is_mo_mobile_phone_prefix(tel.substring(4))) { return tel; } return ''; } /** * @returns +853 xxxx yyyy if valid */ function format_mo_mobile_phone(tel) { tel = to_full_mo_mobile_phone(tel); if (!tel) return tel; return format_tel_with_pattern(tel, '+853 xxxx yyyy'); } /** ***************** * helper functions * ********************/ /** * helper function to format tel with pattern */ function format_tel_with_pattern(tel, pattern) { tel = to_tel_digits(tel); if (!tel) return tel; const expectedLength = pattern.replaceAll(' ', '').length; if (tel.length != expectedLength) { throw new Error(`invalid length, expect length ${expectedLength} but got length ${tel.length}`); } let offset = 0; return pattern .split(' ') .map(pattern => { const length = pattern.length; const part = tel.slice(offset, offset + length); offset += length; return part; }) .join(' '); } /** * remove space, hyphen, bracket, etc. * * preserve only digits and + */ function to_tel_digits(tel) { if (typeof tel === 'number') { tel = tel.toString(); } return tel .split('') .filter(x => x == '+' || ('0' <= x && x <= '9')) .join(''); }