UNPKG

8.2 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports["default"] = findPhoneNumbers;
7exports.searchPhoneNumbers = searchPhoneNumbers;
8exports.PhoneNumberSearch = exports.EXTN_PATTERNS_FOR_PARSING = void 0;
9
10var _constants = require("./constants");
11
12var _parse_ = _interopRequireDefault(require("./parse_"));
13
14var _isViablePhoneNumber = require("./helpers/isViablePhoneNumber");
15
16var _createExtensionPattern = _interopRequireDefault(require("./helpers/extension/createExtensionPattern"));
17
18var _parsePreCandidate = _interopRequireDefault(require("./findNumbers/parsePreCandidate"));
19
20var _isValidPreCandidate = _interopRequireDefault(require("./findNumbers/isValidPreCandidate"));
21
22var _isValidCandidate = _interopRequireDefault(require("./findNumbers/isValidCandidate"));
23
24function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
25
26function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
27
28function _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); } }
29
30function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
31
32function _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; }
33
34/**
35 * Regexp of all possible ways to write extensions, for use when parsing. This
36 * will be run as a case-insensitive regexp match. Wide character versions are
37 * also provided after each ASCII version. There are three regular expressions
38 * here. The first covers RFC 3966 format, where the extension is added using
39 * ';ext='. The second more generic one starts with optional white space and
40 * ends with an optional full stop (.), followed by zero or more spaces/tabs
41 * /commas and then the numbers themselves. The other one covers the special
42 * case of American numbers where the extension is written with a hash at the
43 * end, such as '- 503#'. Note that the only capturing groups should be around
44 * the digits that you want to capture as part of the extension, or else parsing
45 * will fail! We allow two options for representing the accented o - the
46 * character itself, and one in the unicode decomposed form with the combining
47 * acute accent.
48 */
49var EXTN_PATTERNS_FOR_PARSING = (0, _createExtensionPattern["default"])('parsing');
50exports.EXTN_PATTERNS_FOR_PARSING = EXTN_PATTERNS_FOR_PARSING;
51var WHITESPACE_IN_THE_BEGINNING_PATTERN = new RegExp('^[' + _constants.WHITESPACE + ']+');
52var PUNCTUATION_IN_THE_END_PATTERN = new RegExp('[' + _constants.VALID_PUNCTUATION + ']+$'); // // Regular expression for getting opening brackets for a valid number
53// // found using `PHONE_NUMBER_START_PATTERN` for prepending those brackets to the number.
54// const BEFORE_NUMBER_DIGITS_PUNCTUATION = new RegExp('[' + OPENING_BRACKETS + ']+' + '[' + WHITESPACE + ']*' + '$')
55
56var VALID_PRECEDING_CHARACTER_PATTERN = /[^a-zA-Z0-9]/;
57
58function findPhoneNumbers(text, options, metadata) {
59 /* istanbul ignore if */
60 if (options === undefined) {
61 options = {};
62 }
63
64 var search = new PhoneNumberSearch(text, options, metadata);
65 var phones = [];
66
67 while (search.hasNext()) {
68 phones.push(search.next());
69 }
70
71 return phones;
72}
73/**
74 * @return ES6 `for ... of` iterator.
75 */
76
77
78function searchPhoneNumbers(text, options, metadata) {
79 /* istanbul ignore if */
80 if (options === undefined) {
81 options = {};
82 }
83
84 var search = new PhoneNumberSearch(text, options, metadata);
85 return _defineProperty({}, Symbol.iterator, function () {
86 return {
87 next: function next() {
88 if (search.hasNext()) {
89 return {
90 done: false,
91 value: search.next()
92 };
93 }
94
95 return {
96 done: true
97 };
98 }
99 };
100 });
101}
102/**
103 * Extracts a parseable phone number including any opening brackets, etc.
104 * @param {string} text - Input.
105 * @return {object} `{ ?number, ?startsAt, ?endsAt }`.
106 */
107
108
109var PhoneNumberSearch =
110/*#__PURE__*/
111function () {
112 // Iteration tristate.
113 function PhoneNumberSearch(text, options, metadata) {
114 _classCallCheck(this, PhoneNumberSearch);
115
116 _defineProperty(this, "state", 'NOT_READY');
117
118 this.text = text; // If assigning the `{}` default value is moved to the arguments above,
119 // code coverage would decrease for some weird reason.
120
121 this.options = options || {};
122 this.metadata = metadata;
123 this.regexp = new RegExp(_isViablePhoneNumber.VALID_PHONE_NUMBER_WITH_EXTENSION, 'ig');
124 }
125
126 _createClass(PhoneNumberSearch, [{
127 key: "find",
128 value: function find() {
129 var matches = this.regexp.exec(this.text);
130
131 if (!matches) {
132 return;
133 }
134
135 var number = matches[0];
136 var startsAt = matches.index;
137 number = number.replace(WHITESPACE_IN_THE_BEGINNING_PATTERN, '');
138 startsAt += matches[0].length - number.length; // Fixes not parsing numbers with whitespace in the end.
139 // Also fixes not parsing numbers with opening parentheses in the end.
140 // https://github.com/catamphetamine/libphonenumber-js/issues/252
141
142 number = number.replace(PUNCTUATION_IN_THE_END_PATTERN, '');
143 number = (0, _parsePreCandidate["default"])(number);
144 var result = this.parseCandidate(number, startsAt);
145
146 if (result) {
147 return result;
148 } // Tail recursion.
149 // Try the next one if this one is not a valid phone number.
150
151
152 return this.find();
153 }
154 }, {
155 key: "parseCandidate",
156 value: function parseCandidate(number, startsAt) {
157 if (!(0, _isValidPreCandidate["default"])(number, startsAt, this.text)) {
158 return;
159 } // Don't parse phone numbers which are non-phone numbers
160 // due to being part of something else (e.g. a UUID).
161 // https://github.com/catamphetamine/libphonenumber-js/issues/213
162 // Copy-pasted from Google's `PhoneNumberMatcher.js` (`.parseAndValidate()`).
163
164
165 if (!(0, _isValidCandidate["default"])(number, startsAt, this.text, this.options.extended ? 'POSSIBLE' : 'VALID')) {
166 return;
167 } // // Prepend any opening brackets left behind by the
168 // // `PHONE_NUMBER_START_PATTERN` regexp.
169 // const text_before_number = text.slice(this.searching_from, startsAt)
170 // const full_number_starts_at = text_before_number.search(BEFORE_NUMBER_DIGITS_PUNCTUATION)
171 // if (full_number_starts_at >= 0)
172 // {
173 // number = text_before_number.slice(full_number_starts_at) + number
174 // startsAt = full_number_starts_at
175 // }
176 //
177 // this.searching_from = matches.lastIndex
178
179
180 var result = (0, _parse_["default"])(number, this.options, this.metadata);
181
182 if (!result.phone) {
183 return;
184 }
185
186 result.startsAt = startsAt;
187 result.endsAt = startsAt + number.length;
188 return result;
189 }
190 }, {
191 key: "hasNext",
192 value: function hasNext() {
193 if (this.state === 'NOT_READY') {
194 this.last_match = this.find();
195
196 if (this.last_match) {
197 this.state = 'READY';
198 } else {
199 this.state = 'DONE';
200 }
201 }
202
203 return this.state === 'READY';
204 }
205 }, {
206 key: "next",
207 value: function next() {
208 // Check the state and find the next match as a side-effect if necessary.
209 if (!this.hasNext()) {
210 throw new Error('No next element');
211 } // Don't retain that memory any longer than necessary.
212
213
214 var result = this.last_match;
215 this.last_match = null;
216 this.state = 'NOT_READY';
217 return result;
218 }
219 }]);
220
221 return PhoneNumberSearch;
222}();
223
224exports.PhoneNumberSearch = PhoneNumberSearch;
225//# sourceMappingURL=findPhoneNumbers_.js.map
\No newline at end of file