You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					222 lines
				
				8.1 KiB
			
		
		
			
		
	
	
					222 lines
				
				8.1 KiB
			| 
											3 years ago
										 | "use strict"; | ||
|  | 
 | ||
|  | Object.defineProperty(exports, "__esModule", { | ||
|  |   value: true | ||
|  | }); | ||
|  | exports.PhoneNumberSearch = exports.EXTN_PATTERNS_FOR_PARSING = void 0; | ||
|  | exports["default"] = findPhoneNumbers; | ||
|  | exports.searchPhoneNumbers = searchPhoneNumbers; | ||
|  | 
 | ||
|  | var _constants = require("./constants.js"); | ||
|  | 
 | ||
|  | var _parse_ = _interopRequireDefault(require("./parse_.js")); | ||
|  | 
 | ||
|  | var _isViablePhoneNumber = require("./helpers/isViablePhoneNumber.js"); | ||
|  | 
 | ||
|  | var _createExtensionPattern = _interopRequireDefault(require("./helpers/extension/createExtensionPattern.js")); | ||
|  | 
 | ||
|  | var _parsePreCandidate = _interopRequireDefault(require("./findNumbers/parsePreCandidate.js")); | ||
|  | 
 | ||
|  | var _isValidPreCandidate = _interopRequireDefault(require("./findNumbers/isValidPreCandidate.js")); | ||
|  | 
 | ||
|  | var _isValidCandidate = _interopRequireDefault(require("./findNumbers/isValidCandidate.js")); | ||
|  | 
 | ||
|  | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
|  | 
 | ||
|  | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
|  | 
 | ||
|  | 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); } } | ||
|  | 
 | ||
|  | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } | ||
|  | 
 | ||
|  | 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; } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Regexp of all possible ways to write extensions, for use when parsing. This | ||
|  |  * will be run as a case-insensitive regexp match. Wide character versions are | ||
|  |  * also provided after each ASCII version. There are three regular expressions | ||
|  |  * here. The first covers RFC 3966 format, where the extension is added using | ||
|  |  * ';ext='. The second more generic one starts with optional white space and | ||
|  |  * ends with an optional full stop (.), followed by zero or more spaces/tabs | ||
|  |  * /commas and then the numbers themselves. The other one covers the special | ||
|  |  * case of American numbers where the extension is written with a hash at the | ||
|  |  * end, such as '- 503#'. Note that the only capturing groups should be around | ||
|  |  * the digits that you want to capture as part of the extension, or else parsing | ||
|  |  * will fail! We allow two options for representing the accented o - the | ||
|  |  * character itself, and one in the unicode decomposed form with the combining | ||
|  |  * acute accent. | ||
|  |  */ | ||
|  | var EXTN_PATTERNS_FOR_PARSING = (0, _createExtensionPattern["default"])('parsing'); | ||
|  | exports.EXTN_PATTERNS_FOR_PARSING = EXTN_PATTERNS_FOR_PARSING; | ||
|  | var WHITESPACE_IN_THE_BEGINNING_PATTERN = new RegExp('^[' + _constants.WHITESPACE + ']+'); | ||
|  | var PUNCTUATION_IN_THE_END_PATTERN = new RegExp('[' + _constants.VALID_PUNCTUATION + ']+$'); // // Regular expression for getting opening brackets for a valid number
 | ||
|  | // // found using `PHONE_NUMBER_START_PATTERN` for prepending those brackets to the number.
 | ||
|  | // const BEFORE_NUMBER_DIGITS_PUNCTUATION = new RegExp('[' + OPENING_BRACKETS + ']+' + '[' + WHITESPACE + ']*' + '$')
 | ||
|  | 
 | ||
|  | var VALID_PRECEDING_CHARACTER_PATTERN = /[^a-zA-Z0-9]/; | ||
|  | 
 | ||
|  | function findPhoneNumbers(text, options, metadata) { | ||
|  |   /* istanbul ignore if */ | ||
|  |   if (options === undefined) { | ||
|  |     options = {}; | ||
|  |   } | ||
|  | 
 | ||
|  |   var search = new PhoneNumberSearch(text, options, metadata); | ||
|  |   var phones = []; | ||
|  | 
 | ||
|  |   while (search.hasNext()) { | ||
|  |     phones.push(search.next()); | ||
|  |   } | ||
|  | 
 | ||
|  |   return phones; | ||
|  | } | ||
|  | /** | ||
|  |  * @return ES6 `for ... of` iterator. | ||
|  |  */ | ||
|  | 
 | ||
|  | 
 | ||
|  | function searchPhoneNumbers(text, options, metadata) { | ||
|  |   /* istanbul ignore if */ | ||
|  |   if (options === undefined) { | ||
|  |     options = {}; | ||
|  |   } | ||
|  | 
 | ||
|  |   var search = new PhoneNumberSearch(text, options, metadata); | ||
|  |   return _defineProperty({}, Symbol.iterator, function () { | ||
|  |     return { | ||
|  |       next: function next() { | ||
|  |         if (search.hasNext()) { | ||
|  |           return { | ||
|  |             done: false, | ||
|  |             value: search.next() | ||
|  |           }; | ||
|  |         } | ||
|  | 
 | ||
|  |         return { | ||
|  |           done: true | ||
|  |         }; | ||
|  |       } | ||
|  |     }; | ||
|  |   }); | ||
|  | } | ||
|  | /** | ||
|  |  * Extracts a parseable phone number including any opening brackets, etc. | ||
|  |  * @param  {string} text - Input. | ||
|  |  * @return {object} `{ ?number, ?startsAt, ?endsAt }`. | ||
|  |  */ | ||
|  | 
 | ||
|  | 
 | ||
