UNPKG

33.3 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6Object.defineProperty(exports, "DIGIT_PLACEHOLDER", {
7 enumerable: true,
8 get: function get() {
9 return _AsYouTypeFormatter.DIGIT_PLACEHOLDER;
10 }
11});
12exports["default"] = void 0;
13
14var _AsYouTypeFormatter = require("./AsYouTypeFormatter.util");
15
16var _AsYouTypeFormatter2 = _interopRequireWildcard(require("./AsYouTypeFormatter.complete"));
17
18var _parseDigits = _interopRequireDefault(require("./helpers/parseDigits"));
19
20var _formatNationalNumberUsingFormat = require("./helpers/formatNationalNumberUsingFormat");
21
22var _constants = require("./constants");
23
24var _applyInternationalSeparatorStyle = _interopRequireDefault(require("./helpers/applyInternationalSeparatorStyle"));
25
26function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
27
28function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj["default"] = obj; return newObj; } }
29
30function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
31
32function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
33
34function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
35
36function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
37
38// Used in phone number format template creation.
39// Could be any digit, I guess.
40var DUMMY_DIGIT = '9'; // I don't know why is it exactly `15`
41
42var LONGEST_NATIONAL_PHONE_NUMBER_LENGTH = 15; // Create a phone number consisting only of the digit 9 that matches the
43// `number_pattern` by applying the pattern to the "longest phone number" string.
44
45var LONGEST_DUMMY_PHONE_NUMBER = (0, _AsYouTypeFormatter.repeat)(DUMMY_DIGIT, LONGEST_NATIONAL_PHONE_NUMBER_LENGTH); // A set of characters that, if found in a national prefix formatting rules, are an indicator to
46// us that we should separate the national prefix from the number when formatting.
47
48var NATIONAL_PREFIX_SEPARATORS_PATTERN = /[- ]/; // Deprecated: Google has removed some formatting pattern related code from their repo.
49// https://github.com/googlei18n/libphonenumber/commit/a395b4fef3caf57c4bc5f082e1152a4d2bd0ba4c
50// "We no longer have numbers in formatting matching patterns, only \d."
51// Because this library supports generating custom metadata
52// some users may still be using old metadata so the relevant
53// code seems to stay until some next major version update.
54
55var SUPPORT_LEGACY_FORMATTING_PATTERNS = true; // A pattern that is used to match character classes in regular expressions.
56// An example of a character class is "[1-4]".
57
58var CREATE_CHARACTER_CLASS_PATTERN = SUPPORT_LEGACY_FORMATTING_PATTERNS && function () {
59 return /\[([^\[\]])*\]/g;
60}; // Any digit in a regular expression that actually denotes a digit. For
61// example, in the regular expression "80[0-2]\d{6,10}", the first 2 digits
62// (8 and 0) are standalone digits, but the rest are not.
63// Two look-aheads are needed because the number following \\d could be a
64// two-digit number, since the phone number can be as long as 15 digits.
65
66
67var CREATE_STANDALONE_DIGIT_PATTERN = SUPPORT_LEGACY_FORMATTING_PATTERNS && function () {
68 return /\d(?=[^,}][^,}])/g;
69}; // A regular expression that is used to determine if a `format` is
70// suitable to be used in the "as you type formatter".
71// A `format` is suitable when the resulting formatted number has
72// the same digits as the user has entered.
73//
74// In the simplest case, that would mean that the format
75// doesn't add any additional digits when formatting a number.
76// Google says that it also shouldn't add "star" (`*`) characters,
77// like it does in some Israeli formats.
78// Such basic format would only contain "valid punctuation"
79// and "captured group" identifiers ($1, $2, etc).
80//
81// An example of a format that adds additional digits:
82//
83// Country: `AR` (Argentina).
84// Format:
85// {
86// "pattern": "(\\d)(\\d{2})(\\d{4})(\\d{4})",
87// "leading_digits_patterns": ["91"],
88// "national_prefix_formatting_rule": "0$1",
89// "format": "$2 15-$3-$4",
90// "international_format": "$1 $2 $3-$4"
91// }
92//
93// In the format above, the `format` adds `15` to the digits when formatting a number.
94// A sidenote: this format actually is suitable because `national_prefix_for_parsing`
95// has previously removed `15` from a national number, so re-adding `15` in `format`
96// doesn't actually result in any extra digits added to user's input.
97// But verifying that would be a complex procedure, so the code chooses a simpler path:
98// it simply filters out all `format`s that contain anything but "captured group" ids.
99//
100// This regular expression is called `ELIGIBLE_FORMAT_PATTERN` in Google's
101// `libphonenumber` code.
102//
103
104
105var NON_ALTERING_FORMAT_REG_EXP = new RegExp('^' + '[' + _constants.VALID_PUNCTUATION + ']*' + '(\\$\\d[' + _constants.VALID_PUNCTUATION + ']*)+' + '$'); // This is the minimum length of the leading digits of a phone number
106// to guarantee the first "leading digits pattern" for a phone number format
107// to be preemptive.
108
109var MIN_LEADING_DIGITS_LENGTH = 3;
110
111var AsYouTypeFormatter =
112/*#__PURE__*/
113function () {
114 function AsYouTypeFormatter(_ref) {
115 var _this = this;
116
117 var state = _ref.state,
118 metadata = _ref.metadata;
119
120 _classCallCheck(this, AsYouTypeFormatter);
121
122 _defineProperty(this, "getSeparatorAfterNationalPrefix", function (format) {
123 // `US` metadata doesn't have a `national_prefix_formatting_rule`,
124 // so the `if` condition below doesn't apply to `US`,
125 // but in reality there shoudl be a separator
126 // between a national prefix and a national (significant) number.
127 // So `US` national prefix separator is a "special" "hardcoded" case.
128 if (_this.isNANP) {
129 return ' ';
130 } // If a `format` has a `national_prefix_formatting_rule`
131 // and that rule has a separator after a national prefix,
132 // then it means that there should be a separator
133 // between a national prefix and a national (significant) number.
134
135
136 if (format && format.nationalPrefixFormattingRule() && NATIONAL_PREFIX_SEPARATORS_PATTERN.test(format.nationalPrefixFormattingRule())) {
137 return ' ';
138 } // At this point, there seems to be no clear evidence that
139 // there should be a separator between a national prefix
140 // and a national (significant) number. So don't insert one.
141
142
143 return '';
144 });
145
146 _defineProperty(this, "shouldTryNationalPrefixFormattingRule", function (format, _ref2) {
147 var international = _ref2.international,
148 nationalPrefix = _ref2.nationalPrefix;
149
150 if (format.nationalPrefixFormattingRule()) {
151 // In some countries, `national_prefix_formatting_rule` is `($1)`,
152 // so it applies even if the user hasn't input a national prefix.
153 // `format.usesNationalPrefix()` detects such cases.
154 var usesNationalPrefix = format.usesNationalPrefix();
155
156 if (usesNationalPrefix && nationalPrefix || !usesNationalPrefix && !international) {
157 return true;
158 }
159 }
160 });
161
162 this.metadata = metadata;
163 this.resetFormat();
164 }
165
166 _createClass(AsYouTypeFormatter, [{
167 key: "resetFormat",
168 value: function resetFormat() {
169 this.chosenFormat = undefined;
170 this.template = undefined;
171 this.nationalNumberTemplate = undefined;
172 this.populatedNationalNumberTemplate = undefined;
173 this.populatedNationalNumberTemplatePosition = -1;
174 }
175 }, {
176 key: "reset",
177 value: function reset(numberingPlan, state) {
178 this.resetFormat();
179
180 if (numberingPlan) {
181 this.isNANP = numberingPlan.callingCode() === '1';
182 this.matchingFormats = numberingPlan.formats();
183
184 if (state.nationalSignificantNumber) {
185 this.narrowDownMatchingFormats(state);
186 }
187 } else {
188 this.isNANP = undefined;
189 this.matchingFormats = [];
190 }
191 }
192 }, {
193 key: "format",
194 value: function format(nextDigits, state) {
195 var _this2 = this;
196
197 // See if the phone number digits can be formatted as a complete phone number.
198 // If not, use the results from `formatNationalNumberWithNextDigits()`,
199 // which formats based on the chosen formatting pattern.
200 //
201 // Attempting to format complete phone number first is how it's done
202 // in Google's `libphonenumber`, so this library just follows it.
203 // Google's `libphonenumber` code doesn't explain in detail why does it
204 // attempt to format digits as a complete phone number
205 // instead of just going with a previoulsy (or newly) chosen `format`:
206 //
207 // "Checks to see if there is an exact pattern match for these digits.
208 // If so, we should use this instead of any other formatting template
209 // whose leadingDigitsPattern also matches the input."
210 //
211 if ((0, _AsYouTypeFormatter2.canFormatCompleteNumber)(state.nationalSignificantNumber, this.metadata)) {
212 for (var _iterator = this.matchingFormats, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
213 var _ref3;
214
215 if (_isArray) {
216 if (_i >= _iterator.length) break;
217 _ref3 = _iterator[_i++];
218 } else {
219 _i = _iterator.next();
220 if (_i.done) break;
221 _ref3 = _i.value;
222 }
223
224 var format = _ref3;
225 var formattedCompleteNumber = (0, _AsYouTypeFormatter2["default"])(state, format, {
226 metadata: this.metadata,
227 shouldTryNationalPrefixFormattingRule: function shouldTryNationalPrefixFormattingRule(format) {
228 return _this2.shouldTryNationalPrefixFormattingRule(format, {
229 international: state.international,
230 nationalPrefix: state.nationalPrefix
231 });
232 },
233 getSeparatorAfterNationalPrefix: this.getSeparatorAfterNationalPrefix
234 });
235
236 if (formattedCompleteNumber) {
237 this.resetFormat();
238 this.chosenFormat = format;
239 this.setNationalNumberTemplate(formattedCompleteNumber.replace(/\d/g, _AsYouTypeFormatter.DIGIT_PLACEHOLDER), state);
240 this.populatedNationalNumberTemplate = formattedCompleteNumber; // With a new formatting template, the matched position
241 // using the old template needs to be reset.
242
243 this.populatedNationalNumberTemplatePosition = this.template.lastIndexOf(_AsYouTypeFormatter.DIGIT_PLACEHOLDER);
244 return formattedCompleteNumber;
245 }
246 }
247 } // Format the digits as a partial (incomplete) phone number
248 // using the previously chosen formatting pattern (or a newly chosen one).
249
250
251 return this.formatNationalNumberWithNextDigits(nextDigits, state);
252 } // Formats the next phone number digits.
253
254 }, {
255 key: "formatNationalNumberWithNextDigits",
256 value: function formatNationalNumberWithNextDigits(nextDigits, state) {
257 var previouslyChosenFormat = this.chosenFormat; // Choose a format from the list of matching ones.
258
259 var newlyChosenFormat = this.chooseFormat(state);
260
261 if (newlyChosenFormat) {
262 if (newlyChosenFormat === previouslyChosenFormat) {
263 // If it can format the next (current) digits
264 // using the previously chosen phone number format
265 // then return the updated formatted number.
266 return this.formatNextNationalNumberDigits(nextDigits);
267 } else {
268 // If a more appropriate phone number format
269 // has been chosen for these "leading digits",
270 // then re-format the national phone number part
271 // using the newly selected format.
272 return this.formatNextNationalNumberDigits(state.getNationalDigits());
273 }
274 }
275 }
276 }, {
277 key: "narrowDownMatchingFormats",
278 value: function narrowDownMatchingFormats(_ref4) {
279 var _this3 = this;
280
281 var nationalSignificantNumber = _ref4.nationalSignificantNumber,
282 nationalPrefix = _ref4.nationalPrefix,
283 international = _ref4.international;
284 var leadingDigits = nationalSignificantNumber; // "leading digits" pattern list starts with a
285 // "leading digits" pattern fitting a maximum of 3 leading digits.
286 // So, after a user inputs 3 digits of a national (significant) phone number
287 // this national (significant) number can already be formatted.
288 // The next "leading digits" pattern is for 4 leading digits max,
289 // and the "leading digits" pattern after it is for 5 leading digits max, etc.
290 // This implementation is different from Google's
291 // in that it searches for a fitting format
292 // even if the user has entered less than
293 // `MIN_LEADING_DIGITS_LENGTH` digits of a national number.
294 // Because some leading digit patterns already match for a single first digit.
295
296 var leadingDigitsPatternIndex = leadingDigits.length - MIN_LEADING_DIGITS_LENGTH;
297
298 if (leadingDigitsPatternIndex < 0) {
299 leadingDigitsPatternIndex = 0;
300 }
301
302 this.matchingFormats = this.matchingFormats.filter(function (format) {
303 return _this3.formatSuits(format, international, nationalPrefix) && _this3.formatMatches(format, leadingDigits, leadingDigitsPatternIndex);
304 }); // If there was a phone number format chosen
305 // and it no longer holds given the new leading digits then reset it.
306 // The test for this `if` condition is marked as:
307 // "Reset a chosen format when it no longer holds given the new leading digits".
308 // To construct a valid test case for this one can find a country
309 // in `PhoneNumberMetadata.xml` yielding one format for 3 `<leadingDigits>`
310 // and yielding another format for 4 `<leadingDigits>` (Australia in this case).
311
312 if (this.chosenFormat && this.matchingFormats.indexOf(this.chosenFormat) === -1) {
313 this.resetFormat();
314 }
315 }
316 }, {
317 key: "formatSuits",
318 value: function formatSuits(format, international, nationalPrefix) {
319 // When a prefix before a national (significant) number is
320 // simply a national prefix, then it's parsed as `this.nationalPrefix`.
321 // In more complex cases, a prefix before national (significant) number
322 // could include a national prefix as well as some "capturing groups",
323 // and in that case there's no info whether a national prefix has been parsed.
324 // If national prefix is not used when formatting a phone number
325 // using this format, but a national prefix has been entered by the user,
326 // and was extracted, then discard such phone number format.
327 // In Google's "AsYouType" formatter code, the equivalent would be this part:
328 // https://github.com/google/libphonenumber/blob/0a45cfd96e71cad8edb0e162a70fcc8bd9728933/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java#L175-L184
329 if (nationalPrefix && !format.usesNationalPrefix() && // !format.domesticCarrierCodeFormattingRule() &&
330 !format.nationalPrefixIsOptionalWhenFormattingInNationalFormat()) {
331 return false;
332 } // If national prefix is mandatory for this phone number format
333 // and there're no guarantees that a national prefix is present in user input
334 // then discard this phone number format as not suitable.
335 // In Google's "AsYouType" formatter code, the equivalent would be this part:
336 // https://github.com/google/libphonenumber/blob/0a45cfd96e71cad8edb0e162a70fcc8bd9728933/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java#L185-L193
337
338
339 if (!international && !nationalPrefix && format.nationalPrefixIsMandatoryWhenFormattingInNationalFormat()) {
340 return false;
341 }
342
343 return true;
344 }
345 }, {
346 key: "formatMatches",
347 value: function formatMatches(format, leadingDigits, leadingDigitsPatternIndex) {
348 var leadingDigitsPatternsCount = format.leadingDigitsPatterns().length; // If this format is not restricted to a certain
349 // leading digits pattern then it fits.
350
351 if (leadingDigitsPatternsCount === 0) {
352 return true;
353 } // Start excluding any non-matching formats only when the
354 // national number entered so far is at least 3 digits long,
355 // otherwise format matching would give false negatives.
356 // For example, when the digits entered so far are `2`
357 // and the leading digits pattern is `21` –
358 // it's quite obvious in this case that the format could be the one
359 // but due to the absence of further digits it would give false negative.
360
361
362 if (leadingDigits.length < MIN_LEADING_DIGITS_LENGTH) {
363 return true;
364 } // If at least `MIN_LEADING_DIGITS_LENGTH` digits of a national number are available
365 // then format matching starts narrowing down the list of possible formats
366 // (only previously matched formats are considered for next digits).
367
368
369 leadingDigitsPatternIndex = Math.min(leadingDigitsPatternIndex, leadingDigitsPatternsCount - 1);
370 var leadingDigitsPattern = format.leadingDigitsPatterns()[leadingDigitsPatternIndex]; // Brackets are required for `^` to be applied to
371 // all or-ed (`|`) parts, not just the first one.
372
373 return new RegExp("^(".concat(leadingDigitsPattern, ")")).test(leadingDigits);
374 }
375 }, {
376 key: "getFormatFormat",
377 value: function getFormatFormat(format, international) {
378 return international ? format.internationalFormat() : format.format();
379 }
380 }, {
381 key: "chooseFormat",
382 value: function chooseFormat(state) {
383 var _this4 = this;
384
385 var _loop2 = function _loop2() {
386 if (_isArray2) {
387 if (_i2 >= _iterator2.length) return "break";
388 _ref5 = _iterator2[_i2++];
389 } else {
390 _i2 = _iterator2.next();
391 if (_i2.done) return "break";
392 _ref5 = _i2.value;
393 }
394
395 var format = _ref5;
396
397 // If this format is currently being used
398 // and is still suitable, then stick to it.
399 if (_this4.chosenFormat === format) {
400 return "break";
401 } // Sometimes, a formatting rule inserts additional digits in a phone number,
402 // and "as you type" formatter can't do that: it should only use the digits
403 // that the user has input.
404 //
405 // For example, in Argentina, there's a format for mobile phone numbers:
406 //
407 // {
408 // "pattern": "(\\d)(\\d{2})(\\d{4})(\\d{4})",
409 // "leading_digits_patterns": ["91"],
410 // "national_prefix_formatting_rule": "0$1",
411 // "format": "$2 15-$3-$4",
412 // "international_format": "$1 $2 $3-$4"
413 // }
414 //
415 // In that format, `international_format` is used instead of `format`
416 // because `format` inserts `15` in the formatted number,
417 // and `AsYouType` formatter should only use the digits
418 // the user has actually input, without adding any extra digits.
419 // In this case, it wouldn't make a difference, because the `15`
420 // is first stripped when applying `national_prefix_for_parsing`
421 // and then re-added when using `format`, so in reality it doesn't
422 // add any new digits to the number, but to detect that, the code
423 // would have to be more complex: it would have to try formatting
424 // the digits using the format and then see if any digits have
425 // actually been added or removed, and then, every time a new digit
426 // is input, it should re-check whether the chosen format doesn't
427 // alter the digits.
428 //
429 // Google's code doesn't go that far, and so does this library:
430 // it simply requires that a `format` doesn't add any additonal
431 // digits to user's input.
432 //
433 // Also, people in general should move from inputting phone numbers
434 // in national format (possibly with national prefixes)
435 // and use international phone number format instead:
436 // it's a logical thing in the modern age of mobile phones,
437 // globalization and the internet.
438 //
439
440 /* istanbul ignore if */
441
442
443 if (!NON_ALTERING_FORMAT_REG_EXP.test(_this4.getFormatFormat(format, state.international))) {
444 return "continue";
445 }
446
447 if (!_this4.createTemplateForFormat(format, state)) {
448 // Remove the format if it can't generate a template.
449 _this4.matchingFormats = _this4.matchingFormats.filter(function (_) {
450 return _ !== format;
451 });
452 return "continue";
453 }
454
455 _this4.chosenFormat = format;
456 return "break";
457 };
458
459 // When there are multiple available formats, the formatter uses the first
460 // format where a formatting template could be created.
461 _loop: for (var _iterator2 = this.matchingFormats.slice(), _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
462 var _ref5;
463
464 var _ret = _loop2();
465
466 switch (_ret) {
467 case "break":
468 break _loop;
469
470 case "continue":
471 continue;
472 }
473 }
474
475 if (!this.chosenFormat) {
476 // No format matches the national (significant) phone number.
477 this.resetFormat();
478 }
479
480 return this.chosenFormat;
481 }
482 }, {
483 key: "createTemplateForFormat",
484 value: function createTemplateForFormat(format, state) {
485 // The formatter doesn't format numbers when numberPattern contains '|', e.g.
486 // (20|3)\d{4}. In those cases we quickly return.
487 // (Though there's no such format in current metadata)
488
489 /* istanbul ignore if */
490 if (SUPPORT_LEGACY_FORMATTING_PATTERNS && format.pattern().indexOf('|') >= 0) {
491 return;
492 } // Get formatting template for this phone number format
493
494
495 var template = this.getTemplateForFormat(format, state); // If the national number entered is too long
496 // for any phone number format, then abort.
497
498 if (template) {
499 this.setNationalNumberTemplate(template, state);
500 return true;
501 }
502 }
503 }, {
504 key: "getInternationalPrefixBeforeCountryCallingCode",
505 value: function getInternationalPrefixBeforeCountryCallingCode(_ref6, options) {
506 var IDDPrefix = _ref6.IDDPrefix,
507 missingPlus = _ref6.missingPlus;
508
509 if (IDDPrefix) {
510 return options && options.spacing === false ? IDDPrefix : IDDPrefix + ' ';
511 }
512
513 if (missingPlus) {
514 return '';
515 }
516
517 return '+';
518 }
519 }, {
520 key: "getTemplate",
521 value: function getTemplate(state) {
522 if (!this.template) {
523 return;
524 } // `this.template` holds the template for a "complete" phone number.
525 // The currently entered phone number is most likely not "complete",
526 // so trim all non-populated digits.
527
528
529 var index = -1;
530 var i = 0;
531 var internationalPrefix = state.international ? this.getInternationalPrefixBeforeCountryCallingCode(state, {
532 spacing: false
533 }) : '';
534
535 while (i < internationalPrefix.length + state.getDigitsWithoutInternationalPrefix().length) {
536 index = this.template.indexOf(_AsYouTypeFormatter.DIGIT_PLACEHOLDER, index + 1);
537 i++;
538 }
539
540 return (0, _AsYouTypeFormatter.cutAndStripNonPairedParens)(this.template, index + 1);
541 }
542 }, {
543 key: "setNationalNumberTemplate",
544 value: function setNationalNumberTemplate(template, state) {
545 this.nationalNumberTemplate = template;
546 this.populatedNationalNumberTemplate = template; // With a new formatting template, the matched position
547 // using the old template needs to be reset.
548
549 this.populatedNationalNumberTemplatePosition = -1; // For convenience, the public `.template` property
550 // contains the whole international number
551 // if the phone number being input is international:
552 // 'x' for the '+' sign, 'x'es for the country phone code,
553 // a spacebar and then the template for the formatted national number.
554
555 if (state.international) {
556 this.template = this.getInternationalPrefixBeforeCountryCallingCode(state).replace(/[\d\+]/g, _AsYouTypeFormatter.DIGIT_PLACEHOLDER) + (0, _AsYouTypeFormatter.repeat)(_AsYouTypeFormatter.DIGIT_PLACEHOLDER, state.callingCode.length) + ' ' + template;
557 } else {
558 this.template = template;
559 }
560 }
561 /**
562 * Generates formatting template for a national phone number,
563 * optionally containing a national prefix, for a format.
564 * @param {Format} format
565 * @param {string} nationalPrefix
566 * @return {string}
567 */
568
569 }, {
570 key: "getTemplateForFormat",
571 value: function getTemplateForFormat(format, _ref7) {
572 var nationalSignificantNumber = _ref7.nationalSignificantNumber,
573 international = _ref7.international,
574 nationalPrefix = _ref7.nationalPrefix,
575 complexPrefixBeforeNationalSignificantNumber = _ref7.complexPrefixBeforeNationalSignificantNumber;
576 var pattern = format.pattern();
577 /* istanbul ignore else */
578
579 if (SUPPORT_LEGACY_FORMATTING_PATTERNS) {
580 pattern = pattern // Replace anything in the form of [..] with \d
581 .replace(CREATE_CHARACTER_CLASS_PATTERN(), '\\d') // Replace any standalone digit (not the one in `{}`) with \d
582 .replace(CREATE_STANDALONE_DIGIT_PATTERN(), '\\d');
583 } // Generate a dummy national number (consisting of `9`s)
584 // that fits this format's `pattern`.
585 //
586 // This match will always succeed,
587 // because the "longest dummy phone number"
588 // has enough length to accomodate any possible
589 // national phone number format pattern.
590 //
591
592
593 var digits = LONGEST_DUMMY_PHONE_NUMBER.match(pattern)[0]; // If the national number entered is too long
594 // for any phone number format, then abort.
595
596 if (nationalSignificantNumber.length > digits.length) {
597 return;
598 } // Get a formatting template which can be used to efficiently format
599 // a partial number where digits are added one by one.
600 // Below `strictPattern` is used for the
601 // regular expression (with `^` and `$`).
602 // This wasn't originally in Google's `libphonenumber`
603 // and I guess they don't really need it
604 // because they're not using "templates" to format phone numbers
605 // but I added `strictPattern` after encountering
606 // South Korean phone number formatting bug.
607 //
608 // Non-strict regular expression bug demonstration:
609 //
610 // this.nationalSignificantNumber : `111111111` (9 digits)
611 //
612 // pattern : (\d{2})(\d{3,4})(\d{4})
613 // format : `$1 $2 $3`
614 // digits : `9999999999` (10 digits)
615 //
616 // '9999999999'.replace(new RegExp(/(\d{2})(\d{3,4})(\d{4})/g), '$1 $2 $3') = "99 9999 9999"
617 //
618 // template : xx xxxx xxxx
619 //
620 // But the correct template in this case is `xx xxx xxxx`.
621 // The template was generated incorrectly because of the
622 // `{3,4}` variability in the `pattern`.
623 //
624 // The fix is, if `this.nationalSignificantNumber` has already sufficient length
625 // to satisfy the `pattern` completely then `this.nationalSignificantNumber`
626 // is used instead of `digits`.
627
628
629 var strictPattern = new RegExp('^' + pattern + '$');
630 var nationalNumberDummyDigits = nationalSignificantNumber.replace(/\d/g, DUMMY_DIGIT); // If `this.nationalSignificantNumber` has already sufficient length
631 // to satisfy the `pattern` completely then use it
632 // instead of `digits`.
633
634 if (strictPattern.test(nationalNumberDummyDigits)) {
635 digits = nationalNumberDummyDigits;
636 }
637
638 var numberFormat = this.getFormatFormat(format, international);
639 var nationalPrefixIncludedInTemplate; // If a user did input a national prefix (and that's guaranteed),
640 // and if a `format` does have a national prefix formatting rule,
641 // then see if that national prefix formatting rule
642 // prepends exactly the same national prefix the user has input.
643 // If that's the case, then use the `format` with the national prefix formatting rule.
644 // Otherwise, use the `format` without the national prefix formatting rule,
645 // and prepend a national prefix manually to it.
646
647 if (this.shouldTryNationalPrefixFormattingRule(format, {
648 international: international,
649 nationalPrefix: nationalPrefix
650 })) {
651 var numberFormatWithNationalPrefix = numberFormat.replace(_formatNationalNumberUsingFormat.FIRST_GROUP_PATTERN, format.nationalPrefixFormattingRule()); // If `national_prefix_formatting_rule` of a `format` simply prepends
652 // national prefix at the start of a national (significant) number,
653 // then such formatting can be used with `AsYouType` formatter.
654 // There seems to be no `else` case: everywhere in metadata,
655 // national prefix formatting rule is national prefix + $1,
656 // or `($1)`, in which case such format isn't even considered
657 // when the user has input a national prefix.
658
659 /* istanbul ignore else */
660
661 if ((0, _parseDigits["default"])(format.nationalPrefixFormattingRule()) === (nationalPrefix || '') + (0, _parseDigits["default"])('$1')) {
662 numberFormat = numberFormatWithNationalPrefix;
663 nationalPrefixIncludedInTemplate = true; // Replace all digits of the national prefix in the formatting template
664 // with `DIGIT_PLACEHOLDER`s.
665
666 if (nationalPrefix) {
667 var i = nationalPrefix.length;
668
669 while (i > 0) {
670 numberFormat = numberFormat.replace(/\d/, _AsYouTypeFormatter.DIGIT_PLACEHOLDER);
671 i--;
672 }
673 }
674 }
675 } // Generate formatting template for this phone number format.
676
677
678 var template = digits // Format the dummy phone number according to the format.
679 .replace(new RegExp(pattern), numberFormat) // Replace each dummy digit with a DIGIT_PLACEHOLDER.
680 .replace(new RegExp(DUMMY_DIGIT, 'g'), _AsYouTypeFormatter.DIGIT_PLACEHOLDER); // If a prefix of a national (significant) number is not as simple
681 // as just a basic national prefix, then just prepend such prefix
682 // before the national (significant) number, optionally spacing
683 // the two with a whitespace.
684
685 if (!nationalPrefixIncludedInTemplate) {
686 if (complexPrefixBeforeNationalSignificantNumber) {
687 // Prepend the prefix to the template manually.
688 template = (0, _AsYouTypeFormatter.repeat)(_AsYouTypeFormatter.DIGIT_PLACEHOLDER, complexPrefixBeforeNationalSignificantNumber.length) + ' ' + template;
689 } else if (nationalPrefix) {
690 // Prepend national prefix to the template manually.
691 template = (0, _AsYouTypeFormatter.repeat)(_AsYouTypeFormatter.DIGIT_PLACEHOLDER, nationalPrefix.length) + this.getSeparatorAfterNationalPrefix(format) + template;
692 }
693 }
694
695 if (international) {
696 template = (0, _applyInternationalSeparatorStyle["default"])(template);
697 }
698
699 return template;
700 }
701 }, {
702 key: "formatNextNationalNumberDigits",
703 value: function formatNextNationalNumberDigits(digits) {
704 var result = (0, _AsYouTypeFormatter.populateTemplateWithDigits)(this.populatedNationalNumberTemplate, this.populatedNationalNumberTemplatePosition, digits);
705
706 if (!result) {
707 // Reset the format.
708 this.resetFormat();
709 return;
710 }
711
712 this.populatedNationalNumberTemplate = result[0];
713 this.populatedNationalNumberTemplatePosition = result[1]; // Return the formatted phone number so far.
714
715 return (0, _AsYouTypeFormatter.cutAndStripNonPairedParens)(this.populatedNationalNumberTemplate, this.populatedNationalNumberTemplatePosition + 1); // The old way which was good for `input-format` but is not so good
716 // for `react-phone-number-input`'s default input (`InputBasic`).
717 // return closeNonPairedParens(this.populatedNationalNumberTemplate, this.populatedNationalNumberTemplatePosition + 1)
718 // .replace(new RegExp(DIGIT_PLACEHOLDER, 'g'), ' ')
719 }
720 }]);
721
722 return AsYouTypeFormatter;
723}();
724
725exports["default"] = AsYouTypeFormatter;
726//# sourceMappingURL=AsYouTypeFormatter.js.map
\No newline at end of file