1 | ;
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | Object.defineProperty(exports, "DIGIT_PLACEHOLDER", {
|
7 | enumerable: true,
|
8 | get: function get() {
|
9 | return _AsYouTypeFormatter.DIGIT_PLACEHOLDER;
|
10 | }
|
11 | });
|
12 | exports["default"] = void 0;
|
13 |
|
14 | var _AsYouTypeFormatter = require("./AsYouTypeFormatter.util");
|
15 |
|
16 | var _AsYouTypeFormatter2 = _interopRequireWildcard(require("./AsYouTypeFormatter.complete"));
|
17 |
|
18 | var _parseDigits = _interopRequireDefault(require("./helpers/parseDigits"));
|
19 |
|
20 | var _formatNationalNumberUsingFormat = require("./helpers/formatNationalNumberUsingFormat");
|
21 |
|
22 | var _constants = require("./constants");
|
23 |
|
24 | var _applyInternationalSeparatorStyle = _interopRequireDefault(require("./helpers/applyInternationalSeparatorStyle"));
|
25 |
|
26 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
27 |
|
28 | function _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 |
|
30 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
31 |
|
32 | function _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 |
|
34 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
35 |
|
36 | function _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.
|
40 | var DUMMY_DIGIT = '9'; // I don't know why is it exactly `15`
|
41 |
|
42 | var 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 |
|
45 | var 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 |
|
48 | var 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 |
|
55 | var 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 |
|
58 | var 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 |
|
67 | var 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 |
|
105 | var 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 |
|
109 | var MIN_LEADING_DIGITS_LENGTH = 3;
|
110 |
|
111 | var AsYouTypeFormatter =
|
112 | /*#__PURE__*/
|
113 | function () {
|
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 |
|
725 | exports["default"] = AsYouTypeFormatter;
|
726 | //# sourceMappingURL=AsYouTypeFormatter.js.map |
\ | No newline at end of file |