|  | var PhoneNumberSearch = /*#__PURE__*/function () { | ||
|  |   function PhoneNumberSearch(text, options, metadata) { | ||
|  |     _classCallCheck(this, PhoneNumberSearch); | ||
|  | 
 | ||
|  |     this.text = text; // If assigning the `{}` default value is moved to the arguments above,
 | ||
|  |     // code coverage would decrease for some weird reason.
 | ||
|  | 
 | ||
|  |     this.options = options || {}; | ||
|  |     this.metadata = metadata; // Iteration tristate.
 | ||
|  | 
 | ||
|  |     this.state = 'NOT_READY'; | ||
|  |     this.regexp = new RegExp(_isViablePhoneNumber.VALID_PHONE_NUMBER_WITH_EXTENSION, 'ig'); | ||
|  |   } | ||
|  | 
 | ||
|  |   _createClass(PhoneNumberSearch, [{ | ||
|  |     key: "find", | ||
|  |     value: function find() { | ||
|  |       var matches = this.regexp.exec(this.text); | ||
|  | 
 | ||
|  |       if (!matches) { | ||
|  |         return; | ||
|  |       } | ||
|  | 
 | ||
|  |       var number = matches[0]; | ||
|  |       var startsAt = matches.index; | ||
|  |       number = number.replace(WHITESPACE_IN_THE_BEGINNING_PATTERN, ''); | ||
|  |       startsAt += matches[0].length - number.length; // Fixes not parsing numbers with whitespace in the end.
 | ||
|  |       // Also fixes not parsing numbers with opening parentheses in the end.
 | ||
|  |       // https://github.com/catamphetamine/libphonenumber-js/issues/252
 | ||
|  | 
 | ||
|  |       number = number.replace(PUNCTUATION_IN_THE_END_PATTERN, ''); | ||
|  |       number = (0, _parsePreCandidate["default"])(number); | ||
|  |       var result = this.parseCandidate(number, startsAt); | ||
|  | 
 | ||
|  |       if (result) { | ||
|  |         return result; | ||
|  |       } // Tail recursion.
 | ||
|  |       // Try the next one if this one is not a valid phone number.
 | ||
|  | 
 | ||
|  | 
 | ||
|  |       return this.find(); | ||
|  |     } | ||
|  |   }, { | ||
|  |     key: "parseCandidate", | ||
|  |     value: function parseCandidate(number, startsAt) { | ||
|  |       if (!(0, _isValidPreCandidate["default"])(number, startsAt, this.text)) { | ||
|  |         return; | ||
|  |       } // Don't parse phone numbers which are non-phone numbers
 | ||
|  |       // due to being part of something else (e.g. a UUID).
 | ||
|  |       // https://github.com/catamphetamine/libphonenumber-js/issues/213
 | ||
|  |       // Copy-pasted from Google's `PhoneNumberMatcher.js` (`.parseAndValidate()`).
 | ||
|  | 
 | ||
|  | 
 | ||
|  |       if (!(0, _isValidCandidate["default"])(number, startsAt, this.text, this.options.extended ? 'POSSIBLE' : 'VALID')) { | ||
|  |         return; | ||
|  |       } // // Prepend any opening brackets left behind by the
 | ||
|  |       // // `PHONE_NUMBER_START_PATTERN` regexp.
 | ||
|  |       // const text_before_number = text.slice(this.searching_from, startsAt)
 | ||
|  |       // const full_number_starts_at = text_before_number.search(BEFORE_NUMBER_DIGITS_PUNCTUATION)
 | ||
|  |       // if (full_number_starts_at >= 0)
 | ||
|  |       // {
 | ||
|  |       // 	number   = text_before_number.slice(full_number_starts_at) + number
 | ||
|  |       // 	startsAt = full_number_starts_at
 | ||
|  |       // }
 | ||
|  |       //
 | ||
|  |       // this.searching_from = matches.lastIndex
 | ||
|  | 
 | ||
|  | 
 | ||
|  |       var result = (0, _parse_["default"])(number, this.options, this.metadata); | ||
|  | 
 | ||
|  |       if (!result.phone) { | ||
|  |         return; | ||
|  |       } | ||
|  | 
 | ||
|  |       result.startsAt = startsAt; | ||
|  |       result.endsAt = startsAt + number.length; | ||
|  |       return result; | ||
|  |     } | ||
|  |   }, { | ||
|  |     key: "hasNext", | ||
|  |     value: function hasNext() { | ||
|  |       if (this.state === 'NOT_READY') { | ||
|  |         this.last_match = this.find(); | ||
|  | 
 | ||
|  |         if (this.last_match) { | ||
|  |           this.state = 'READY'; | ||
|  |         } else { | ||
|  |           this.state = 'DONE'; | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |       return this.state === 'READY'; | ||
|  |     } | ||
|  |   }, { | ||
|  |     key: "next", | ||
|  |     value: function next() { | ||
|  |       // Check the state and find the next match as a side-effect if necessary.
 | ||
|  |       if (!this.hasNext()) { | ||
|  |         throw new Error('No next element'); | ||
|  |       } // Don't retain that memory any longer than necessary.
 | ||
|  | 
 | ||
|  | 
 | ||
|  |       var result = this.last_match; | ||
|  |       this.last_match = null; | ||
|  |       this.state = 'NOT_READY'; | ||
|  |       return result; | ||
|  |     } | ||
|  |   }]); | ||
|  | 
 | ||
|  |   return PhoneNumberSearch; | ||
|  | }(); | ||
|  | 
 | ||
|  | exports.PhoneNumberSearch = PhoneNumberSearch; | ||
|  | //# sourceMappingURL=findPhoneNumbers_.js.map
 |