-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
123 lines (100 loc) · 4.1 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
'use strict';
const countrydata = require( 'countrydata' );
const extend = require( 'extend' );
const ALLOW_LEADING_ZEROES = [
'GAB',
'CIV',
'COG'
];
const phoneparser = module.exports = {
strip: ( input ) => {
const trimmed = input.trim();
const non_numbers_removed = trimmed.replace( /\D/g, '' );
return non_numbers_removed;
},
format: ( input, formatting ) => {
const formatted = formatting.split( '' );
let inputIndex = 0;
for ( let index = 0, length = formatting.length; index < length; ++index ) {
if ( formatting[ index ] === 'N' ) {
formatted[ index ] = input[ inputIndex++ ];
}
}
return formatted.join( '' );
},
parse: ( input, country_code ) => {
const stripped = phoneparser.strip( input );
const possible_countries = countrydata.all().filter( ( country ) => {
const phone_info = country.phone;
if ( stripped.indexOf( phone_info.code ) === 0 ) {
const valid_lengths = phone_info.lengths.map( ( length ) => ( length + phone_info.code.length ) );
const is_valid_length = valid_lengths.indexOf( stripped.length ) !== -1;
const has_valid_prefix = Object.keys( phone_info.prefixes ).reduce( ( _has_valid_prefix, prefix ) => ( _has_valid_prefix || stripped.indexOf( phone_info.code + prefix ) === 0 ), false );
if ( is_valid_length && has_valid_prefix ) {
return true;
}
}
const is_valid_length_forcountry = phone_info.lengths.some( ( length ) => ( length === stripped.length ) );
if ( !is_valid_length_forcountry ) {
return false;
}
const valid_prefix = Object.keys( phone_info.prefixes ).some( ( prefix ) => ( stripped.indexOf( prefix ) === 0 ) );
return valid_prefix;
} );
// try to sort possible matching countries by:
// 1) if a longer valid prefix is matched, sort earlier
// 2) if a country has fewer possible phone number lengths, and this one matches, sort that country earlier
const sorted_possible_countries = possible_countries.sort( ( lhs, rhs ) => {
const lhs_matched_prefix = Object.keys( lhs.phone.prefixes ).find( ( prefix ) => ( stripped.indexOf( prefix === 0 ) ) );
const rhs_matched_prefix = Object.keys( rhs.phone.prefixes ).find( ( prefix ) => ( stripped.indexOf( prefix === 0 ) ) );
if ( lhs_matched_prefix && rhs_matched_prefix ) {
return lhs_matched_prefix.length > rhs_matched_prefix.length ? -1 : lhs_matched_prefix.length < rhs_matched_prefix.length ? 1 : 0;
}
return lhs.phone.lengths.length < rhs.phone.lengths.length ? -1 : lhs.phone.lengths.length > rhs.phone.lengths.length ? 1 : 0;
} );
const country = sorted_possible_countries.find( ( country ) => ( country && country.iso3166 && country.iso3166.alpha3 === country_code ) ) || sorted_possible_countries[ 0 ] || null;
let normalized = stripped;
if ( ALLOW_LEADING_ZEROES.indexOf( country_code ) === -1 ) {
normalized = normalized.replace( /^0+/, '' );
}
// if input 89234567890, RUS, remove the 8
if ( country_code === 'RUS' && normalized.length === 11 && normalized.indexOf( '89' ) === 0 ) {
normalized = normalized.slice( 1 );
}
// if the phone number is the length of an in-country number for the selected country (ie:
// it's missing the country code), add the country code on the front.
if ( country && country.phone.lengths.indexOf( normalized.length ) !== -1 ) {
normalized = country.phone.code + normalized;
}
let valid = !!country;
let info = null;
let localized = null;
if ( country ) {
localized = normalized.slice( country.phone.code.length );
if ( country.phone.lengths.indexOf( localized.length ) === -1 ) {
valid = false;
}
Object.keys( country.phone.prefixes ).some( ( prefix ) => {
if ( localized.indexOf( prefix ) === 0 ) {
info = extend( true, {
prefix: prefix
}, country.phone.prefixes[ prefix ] );
return true;
}
return false;
} );
}
return {
valid: valid,
normalized: valid ? `+${ normalized }` : normalized,
stripped: stripped,
format: phoneparser.format.bind( null, stripped ),
localized: {
stripped: localized,
format: phoneparser.format.bind( null, localized )
},
info: info,
country: country
};
}
};