PhoneNumberMatcher.js.map 22 KB

1
  1. {"version":3,"file":"PhoneNumberMatcher.js","names":["USE_NON_GEOGRAPHIC_COUNTRY_CODE","EXTN_PATTERNS_FOR_MATCHING","createExtensionPattern","INNER_MATCHES","pZ","PZ","leadLimit","limit","punctuationLimit","digitBlockLimit","MAX_LENGTH_FOR_NSN","MAX_LENGTH_COUNTRY_CODE","blockLimit","punctuation","VALID_PUNCTUATION","digitSequence","pNd","PATTERN","LEAD_CLASS","UNWANTED_END_CHAR_PATTERN","RegExp","_pN","_pL","NON_DIGITS_PATTERN","MAX_SAFE_INTEGER","Number","Math","pow","PhoneNumberMatcher","text","options","metadata","v2","defaultCallingCode","defaultCountry","isSupportedCountry","undefined","leniency","extended","maxTries","TypeError","Leniency","state","searchIndex","regExpCache","RegExpCache","matches","exec","candidate","offset","index","parsePreCandidate","isValidPreCandidate","match","parseAndVerify","extractInnerMatch","startsAt","endsAt","number","phoneNumber","result","phone","nationalNumber","country","countryCallingCode","ext","substring","innerMatchPattern","isFirstMatch","candidateMatch","innerMatchRegExp","trimAfterFirstMatch","slice","candidateIndexGuess","indexOf","isValidCandidate","parsePhoneNumber","isPossible","length","lastMatch","find","hasNext","Error"],"sources":["../source/PhoneNumberMatcher.js"],"sourcesContent":["/**\r\n * A port of Google's `PhoneNumberMatcher.java`.\r\n * https://github.com/googlei18n/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java\r\n * Date: 08.03.2018.\r\n */\r\n\r\nimport PhoneNumber from './PhoneNumber.js'\r\n\r\nimport {\r\n MAX_LENGTH_FOR_NSN,\r\n MAX_LENGTH_COUNTRY_CODE,\r\n VALID_PUNCTUATION\r\n} from './constants.js'\r\n\r\nimport createExtensionPattern from './helpers/extension/createExtensionPattern.js'\r\n\r\nimport RegExpCache from './findNumbers/RegExpCache.js'\r\n\r\nimport {\r\n\tlimit,\r\n\ttrimAfterFirstMatch\r\n} from './findNumbers/util.js'\r\n\r\nimport {\r\n\t_pL,\r\n\t_pN,\r\n\tpZ,\r\n\tPZ,\r\n\tpNd\r\n} from './findNumbers/utf-8.js'\r\n\r\nimport Leniency from './findNumbers/Leniency.js'\r\nimport parsePreCandidate from './findNumbers/parsePreCandidate.js'\r\nimport isValidPreCandidate from './findNumbers/isValidPreCandidate.js'\r\nimport isValidCandidate, { LEAD_CLASS } from './findNumbers/isValidCandidate.js'\r\n\r\nimport { isSupportedCountry } from './metadata.js'\r\n\r\nimport parsePhoneNumber from './parsePhoneNumber.js'\r\n\r\nconst USE_NON_GEOGRAPHIC_COUNTRY_CODE = false\r\n\r\nconst EXTN_PATTERNS_FOR_MATCHING = createExtensionPattern('matching')\r\n\r\n/**\r\n * Patterns used to extract phone numbers from a larger phone-number-like pattern. These are\r\n * ordered according to specificity. For example, white-space is last since that is frequently\r\n * used in numbers, not just to separate two numbers. We have separate patterns since we don't\r\n * want to break up the phone-number-like text on more than one different kind of symbol at one\r\n * time, although symbols of the same type (e.g. space) can be safely grouped together.\r\n *\r\n * Note that if there is a match, we will always check any text found up to the first match as\r\n * well.\r\n */\r\nconst INNER_MATCHES =\r\n[\r\n\t// Breaks on the slash - e.g. \"651-234-2345/332-445-1234\"\r\n\t'\\\\/+(.*)/',\r\n\r\n\t// Note that the bracket here is inside the capturing group, since we consider it part of the\r\n\t// phone number. Will match a pattern like \"(650) 223 3345 (754) 223 3321\".\r\n\t'(\\\\([^(]*)',\r\n\r\n\t// Breaks on a hyphen - e.g. \"12345 - 332-445-1234 is my number.\"\r\n\t// We require a space on either side of the hyphen for it to be considered a separator.\r\n\t`(?:${pZ}-|-${pZ})${pZ}*(.+)`,\r\n\r\n\t// Various types of wide hyphens. Note we have decided not to enforce a space here, since it's\r\n\t// possible that it's supposed to be used to break two numbers without spaces, and we haven't\r\n\t// seen many instances of it used within a number.\r\n\t`[\\u2012-\\u2015\\uFF0D]${pZ}*(.+)`,\r\n\r\n\t// Breaks on a full stop - e.g. \"12345. 332-445-1234 is my number.\"\r\n\t`\\\\.+${pZ}*([^.]+)`,\r\n\r\n\t// Breaks on space - e.g. \"3324451234 8002341234\"\r\n\t`${pZ}+(${PZ}+)`\r\n]\r\n\r\n// Limit on the number of leading (plus) characters.\r\nconst leadLimit = limit(0, 2)\r\n\r\n// Limit on the number of consecutive punctuation characters.\r\nconst punctuationLimit = limit(0, 4)\r\n\r\n/* The maximum number of digits allowed in a digit-separated block. As we allow all digits in a\r\n * single block, set high enough to accommodate the entire national number and the international\r\n * country code. */\r\nconst digitBlockLimit = MAX_LENGTH_FOR_NSN + MAX_LENGTH_COUNTRY_CODE\r\n\r\n// Limit on the number of blocks separated by punctuation.\r\n// Uses digitBlockLimit since some formats use spaces to separate each digit.\r\nconst blockLimit = limit(0, digitBlockLimit)\r\n\r\n/* A punctuation sequence allowing white space. */\r\nconst punctuation = `[${VALID_PUNCTUATION}]` + punctuationLimit\r\n\r\n// A digits block without punctuation.\r\nconst digitSequence = pNd + limit(1, digitBlockLimit)\r\n\r\n/**\r\n * Phone number pattern allowing optional punctuation.\r\n * The phone number pattern used by `find()`, similar to\r\n * VALID_PHONE_NUMBER, but with the following differences:\r\n * <ul>\r\n * <li>All captures are limited in order to place an upper bound to the text matched by the\r\n * pattern.\r\n * <ul>\r\n * <li>Leading punctuation / plus signs are limited.\r\n * <li>Consecutive occurrences of punctuation are limited.\r\n * <li>Number of digits is limited.\r\n * </ul>\r\n * <li>No whitespace is allowed at the start or end.\r\n * <li>No alpha digits (vanity numbers such as 1-800-SIX-FLAGS) are currently supported.\r\n * </ul>\r\n */\r\nconst PATTERN = '(?:' + LEAD_CLASS + punctuation + ')' + leadLimit\r\n\t+ digitSequence + '(?:' + punctuation + digitSequence + ')' + blockLimit\r\n\t+ '(?:' + EXTN_PATTERNS_FOR_MATCHING + ')?'\r\n\r\n// Regular expression of trailing characters that we want to remove.\r\n// We remove all characters that are not alpha or numerical characters.\r\n// The hash character is retained here, as it may signify\r\n// the previous block was an extension.\r\n//\r\n// // Don't know what does '&&' mean here.\r\n// const UNWANTED_END_CHAR_PATTERN = new RegExp(`[[\\\\P{N}&&\\\\P{L}]&&[^#]]+$`)\r\n//\r\nconst UNWANTED_END_CHAR_PATTERN = new RegExp(`[^${_pN}${_pL}#]+$`)\r\n\r\nconst NON_DIGITS_PATTERN = /(\\D+)/\r\n\r\nconst MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1\r\n\r\n/**\r\n * A stateful class that finds and extracts telephone numbers from {@linkplain CharSequence text}.\r\n * Instances can be created using the {@linkplain PhoneNumberUtil#findNumbers factory methods} in\r\n * {@link PhoneNumberUtil}.\r\n *\r\n * <p>Vanity numbers (phone numbers using alphabetic digits such as <tt>1-800-SIX-FLAGS</tt> are\r\n * not found.\r\n *\r\n * <p>This class is not thread-safe.\r\n */\r\nexport default class PhoneNumberMatcher\r\n{\r\n /**\r\n * @param {string} text — the character sequence that we will search, null for no text.\r\n * @param {'POSSIBLE'|'VALID'|'STRICT_GROUPING'|'EXACT_GROUPING'} [options.leniency] — The leniency to use when evaluating candidate phone numbers. See `source/findNumbers/Leniency.js` for more details.\r\n * @param {number} [options.maxTries] — The maximum number of invalid numbers to try before giving up on the text. This is to cover degenerate cases where the text has a lot of false positives in it. Must be >= 0.\r\n */\r\n constructor(text = '', options = {}, metadata)\r\n {\r\n options = {\r\n v2: options.v2,\r\n defaultCallingCode: options.defaultCallingCode,\r\n defaultCountry: options.defaultCountry && isSupportedCountry(options.defaultCountry, metadata) ? options.defaultCountry : undefined,\r\n leniency: options.leniency || (options.extended ? 'POSSIBLE' : 'VALID'),\r\n maxTries: options.maxTries || MAX_SAFE_INTEGER\r\n }\r\n\r\n // Validate `leniency`.\r\n\t\tif (!options.leniency) {\r\n\t\t\tthrow new TypeError('`leniency` is required')\r\n\t\t}\r\n if (options.leniency !== 'POSSIBLE' && options.leniency !== 'VALID') {\r\n throw new TypeError(`Invalid \\`leniency\\`: \"${options.leniency}\". Supported values: \"POSSIBLE\", \"VALID\".`)\r\n }\r\n\r\n // Validate `maxTries`.\r\n\t\tif (options.maxTries < 0) {\r\n\t\t\tthrow new TypeError('`maxTries` must be `>= 0`')\r\n\t\t}\r\n\r\n\t\tthis.text = text\r\n\t\tthis.options = options\r\n this.metadata = metadata\r\n\r\n\t\t// The degree of phone number validation.\r\n\t\tthis.leniency = Leniency[options.leniency]\r\n\r\n\t\tif (!this.leniency) {\r\n\t\t\tthrow new TypeError(`Unknown leniency: \"${options.leniency}\"`)\r\n\t\t}\r\n\r\n\t\t/** The maximum number of retries after matching an invalid number. */\r\n\t\tthis.maxTries = options.maxTries\r\n\r\n\t\tthis.PATTERN = new RegExp(PATTERN, 'ig')\r\n\r\n /** The iteration tristate. */\r\n this.state = 'NOT_READY'\r\n\r\n /** The next index to start searching at. Undefined in {@link State#DONE}. */\r\n this.searchIndex = 0\r\n\r\n // A cache for frequently used country-specific regular expressions. Set to 32 to cover ~2-3\r\n // countries being used for the same doc with ~10 patterns for each country. Some pages will have\r\n // a lot more countries in use, but typically fewer numbers for each so expanding the cache for\r\n // that use-case won't have a lot of benefit.\r\n this.regExpCache = new RegExpCache(32)\r\n }\r\n\r\n /**\r\n * Attempts to find the next subsequence in the searched sequence on or after {@code searchIndex}\r\n * that represents a phone number. Returns the next match, null if none was found.\r\n *\r\n * @param index the search index to start searching at\r\n * @return the phone number match found, null if none can be found\r\n */\r\n\tfind() {\r\n\t\t// // Reset the regular expression.\r\n\t\t// this.PATTERN.lastIndex = index\r\n\r\n\t\tlet matches\r\n\t\twhile ((this.maxTries > 0) && (matches = this.PATTERN.exec(this.text)) !== null) {\r\n\t\t\tlet candidate = matches[0]\r\n\t\t\tconst offset = matches.index\r\n\r\n\t\t\tcandidate = parsePreCandidate(candidate)\r\n\r\n\t\t\tif (isValidPreCandidate(candidate, offset, this.text)) {\r\n\t\t\t\tconst match =\r\n\t\t\t\t\t// Try to come up with a valid match given the entire candidate.\r\n\t\t\t\t\tthis.parseAndVerify(candidate, offset, this.text)\r\n\t\t\t\t\t// If that failed, try to find an \"inner match\" -\r\n\t\t\t\t\t// there might be a phone number within this candidate.\r\n\t\t\t\t\t|| this.extractInnerMatch(candidate, offset, this.text)\r\n\r\n\t\t\t\tif (match) {\r\n\t\t\t\t\tif (this.options.v2) {\r\n\t\t\t\t\t\treturn {\r\n\t\t\t\t\t\t\tstartsAt: match.startsAt,\r\n\t\t\t\t\t\t\tendsAt: match.endsAt,\r\n\t\t\t\t\t\t\tnumber: match.phoneNumber\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n const { phoneNumber } = match\r\n\r\n const result = {\r\n startsAt: match.startsAt,\r\n endsAt: match.endsAt,\r\n phone: phoneNumber.nationalNumber\r\n }\r\n\r\n if (phoneNumber.country) {\r\n /* istanbul ignore if */\r\n if (USE_NON_GEOGRAPHIC_COUNTRY_CODE && country === '001') {\r\n result.countryCallingCode = phoneNumber.countryCallingCode\r\n } else {\r\n result.country = phoneNumber.country\r\n }\r\n } else {\r\n result.countryCallingCode = phoneNumber.countryCallingCode\r\n }\r\n\r\n if (phoneNumber.ext) {\r\n result.ext = phoneNumber.ext\r\n }\r\n\r\n return result\r\n }\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tthis.maxTries--\r\n\t\t}\r\n\t}\r\n\r\n /**\r\n * Attempts to extract a match from `substring`\r\n * if the substring itself does not qualify as a match.\r\n */\r\n extractInnerMatch(substring, offset, text) {\r\n for (const innerMatchPattern of INNER_MATCHES) {\r\n let isFirstMatch = true\r\n let candidateMatch\r\n const innerMatchRegExp = new RegExp(innerMatchPattern, 'g')\r\n while (this.maxTries > 0 && (candidateMatch = innerMatchRegExp.exec(substring)) !== null) {\r\n if (isFirstMatch) {\r\n // We should handle any group before this one too.\r\n const candidate = trimAfterFirstMatch(\r\n UNWANTED_END_CHAR_PATTERN,\r\n substring.slice(0, candidateMatch.index)\r\n )\r\n\r\n const match = this.parseAndVerify(candidate, offset, text)\r\n\r\n if (match) {\r\n return match\r\n }\r\n\r\n this.maxTries--\r\n isFirstMatch = false\r\n }\r\n\r\n const candidate = trimAfterFirstMatch(UNWANTED_END_CHAR_PATTERN, candidateMatch[1])\r\n\r\n // Java code does `groupMatcher.start(1)` here,\r\n // but there's no way in javascript to get a `candidate` start index,\r\n // therefore resort to using this kind of an approximation.\r\n // (`groupMatcher` is called `candidateInSubstringMatch` in this javascript port)\r\n // https://stackoverflow.com/questions/15934353/get-index-of-each-capture-in-a-javascript-regex\r\n const candidateIndexGuess = substring.indexOf(candidate, candidateMatch.index)\r\n\r\n const match = this.parseAndVerify(candidate, offset + candidateIndexGuess, text)\r\n if (match) {\r\n return match\r\n }\r\n\r\n this.maxTries--\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Parses a phone number from the `candidate` using `parse` and\r\n * verifies it matches the requested `leniency`. If parsing and verification succeed,\r\n * a corresponding `PhoneNumberMatch` is returned, otherwise this method returns `null`.\r\n *\r\n * @param candidate the candidate match\r\n * @param offset the offset of {@code candidate} within {@link #text}\r\n * @return the parsed and validated phone number match, or null\r\n */\r\n parseAndVerify(candidate, offset, text) {\r\n if (!isValidCandidate(candidate, offset, text, this.options.leniency)) {\r\n return\r\n \t}\r\n\r\n const phoneNumber = parsePhoneNumber(\r\n candidate,\r\n {\r\n extended: true,\r\n defaultCountry: this.options.defaultCountry,\r\n defaultCallingCode: this.options.defaultCallingCode\r\n },\r\n this.metadata\r\n )\r\n\r\n if (!phoneNumber) {\r\n return\r\n }\r\n\r\n if (!phoneNumber.isPossible()) {\r\n return\r\n }\r\n\r\n if (this.leniency(phoneNumber, {\r\n candidate,\r\n defaultCountry: this.options.defaultCountry,\r\n metadata: this.metadata,\r\n regExpCache: this.regExpCache\r\n })) {\r\n return {\r\n startsAt: offset,\r\n endsAt: offset + candidate.length,\r\n phoneNumber\r\n }\r\n }\r\n }\r\n\r\n hasNext()\r\n {\r\n if (this.state === 'NOT_READY')\r\n {\r\n this.lastMatch = this.find() // (this.searchIndex)\r\n\r\n if (this.lastMatch)\r\n {\r\n // this.searchIndex = this.lastMatch.endsAt\r\n this.state = 'READY'\r\n }\r\n else\r\n {\r\n this.state = 'DONE'\r\n }\r\n }\r\n\r\n return this.state === 'READY'\r\n }\r\n\r\n next()\r\n {\r\n // Check the state and find the next match as a side-effect if necessary.\r\n if (!this.hasNext())\r\n {\r\n throw new Error('No next element')\r\n }\r\n\r\n // Don't retain that memory any longer than necessary.\r\n const result = this.lastMatch\r\n this.lastMatch = null\r\n this.state = 'NOT_READY'\r\n return result\r\n }\r\n}"],"mappings":"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"}