1 |
|
2 |
|
3 |
|
4 |
|
5 | import { VALID_DIGITS, PLUS_CHARS, MIN_LENGTH_FOR_NSN, MAX_LENGTH_FOR_NSN } from './constants';
|
6 | import ParseError from './ParseError';
|
7 | import Metadata from './metadata';
|
8 | import isViablePhoneNumber from './helpers/isViablePhoneNumber';
|
9 | import extractExtension from './helpers/extension/extractExtension';
|
10 | import parseIncompletePhoneNumber from './parseIncompletePhoneNumber';
|
11 | import getCountryCallingCode from './getCountryCallingCode';
|
12 | import { isPossibleNumber } from './isPossibleNumber_';
|
13 | import { parseRFC3966 } from './helpers/RFC3966';
|
14 | import PhoneNumber from './PhoneNumber';
|
15 | import matchesEntirely from './helpers/matchesEntirely';
|
16 | import extractCountryCallingCode from './helpers/extractCountryCallingCode';
|
17 | import extractCountryCallingCodeFromInternationalNumberWithoutPlusSign from './helpers/extractCountryCallingCodeFromInternationalNumberWithoutPlusSign';
|
18 | import extractNationalNumber from './helpers/extractNationalNumber';
|
19 | import stripIddPrefix from './helpers/stripIddPrefix';
|
20 | import getCountryByCallingCode from './helpers/getCountryByCallingCode';
|
21 |
|
22 |
|
23 | var MAX_INPUT_STRING_LENGTH = 250;
|
24 |
|
25 | var PHONE_NUMBER_START_PATTERN = new RegExp('[' + PLUS_CHARS + VALID_DIGITS + ']');
|
26 |
|
27 |
|
28 |
|
29 | var AFTER_PHONE_NUMBER_END_PATTERN = new RegExp('[^' + VALID_DIGITS + '#' + ']+$');
|
30 | var USE_NON_GEOGRAPHIC_COUNTRY_CODE = false;
|
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 | export default function parse(text, options, metadata) {
|
58 |
|
59 |
|
60 | options = options || {};
|
61 | metadata = new Metadata(metadata);
|
62 |
|
63 | if (options.defaultCountry && !metadata.hasCountry(options.defaultCountry)) {
|
64 | if (options.v2) {
|
65 | throw new ParseError('INVALID_COUNTRY');
|
66 | }
|
67 |
|
68 | throw new Error("Unknown country: ".concat(options.defaultCountry));
|
69 | }
|
70 |
|
71 |
|
72 | var _parseInput = parseInput(text, options.v2),
|
73 | formattedPhoneNumber = _parseInput.number,
|
74 | ext = _parseInput.ext;
|
75 |
|
76 |
|
77 | if (!formattedPhoneNumber) {
|
78 | if (options.v2) {
|
79 | throw new ParseError('NOT_A_NUMBER');
|
80 | }
|
81 |
|
82 | return {};
|
83 | }
|
84 |
|
85 | var _parsePhoneNumber = parsePhoneNumber(formattedPhoneNumber, options.defaultCountry, options.defaultCallingCode, metadata),
|
86 | country = _parsePhoneNumber.country,
|
87 | nationalNumber = _parsePhoneNumber.nationalNumber,
|
88 | countryCallingCode = _parsePhoneNumber.countryCallingCode,
|
89 | carrierCode = _parsePhoneNumber.carrierCode;
|
90 |
|
91 | if (!metadata.hasSelectedNumberingPlan()) {
|
92 | if (options.v2) {
|
93 | throw new ParseError('INVALID_COUNTRY');
|
94 | }
|
95 |
|
96 | return {};
|
97 | }
|
98 |
|
99 |
|
100 | if (!nationalNumber || nationalNumber.length < MIN_LENGTH_FOR_NSN) {
|
101 |
|
102 |
|
103 |
|
104 | if (options.v2) {
|
105 | throw new ParseError('TOO_SHORT');
|
106 | }
|
107 |
|
108 |
|
109 | return {};
|
110 | }
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 | if (nationalNumber.length > MAX_LENGTH_FOR_NSN) {
|
122 | if (options.v2) {
|
123 | throw new ParseError('TOO_LONG');
|
124 | }
|
125 |
|
126 |
|
127 | return {};
|
128 | }
|
129 |
|
130 | if (options.v2) {
|
131 | var phoneNumber = new PhoneNumber(countryCallingCode, nationalNumber, metadata.metadata);
|
132 |
|
133 | if (country) {
|
134 | phoneNumber.country = country;
|
135 | }
|
136 |
|
137 | if (carrierCode) {
|
138 | phoneNumber.carrierCode = carrierCode;
|
139 | }
|
140 |
|
141 | if (ext) {
|
142 | phoneNumber.ext = ext;
|
143 | }
|
144 |
|
145 | return phoneNumber;
|
146 | }
|
147 |
|
148 |
|
149 |
|
150 |
|
151 | var valid = (options.extended ? metadata.hasSelectedNumberingPlan() : country) ? matchesEntirely(nationalNumber, metadata.nationalNumberPattern()) : false;
|
152 |
|
153 | if (!options.extended) {
|
154 | return valid ? result(country, nationalNumber, ext) : {};
|
155 | }
|
156 |
|
157 |
|
158 | return {
|
159 | country: country,
|
160 | countryCallingCode: countryCallingCode,
|
161 | carrierCode: carrierCode,
|
162 | valid: valid,
|
163 | possible: valid ? true : options.extended === true && metadata.possibleLengths() && isPossibleNumber(nationalNumber, metadata) ? true : false,
|
164 | phone: nationalNumber,
|
165 | ext: ext
|
166 | };
|
167 | }
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 | export function extractFormattedPhoneNumber(text, throwOnError) {
|
181 | if (!text) {
|
182 | return;
|
183 | }
|
184 |
|
185 | if (text.length > MAX_INPUT_STRING_LENGTH) {
|
186 | if (throwOnError) {
|
187 | throw new ParseError('TOO_LONG');
|
188 | }
|
189 |
|
190 | return;
|
191 | }
|
192 |
|
193 |
|
194 | var startsAt = text.search(PHONE_NUMBER_START_PATTERN);
|
195 |
|
196 | if (startsAt < 0) {
|
197 | return;
|
198 | }
|
199 |
|
200 | return text
|
201 | .slice(startsAt)
|
202 | .replace(AFTER_PHONE_NUMBER_END_PATTERN, '');
|
203 | }
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 | function parseInput(text, v2) {
|
210 |
|
211 | if (text && text.indexOf('tel:') === 0) {
|
212 | return parseRFC3966(text);
|
213 | }
|
214 |
|
215 | var number = extractFormattedPhoneNumber(text, v2);
|
216 |
|
217 | if (!number || !isViablePhoneNumber(number)) {
|
218 | return {};
|
219 | }
|
220 |
|
221 |
|
222 |
|
223 | var withExtensionStripped = extractExtension(number);
|
224 |
|
225 | if (withExtensionStripped.ext) {
|
226 | return withExtensionStripped;
|
227 | }
|
228 |
|
229 | return {
|
230 | number: number
|
231 | };
|
232 | }
|
233 |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 | function result(country, nationalNumber, ext) {
|
239 | var result = {
|
240 | country: country,
|
241 | phone: nationalNumber
|
242 | };
|
243 |
|
244 | if (ext) {
|
245 | result.ext = ext;
|
246 | }
|
247 |
|
248 | return result;
|
249 | }
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 |
|
260 | function parsePhoneNumber(formattedPhoneNumber, defaultCountry, defaultCallingCode, metadata) {
|
261 |
|
262 | var _extractCountryCallin = extractCountryCallingCode(parseIncompletePhoneNumber(formattedPhoneNumber), defaultCountry, defaultCallingCode, metadata.metadata),
|
263 | countryCallingCode = _extractCountryCallin.countryCallingCode,
|
264 | number = _extractCountryCallin.number;
|
265 |
|
266 |
|
267 | var country;
|
268 |
|
269 | if (countryCallingCode) {
|
270 | metadata.selectNumberingPlan(countryCallingCode);
|
271 | }
|
272 |
|
273 | else if (number && (defaultCountry || defaultCallingCode)) {
|
274 | metadata.selectNumberingPlan(defaultCountry, defaultCallingCode);
|
275 |
|
276 | if (defaultCountry) {
|
277 | country = defaultCountry;
|
278 | } else {
|
279 |
|
280 | if (USE_NON_GEOGRAPHIC_COUNTRY_CODE) {
|
281 | if (metadata.isNonGeographicCallingCode(defaultCallingCode)) {
|
282 | country = '001';
|
283 | }
|
284 | }
|
285 | }
|
286 |
|
287 | countryCallingCode = defaultCallingCode || getCountryCallingCode(defaultCountry, metadata.metadata);
|
288 | } else return {};
|
289 |
|
290 | if (!number) {
|
291 | return {
|
292 | countryCallingCode: countryCallingCode
|
293 | };
|
294 | }
|
295 |
|
296 | var _extractNationalNumbe = extractNationalNumber(parseIncompletePhoneNumber(number), metadata),
|
297 | nationalNumber = _extractNationalNumbe.nationalNumber,
|
298 | carrierCode = _extractNationalNumbe.carrierCode;
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 |
|
308 |
|
309 |
|
310 | var exactCountry = getCountryByCallingCode(countryCallingCode, nationalNumber, metadata);
|
311 |
|
312 | if (exactCountry) {
|
313 | country = exactCountry;
|
314 |
|
315 |
|
316 | if (exactCountry === '001') {
|
317 |
|
318 |
|
319 | } else {
|
320 | metadata.country(country);
|
321 | }
|
322 | }
|
323 |
|
324 | return {
|
325 | country: country,
|
326 | countryCallingCode: countryCallingCode,
|
327 | nationalNumber: nationalNumber,
|
328 | carrierCode: carrierCode
|
329 | };
|
330 | }
|
331 |
|
\ | No newline at end of file |