UNPKG

21.3 kBSource Map (JSON)View Raw
1{"version":3,"sources":["../source/PhoneNumberMatcher.js"],"names":["EXTN_PATTERNS_FOR_MATCHING","INNER_MATCHES","pZ","PZ","leadLimit","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","RegExpCache","defaultCallingCode","defaultCountry","undefined","leniency","extended","maxTries","TypeError","Leniency","matches","exec","candidate","offset","index","match","parseAndVerify","extractInnerMatch","v2","phoneNumber","PhoneNumber","country","countryCallingCode","phone","ext","startsAt","endsAt","number","substring","innerMatchPattern","isFirstMatch","candidateMatch","innerMatchRegExp","slice","candidateIndexGuess","indexOf","possible","regExpCache","result","length","state","lastMatch","find","hasNext","Error"],"mappings":"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","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'\r\n\r\nimport {\r\n MAX_LENGTH_FOR_NSN,\r\n MAX_LENGTH_COUNTRY_CODE,\r\n VALID_PUNCTUATION\r\n} from './constants'\r\n\r\nimport createExtensionPattern from './helpers/extension/createExtensionPattern'\r\n\r\nimport RegExpCache from './findNumbers/RegExpCache'\r\n\r\nimport {\r\n\tlimit,\r\n\ttrimAfterFirstMatch\r\n} from './findNumbers/util'\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'\r\n\r\nimport Leniency from './findNumbers/Leniency'\r\nimport parsePreCandidate from './findNumbers/parsePreCandidate'\r\nimport isValidPreCandidate from './findNumbers/isValidPreCandidate'\r\nimport isValidCandidate, { LEAD_CLASS } from './findNumbers/isValidCandidate'\r\n\r\nimport { isSupportedCountry } from './metadata'\r\n\r\nimport parseNumber from './parse_'\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 /** The iteration tristate. */\r\n state = 'NOT_READY'\r\n\r\n /** The next index to start searching at. Undefined in {@link State#DONE}. */\r\n 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 regExpCache = new RegExpCache(32)\r\n\r\n /**\r\n * Creates a new instance. See the factory methods in {@link PhoneNumberUtil} on how to obtain a\r\n * new instance.\r\n *\r\n * @param util the phone number util to use\r\n * @param text the character sequence that we will search, null for no text\r\n * @param country the country to assume for phone numbers not written in international format\r\n * (with a leading plus, or with the international dialing prefix of the specified region).\r\n * May be null or \"ZZ\" if only numbers with a leading plus should be\r\n * considered.\r\n * @param leniency the leniency to use when evaluating candidate phone numbers\r\n * @param maxTries the maximum number of invalid numbers to try before giving up on the text.\r\n * This is to cover degenerate cases where the text has a lot of false positives in it. Must\r\n * be {@code >= 0}.\r\n */\r\n constructor(text = '', options = {}, metadata)\r\n {\r\n options = {\r\n ...options,\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\t\tif (!options.leniency) {\r\n\t\t\tthrow new TypeError('`Leniency` not supplied')\r\n\t\t}\r\n\r\n\t\tif (options.maxTries < 0) {\r\n\t\t\tthrow new TypeError('`maxTries` not supplied')\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 validation requested. */\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\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\tconst phoneNumber = new PhoneNumber(\r\n match.country || match.countryCallingCode,\r\n match.phone,\r\n this.metadata\r\n )\r\n\t\t\t\t\t\tif (match.ext) {\r\n\t\t\t\t\t\t\tphoneNumber.ext = match.ext\r\n\t\t\t\t\t\t}\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: phoneNumber\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn match\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 `parseNumber` 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 number = parseNumber(\r\n candidate, {\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 (!number.possible) {\r\n return\r\n }\r\n\r\n if (this.leniency(number, candidate, this.metadata, this.regExpCache)) {\r\n // // We used parseAndKeepRawInput to create this number,\r\n // // but for now we don't return the extra values parsed.\r\n // // TODO: stop clearing all values here and switch all users over\r\n // // to using rawInput() rather than the rawString() of PhoneNumberMatch.\r\n // number.clearCountryCodeSource()\r\n // number.clearRawInput()\r\n // number.clearPreferredDomesticCarrierCode()\r\n\r\n const result = {\r\n startsAt: offset,\r\n endsAt: offset + candidate.length,\r\n phone: number.phone\r\n }\r\n\r\n if (number.country && number.country !== '001') {\r\n result.country = number.country\r\n } else {\r\n result.countryCallingCode = number.countryCallingCode\r\n }\r\n\r\n if (number.ext) {\r\n result.ext = number.ext\r\n }\r\n\r\n return result\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}"],"file":"PhoneNumberMatcher.js"}
\No newline at end of file