libphonenumber-js
Version:
A simpler (and smaller) rewrite of Google Android's popular libphonenumber library
227 lines (188 loc) • 7.7 kB
JavaScript
import _getIterator from 'babel-runtime/core-js/get-iterator';
// This is a port of Google Android `libphonenumber`'s
// `phonenumberutil.js` of 17th November, 2016.
//
// https://github.com/googlei18n/libphonenumber/commits/master/javascript/i18n/phonenumbers/phonenumberutil.js
import { matches_entirely } from './common';
import { parse_phone_number_and_country_phone_code } from './parse';
import { get_phone_code, get_formats, get_format_pattern, get_format_format, get_format_leading_digits_patterns, get_format_national_prefix_formatting_rule, get_format_national_prefix_is_optional_when_formatting, get_format_international_format, get_metadata_by_country_phone_code } from './metadata';
// Formats a phone number
//
// Example use cases:
//
// ```js
// format('8005553535', 'RU', 'International')
// format('8005553535', 'RU', 'International', metadata)
// format({ phone: '8005553535', country: 'RU' }, 'International')
// format({ phone: '8005553535', country: 'RU' }, 'International', metadata)
// format('+78005553535', 'National')
// format('+78005553535', 'National', metadata)
// ```
//
export default function format(first_argument, second_argument, third_argument, fourth_argument) {
var _sort_out_arguments = sort_out_arguments(first_argument, second_argument, third_argument, fourth_argument),
input = _sort_out_arguments.input,
format_type = _sort_out_arguments.format_type,
metadata = _sort_out_arguments.metadata;
var country_metadata = void 0;
if (input.country) {
country_metadata = metadata.countries[input.country];
}
var _parse_phone_number_a = parse_phone_number_and_country_phone_code(input.phone, metadata),
country_phone_code = _parse_phone_number_a.country_phone_code,
number = _parse_phone_number_a.number;
if (country_phone_code) {
// Check country restriction
if (input.country && country_metadata && country_phone_code !== get_phone_code(country_metadata)) {
return input.phone;
}
country_metadata = get_metadata_by_country_phone_code(country_phone_code, metadata);
}
if (!country_metadata) {
return input.phone;
}
switch (format_type) {
case 'International':
if (!number) {
return '+' + get_phone_code(country_metadata);
}
var national_number = format_national_number(number, 'International', false, country_metadata);
return '+' + get_phone_code(country_metadata) + ' ' + national_number;
case 'International_plaintext':
return '+' + get_phone_code(country_metadata) + input.phone;
case 'National':
if (!number) {
return '';
}
return format_national_number(number, 'National', false, country_metadata);
}
}
// This was originally set to $1 but there are some countries for which the
// first group is not used in the national pattern (e.g. Argentina) so the $1
// group does not match correctly. Therefore, we use \d, so that the first
// group actually used in the pattern will be matched.
export var FIRST_GROUP_PATTERN = /(\$\d)/;
export function format_national_number_using_format(number, format, international, enforce_national_prefix, country_metadata) {
var format_pattern_matcher = new RegExp(get_format_pattern(format));
var national_prefix_formatting_rule = get_format_national_prefix_formatting_rule(format, country_metadata);
// National prefix is omitted if there's no national prefix formatting rule
// set for this country, or when this rule is set but
// national prefix is optional for this phone number format
// (and it is not enforced explicitly)
var national_prefix_may_be_omitted = !national_prefix_formatting_rule || national_prefix_formatting_rule && get_format_national_prefix_is_optional_when_formatting(format, country_metadata) && !enforce_national_prefix;
if (!international && !national_prefix_may_be_omitted) {
return number.replace(format_pattern_matcher, get_format_format(format).replace(FIRST_GROUP_PATTERN, national_prefix_formatting_rule));
}
var formatted_number = number.replace(format_pattern_matcher, international ? get_format_international_format(format) : get_format_format(format));
if (international) {
return local_to_international_style(formatted_number);
}
return formatted_number;
}
export function format_national_number(number, format_as, enforce_national_prefix, country_metadata) {
var format = choose_format_for_number(get_formats(country_metadata), number);
if (!format) {
return number;
}
return format_national_number_using_format(number, format, format_as === 'International', enforce_national_prefix, country_metadata);
}
export function choose_format_for_number(available_formats, national_number) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = _getIterator(available_formats), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _format = _step.value;
// Validate leading digits
if (get_format_leading_digits_patterns(_format).length > 0) {
// The last leading_digits_pattern is used here, as it is the most detailed
var last_leading_digits_pattern = get_format_leading_digits_patterns(_format)[get_format_leading_digits_patterns(_format).length - 1];
// If leading digits don't match then move on to the next phone number format
if (national_number.search(last_leading_digits_pattern) !== 0) {
continue;
}
}
// Check that the national number matches the phone number format regular expression
if (matches_entirely(national_number, new RegExp(get_format_pattern(_format)))) {
return _format;
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
// Removes brackets and replaces dashes with spaces.
//
// E.g. "(999) 111-22-33" -> "999 111 22 33"
//
export function local_to_international_style(local) {
return local
// Remove brackets
.replace(/[\(\)]/g, '')
// Replace dashes with spaces
.replace(/\-/g, ' ').trim();
}
// Sort out arguments
function sort_out_arguments() {
var first_argument = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
var second_argument = arguments[1];
var third_argument = arguments[2];
var fourth_argument = arguments[3];
var input = void 0;
var format_type = void 0;
var metadata = void 0;
// Sort out arguments
if (typeof first_argument === 'string') {
// If country code is supplied
if (typeof third_argument === 'string') {
// Will be `parse()`d later in code
input = {
phone: first_argument,
country: second_argument
};
format_type = third_argument;
metadata = fourth_argument;
}
// Just an international phone number is supplied
else {
// Will be `parse()`d later in code
input = {
phone: first_argument
};
if (typeof second_argument !== 'string') {
throw new Error('Format type argument not passed for `format()`');
}
format_type = second_argument;
metadata = third_argument;
}
} else {
input = first_argument;
format_type = second_argument;
metadata = third_argument;
}
// Sanity check
if (!metadata) {
throw new Error('Metadata not passed');
}
switch (format_type) {
case 'International':
case 'International_plaintext':
case 'National':
break;
default:
throw new Error('Unknown format type argument passed to "format()": "' + format_type + '"');
}
return { input: input, format_type: format_type, metadata: metadata };
}
//# sourceMappingURL=format.js.map