Skip to content

Commit

Permalink
If a number is in an unexpected format, fallback to a standard (sanit…
Browse files Browse the repository at this point in the history
…ized) number (#18)
  • Loading branch information
imbrianj authored Nov 1, 2024
1 parent 398f701 commit aaa4867
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 16 deletions.
13 changes: 11 additions & 2 deletions src/__tests__/base.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,20 +220,29 @@ describe('Phone number pretty formatting', () => {
format: findPhoneFormat({ regionCode: '57', e164: '+573211234567' }),
},
germany: {
e164: '+49 170 87654321',
e164: '+4917087654321',
regionCode: '49',
format: findPhoneFormat({ regionCode: '49', e164: '+4917087654321' }),
},
germanyAlt: {
e164: '+49 170 8765432',
e164: '+491708765432',
regionCode: '49',
format: findPhoneFormat({ regionCode: '49', e164: '+491708765432' }),
},
norwayUnexpected: {
e164: '+47174087654',
regionCode: '47',
format: findPhoneFormat({ regionCode: '47', e164: '+471740876543' }),
},
};

expect(formatPhoneNumber(testNumbers.nullCase)).toBe(null);
expect(formatPhoneNumber(testNumbers.us)).toBe('(310) 349-6200');
expect(formatPhoneNumber(testNumbers.colombia)).toBe('+57 321 123 4567');
expect(formatPhoneNumber(testNumbers.germanyAlt)).toBe('+49 17 08765432');
// This looks like a Norwegian number, but doesn't match a known format. In this case, we'll return a sanitized generic format.
expect(formatPhoneNumber(testNumbers.norwayUnexpected)).toBe(
'+47174087654',
);
});
});
26 changes: 12 additions & 14 deletions src/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,18 +234,6 @@ export const getPhoneParts = (phoneNumber) => {
phoneParts.e164 = formatPhoneNumberForE164(phoneParts);
phoneParts.format = findPhoneFormat(phoneParts);
phoneParts.formattedNumber = formatPhoneNumber(phoneParts);

// If there are left over x's, the formatting ran into something unexpected.
// This may be ok depending on the region and their phone number formats.
// But it does mean we don't want to display this number.
if (
phoneParts.formattedNumber &&
phoneParts.formattedNumber.indexOf('x') !== -1
) {
// Since `rawNumber` isn't sanitized, we'll use a simple format that we
// are assured to be safe.
phoneParts.formattedNumber = strippedPhoneNumber;
}
}

return phoneParts;
Expand Down Expand Up @@ -353,16 +341,26 @@ export const findPhoneFormat = ({ regionCode, e164 }) => {
* @param {Object} params - The parameters for formatting the phone number.
* @param {string} params.format - The desired format for the phone number. Example: `(xxx) xxx-xxxx`.
* @param {string} params.e164 - The E.164 formatted phone number to format. Example: `+12065551234`.
* @param {string} params.regionCode - The region code of the phone number. Example, the US would be "1".
* @returns {string|null} The formatted phone number, or null if the E.164 number or format is not provided.
*/
export const formatPhoneNumber = ({ format, e164 }) => {
export const formatPhoneNumber = ({ format, e164, regionCode }) => {
let formattedNumber = '';

if (e164 && format) {
// Remove the leading '+' and let the format handle it.
const strippedPhone = e164.replace(/\D/g, '');
const strippedPhone = e164.replace(/\+/g, '');
let phoneIndex = strippedPhone.length - 1;

// The US / NANP rarely includes region code prefix when sharing numbers. Other regions often do, so we'll have a special condition to allow ignoring of the region code for region 1.
// For other regions, we'll return the stripped number to safely display the presumed good number that may be in a safe but not-ideal format.
if (
regionCode !== '1' &&
strippedPhone.length !== format.split('x').length - 1
) {
return e164;
}

// Traverse backward so we can omit country code in some formats (like US).
for (let i = format.length; i >= 0; i--) {
if (format[i]) {
Expand Down

0 comments on commit aaa4867

Please sign in to comment.