libphonenumber-js
Version:
A simpler (and smaller) rewrite of Google Android's popular libphonenumber library
287 lines (234 loc) • 9.43 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FIRST_GROUP_PATTERN = undefined;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; // 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
exports.default = format;
exports.format_national_number_using_format = format_national_number_using_format;
exports.choose_format_for_number = choose_format_for_number;
exports.local_to_international_style = local_to_international_style;
var _common = require('./common');
var _metadata = require('./metadata');
var _metadata2 = _interopRequireDefault(_metadata);
var _RFC = require('./RFC3966');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var default_options = {
formatExtension: function formatExtension(number, extension) {
return number + ' ext. ' + extension;
}
// 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)
// ```
//
};function format(arg_1, arg_2, arg_3, arg_4, arg_5) {
var _sort_out_arguments = sort_out_arguments(arg_1, arg_2, arg_3, arg_4, arg_5),
input = _sort_out_arguments.input,
format_type = _sort_out_arguments.format_type,
options = _sort_out_arguments.options,
metadata = _sort_out_arguments.metadata;
if (input.country && metadata.hasCountry(input.country)) {
metadata.country(input.country);
}
var _parse_national_numbe = (0, _common.parse_national_number_and_country_calling_code)(input.phone, metadata),
countryCallingCode = _parse_national_numbe.countryCallingCode,
number = _parse_national_numbe.number;
countryCallingCode = countryCallingCode || input.countryCallingCode;
if (countryCallingCode) {
// Check country restriction
if (input.country && metadata.selectedCountry() && countryCallingCode !== metadata.countryCallingCode()) {
return input.phone;
}
metadata.chooseCountryByCountryCallingCode(countryCallingCode);
}
if (!metadata.selectedCountry()) {
return input.phone;
}
switch (format_type) {
case 'International':
if (!number) {
return '+' + metadata.countryCallingCode();
}
number = format_national_number(number, 'International', false, metadata);
number = '+' + metadata.countryCallingCode() + ' ' + number;
return add_extension(number, input.ext, options.formatExtension);
case 'E.164':
// `E.164` doesn't define "phone number extensions".
return '+' + metadata.countryCallingCode() + input.phone;
case 'RFC3966':
return (0, _RFC.formatRFC3966)({
number: '+' + metadata.countryCallingCode() + input.phone,
ext: input.ext
});
case 'National':
if (!number) {
return '';
}
number = format_national_number(number, 'National', false, metadata);
return add_extension(number, input.ext, options.formatExtension);
}
}
// 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.
var FIRST_GROUP_PATTERN = exports.FIRST_GROUP_PATTERN = /(\$\d)/;
function format_national_number_using_format(number, format, international, enforce_national_prefix, metadata) {
var format_pattern_matcher = new RegExp(format.pattern());
// 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 = !format.nationalPrefixFormattingRule() || format.nationalPrefixFormattingRule() && format.nationalPrefixIsOptionalWhenFormatting() && !enforce_national_prefix;
if (!international && !national_prefix_may_be_omitted) {
return number.replace(format_pattern_matcher, format.format().replace(FIRST_GROUP_PATTERN, format.nationalPrefixFormattingRule()));
}
var formatted_number = number.replace(format_pattern_matcher, international ? format.internationalFormat() : format.format());
if (international) {
return local_to_international_style(formatted_number);
}
return formatted_number;
}
function format_national_number(number, format_as, enforce_national_prefix, metadata) {
var format = choose_format_for_number(metadata.formats(), number);
if (!format) {
return number;
}
return format_national_number_using_format(number, format, format_as === 'International', enforce_national_prefix, metadata);
}
function choose_format_for_number(available_formats, national_number) {
for (var _iterator = available_formats, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var _format = _ref;
// Validate leading digits
if (_format.leadingDigitsPatterns().length > 0) {
// The last leading_digits_pattern is used here, as it is the most detailed
var last_leading_digits_pattern = _format.leadingDigitsPatterns()[_format.leadingDigitsPatterns().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 ((0, _common.matches_entirely)(national_number, new RegExp(_format.pattern()))) {
return _format;
}
}
}
// Removes brackets and replaces dashes with spaces.
//
// E.g. "(999) 111-22-33" -> "999 111 22 33"
//
function local_to_international_style(local) {
return local.replace(new RegExp('[' + _common.VALID_PUNCTUATION + ']+', 'g'), ' ').trim();
}
// Sort out arguments
function sort_out_arguments(arg_1, arg_2, arg_3, arg_4, arg_5) {
var input = void 0;
var format_type = void 0;
var options = void 0;
var metadata = void 0;
// Sort out arguments.
// If the phone number is passed as a string.
// `format('8005553535', ...)`.
if (typeof arg_1 === 'string') {
// If country code is supplied.
// `format('8005553535', 'RU', 'National', [options], metadata)`.
if (typeof arg_3 === 'string') {
// Will be `parse()`d later in code
input = {
phone: arg_1,
country: arg_2
};
format_type = arg_3;
if (arg_5) {
options = arg_4;
metadata = arg_5;
} else {
metadata = arg_4;
}
}
// Just an international phone number is supplied
// `format('+78005553535', 'National', [options], metadata)`.
else {
// Will be `parse()`d later in code
input = {
phone: arg_1
};
if (typeof arg_2 !== 'string') {
throw new Error('Format type argument not passed for `format()`');
}
format_type = arg_2;
if (arg_4) {
options = arg_3;
metadata = arg_4;
} else {
metadata = arg_3;
}
}
}
// If the phone number is passed as a parsed number object.
// `format({ phone: '8005553535', country: 'RU' }, 'National', [options], metadata)`.
else if (is_object(arg_1) && typeof arg_1.phone === 'string') {
input = arg_1;
format_type = arg_2;
if (arg_4) {
options = arg_3;
metadata = arg_4;
} else {
metadata = arg_3;
}
} else throw new TypeError('A phone number must either be a string or an object of shape { phone, [country] }.');
// Metadata is required.
if (!metadata) {
throw new Error('Metadata is required');
}
// Validate `format_type`.
switch (format_type) {
case 'International':
case 'E.164':
case 'National':
case 'RFC3966':
break;
default:
throw new Error('Unknown format type argument passed to "format()": "' + format_type + '"');
}
// Apply default options.
if (options) {
options = _extends({}, default_options, options);
} else {
options = default_options;
}
return { input: input, format_type: format_type, options: options, metadata: new _metadata2.default(metadata) };
}
// Babel transforms `typeof` into some "branches"
// so istanbul will show this as "branch not covered".
/* istanbul ignore next */
var is_object = function is_object(_) {
return (typeof _ === 'undefined' ? 'undefined' : _typeof(_)) === 'object';
};
function add_extension(number, ext, formatExtension) {
return ext ? formatExtension(number, ext) : number;
}
//# sourceMappingURL=format.js.map