{"version":3,"sources":["../../source/findNumbers/Leniency.js"],"names":["isValidNumber","parseDigits","startsWith","endsWith","POSSIBLE","number","candidate","metadata","VALID","undefined","containsOnlyValidXChars","toString","STRICT_GROUPING","regExpCache","candidateString","containsMoreThanOneSlashInNationalNumber","isNationalPrefixPresentIfRequired","checkNumberGroupingIsValid","allNumberGroupsRemainGrouped","EXACT_GROUPING","allNumberGroupsAreExactlyPresent","index","length","charAtIndex","charAt","charAtNextIndex","util","isNumberMatch","substring","MatchType","NSN_MATCH","ext","_metadata","getCountryCodeSource","phoneNumberRegion","getRegionCodeForCountryCode","getCountryCode","getMetadataForRegion","nationalNumber","getNationalSignificantNumber","formatRule","chooseFormattingPatternForNumber","numberFormats","getNationalPrefixFormattingRule","getNationalPrefixOptionalWhenFormatting","PhoneNumberUtil","formattingRuleHasFirstGroupOnly","rawInputCopy","normalizeDigitsOnly","getRawInput","maybeStripNationalPrefixAndCarrierCode","firstSlashInBodyIndex","indexOf","secondSlashInBodyIndex","candidateHasCountryCode","CountryCodeSource","FROM_NUMBER_WITH_PLUS_SIGN","FROM_NUMBER_WITHOUT_PLUS_SIGN","String","slice","checkGroups","normalizedCandidate","normalizeDigits","formattedNumberGroups","getNationalNumberGroups","alternateFormats","MetadataManager","getAlternateFormatsForCountry","nationalSignificantNumber","alternateFormat","leadingDigitsPatterns","leadingDigitsRegExp","getPatternForRegExp","test","formattingPattern","formatNsnUsingPattern","split","rfc3966Format","formatNumber","endIndex","startIndex","candidateGroups","NON_DIGITS_PATTERN","candidateNumberGroupIndex","hasExtension","contains","formattedNumberGroupIndex","fromIndex","FROM_DEFAULT_COUNTRY","countryCode","i","region","getNddPrefixForRegion","Character","isDigit","getExtension"],"mappings":"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","sourcesContent":["import isValidNumber from '../validate_'\r\nimport parseDigits from '../parseDigits'\r\n\r\nimport {\r\n\tstartsWith,\r\n\tendsWith\r\n} from './util'\r\n\r\n/**\r\n * Leniency when finding potential phone numbers in text segments\r\n * The levels here are ordered in increasing strictness.\r\n */\r\nexport default\r\n{\r\n\t/**\r\n\t * Phone numbers accepted are \"possible\", but not necessarily \"valid\".\r\n\t */\r\n\tPOSSIBLE(number, candidate, metadata)\r\n\t{\r\n\t\treturn true\r\n\t},\r\n\r\n\t/**\r\n\t * Phone numbers accepted are \"possible\" and \"valid\".\r\n\t * Numbers written in national format must have their national-prefix\r\n\t * present if it is usually written for a number of this type.\r\n\t */\r\n\tVALID(number, candidate, metadata)\r\n\t{\r\n\t\tif (!isValidNumber(number, undefined, metadata) ||\r\n\t\t\t!containsOnlyValidXChars(number, candidate.toString(), metadata))\r\n\t\t{\r\n\t\t\treturn false\r\n\t\t}\r\n\r\n // Skipped for simplicity.\r\n\t\t// return isNationalPrefixPresentIfRequired(number, metadata)\r\n return true\r\n },\r\n\r\n\t/**\r\n\t * Phone numbers accepted are \"valid\" and\r\n\t * are grouped in a possible way for this locale. For example, a US number written as\r\n\t * \"65 02 53 00 00\" and \"650253 0000\" are not accepted at this leniency level, whereas\r\n\t * \"650 253 0000\", \"650 2530000\" or \"6502530000\" are.\r\n\t * Numbers with more than one '/' symbol in the national significant number\r\n\t * are also dropped at this level.\r\n\t *\r\n\t * Warning: This level might result in lower coverage especially for regions outside of\r\n\t * country code \"+1\". If you are not sure about which level to use,\r\n\t * email the discussion group libphonenumber-discuss@googlegroups.com.\r\n\t */\r\n\tSTRICT_GROUPING(number, candidate, metadata, regExpCache)\r\n\t{\r\n\t\tconst candidateString = candidate.toString()\r\n\r\n\t\tif (!isValidNumber(number, undefined, metadata)\r\n\t\t\t|| !containsOnlyValidXChars(number, candidateString, metadata)\r\n\t\t\t|| containsMoreThanOneSlashInNationalNumber(number, candidateString)\r\n\t\t\t|| !isNationalPrefixPresentIfRequired(number, metadata))\r\n\t\t{\r\n\t\t\treturn false\r\n\t\t}\r\n\r\n\t\treturn checkNumberGroupingIsValid\r\n\t\t(\r\n\t\t\tnumber,\r\n\t\t\tcandidate,\r\n\t\t\tmetadata,\r\n\t\t\tallNumberGroupsRemainGrouped,\r\n\t\t\tregExpCache\r\n\t\t)\r\n },\r\n\r\n\t/**\r\n\t * Phone numbers accepted are {@linkplain PhoneNumberUtil#isValidNumber(PhoneNumber) valid} and\r\n\t * are grouped in the same way that we would have formatted it, or as a single block. For\r\n\t * example, a US number written as \"650 2530000\" is not accepted at this leniency level, whereas\r\n\t * \"650 253 0000\" or \"6502530000\" are.\r\n\t * Numbers with more than one '/' symbol are also dropped at this level.\r\n\t *

\r\n\t * Warning: This level might result in lower coverage especially for regions outside of country\r\n\t * code \"+1\". If you are not sure about which level to use, email the discussion group\r\n\t * libphonenumber-discuss@googlegroups.com.\r\n\t */\r\n\tEXACT_GROUPING(number, candidate, metadata, regExpCache)\r\n\t{\r\n\t\tconst candidateString = candidate.toString()\r\n\r\n\t\tif (!isValidNumber(number, undefined, metadata)\r\n\t\t\t|| !containsOnlyValidXChars(number, candidateString, metadata)\r\n\t\t\t|| containsMoreThanOneSlashInNationalNumber(number, candidateString)\r\n\t\t\t|| !isNationalPrefixPresentIfRequired(number, metadata))\r\n\t\t{\r\n\t\t\treturn false\r\n\t\t}\r\n\r\n\t\treturn checkNumberGroupingIsValid\r\n\t\t(\r\n\t\t\tnumber,\r\n\t\t\tcandidate,\r\n\t\t\tmetadata,\r\n\t\t\tallNumberGroupsAreExactlyPresent,\r\n\t\t\tregExpCache\r\n\t\t)\r\n\t}\r\n}\r\n\r\nfunction containsOnlyValidXChars(number, candidate, metadata)\r\n{\r\n // The characters 'x' and 'X' can be (1) a carrier code, in which case they always precede the\r\n // national significant number or (2) an extension sign, in which case they always precede the\r\n // extension number. We assume a carrier code is more than 1 digit, so the first case has to\r\n // have more than 1 consecutive 'x' or 'X', whereas the second case can only have exactly 1 'x'\r\n // or 'X'. We ignore the character if it appears as the last character of the string.\r\n for (let index = 0; index < candidate.length - 1; index++)\r\n {\r\n const charAtIndex = candidate.charAt(index)\r\n\r\n if (charAtIndex === 'x' || charAtIndex === 'X')\r\n {\r\n const charAtNextIndex = candidate.charAt(index + 1)\r\n\r\n if (charAtNextIndex === 'x' || charAtNextIndex === 'X')\r\n {\r\n // This is the carrier code case, in which the 'X's always precede the national\r\n // significant number.\r\n index++\r\n if (util.isNumberMatch(number, candidate.substring(index)) != MatchType.NSN_MATCH)\r\n {\r\n return false\r\n }\r\n\t // This is the extension sign case, in which the 'x' or 'X' should always precede the\r\n\t // extension number.\r\n }\r\n else if (parseDigits(candidate.substring(index)) !== number.ext)\r\n {\r\n return false\r\n }\r\n }\r\n }\r\n\r\n return true\r\n}\r\n\r\nfunction isNationalPrefixPresentIfRequired(number, _metadata)\r\n{\r\n // First, check how we deduced the country code. If it was written in international format, then\r\n // the national prefix is not required.\r\n if (number.getCountryCodeSource() != 'FROM_DEFAULT_COUNTRY')\r\n {\r\n return true\r\n }\r\n\r\n const phoneNumberRegion = util.getRegionCodeForCountryCode(number.getCountryCode())\r\n\r\n const metadata = util.getMetadataForRegion(phoneNumberRegion)\r\n if (metadata == null)\r\n {\r\n return true\r\n }\r\n\r\n // Check if a national prefix should be present when formatting this number.\r\n const nationalNumber = util.getNationalSignificantNumber(number)\r\n const formatRule = util.chooseFormattingPatternForNumber(metadata.numberFormats(), nationalNumber)\r\n\r\n // To do this, we check that a national prefix formatting rule was present\r\n // and that it wasn't just the first-group symbol ($1) with punctuation.\r\n if (formatRule && formatRule.getNationalPrefixFormattingRule().length > 0)\r\n {\r\n if (formatRule.getNationalPrefixOptionalWhenFormatting())\r\n {\r\n // The national-prefix is optional in these cases, so we don't need to check if it was\r\n // present.\r\n return true\r\n }\r\n\r\n if (PhoneNumberUtil.formattingRuleHasFirstGroupOnly(\r\n formatRule.getNationalPrefixFormattingRule()))\r\n {\r\n // National Prefix not needed for this number.\r\n return true\r\n }\r\n\r\n // Normalize the remainder.\r\n const rawInputCopy = PhoneNumberUtil.normalizeDigitsOnly(number.getRawInput())\r\n\r\n // Check if we found a national prefix and/or carrier code at the start of the raw input, and\r\n // return the result.\r\n return util.maybeStripNationalPrefixAndCarrierCode(rawInputCopy, metadata, null)\r\n }\r\n\r\n return true\r\n}\r\n\r\nexport function containsMoreThanOneSlashInNationalNumber(number, candidate)\r\n{\r\n const firstSlashInBodyIndex = candidate.indexOf('/')\r\n if (firstSlashInBodyIndex < 0)\r\n {\r\n // No slashes, this is okay.\r\n return false\r\n }\r\n\r\n // Now look for a second one.\r\n const secondSlashInBodyIndex = candidate.indexOf('/', firstSlashInBodyIndex + 1)\r\n if (secondSlashInBodyIndex < 0)\r\n {\r\n // Only one slash, this is okay.\r\n return false\r\n }\r\n\r\n // If the first slash is after the country calling code, this is permitted.\r\n const candidateHasCountryCode =\r\n (number.getCountryCodeSource() === CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN\r\n || number.getCountryCodeSource() === CountryCodeSource.FROM_NUMBER_WITHOUT_PLUS_SIGN)\r\n\r\n if (candidateHasCountryCode\r\n && PhoneNumberUtil.normalizeDigitsOnly(candidate.substring(0, firstSlashInBodyIndex))\r\n === String(number.getCountryCode()))\r\n {\r\n // Any more slashes and this is illegal.\r\n return candidate.slice(secondSlashInBodyIndex + 1).indexOf('/') >= 0\r\n }\r\n\r\n return true\r\n}\r\n\r\nfunction checkNumberGroupingIsValid(\r\n number,\r\n candidate,\r\n metadata,\r\n checkGroups,\r\n regExpCache\r\n) {\r\n const normalizedCandidate = normalizeDigits(candidate, true /* keep non-digits */)\r\n let formattedNumberGroups = getNationalNumberGroups(metadata, number, null)\r\n if (checkGroups(metadata, number, normalizedCandidate, formattedNumberGroups)) {\r\n return true\r\n }\r\n\r\n // If this didn't pass, see if there are any alternate formats that match, and try them instead.\r\n const alternateFormats = MetadataManager.getAlternateFormatsForCountry(number.getCountryCode())\r\n const nationalSignificantNumber = util.getNationalSignificantNumber(number)\r\n\r\n if (alternateFormats) {\r\n for (const alternateFormat of alternateFormats.numberFormats()) {\r\n if (alternateFormat.leadingDigitsPatterns().length > 0) {\r\n // There is only one leading digits pattern for alternate formats.\r\n const leadingDigitsRegExp = regExpCache.getPatternForRegExp('^' + alternateFormat.leadingDigitsPatterns()[0])\r\n if (!leadingDigitsRegExp.test(nationalSignificantNumber)) {\r\n // Leading digits don't match; try another one.\r\n continue\r\n }\r\n }\r\n formattedNumberGroups = getNationalNumberGroups(metadata, number, alternateFormat)\r\n if (checkGroups(metadata, number, normalizedCandidate, formattedNumberGroups)) {\r\n return true\r\n }\r\n }\r\n }\r\n\r\n return false\r\n}\r\n\r\n/**\r\n * Helper method to get the national-number part of a number, formatted without any national\r\n * prefix, and return it as a set of digit blocks that would be formatted together following\r\n * standard formatting rules.\r\n */\r\nfunction getNationalNumberGroups(\r\n\tmetadata,\r\n\tnumber,\r\n\tformattingPattern\r\n) {\r\n if (formattingPattern) {\r\n // We format the NSN only, and split that according to the separator.\r\n const nationalSignificantNumber = util.getNationalSignificantNumber(number)\r\n return util.formatNsnUsingPattern(nationalSignificantNumber,\r\n formattingPattern, 'RFC3966', metadata).split('-')\r\n\t}\r\n\r\n // This will be in the format +CC-DG1-DG2-DGX;ext=EXT where DG1..DGX represents groups of digits.\r\n const rfc3966Format = formatNumber(number, 'RFC3966', metadata)\r\n\r\n // We remove the extension part from the formatted string before splitting it into different\r\n // groups.\r\n let endIndex = rfc3966Format.indexOf(';')\r\n if (endIndex < 0) {\r\n endIndex = rfc3966Format.length\r\n }\r\n\r\n // The country-code will have a '-' following it.\r\n const startIndex = rfc3966Format.indexOf('-') + 1\r\n return rfc3966Format.slice(startIndex, endIndex).split('-')\r\n}\r\n\r\nfunction allNumberGroupsAreExactlyPresent\r\n(\r\n\tmetadata,\r\n\tnumber,\r\n\tnormalizedCandidate,\r\n\tformattedNumberGroups\r\n)\r\n{\r\n const candidateGroups = normalizedCandidate.split(NON_DIGITS_PATTERN)\r\n\r\n // Set this to the last group, skipping it if the number has an extension.\r\n let candidateNumberGroupIndex =\r\n number.hasExtension() ? candidateGroups.length - 2 : candidateGroups.length - 1\r\n\r\n // First we check if the national significant number is formatted as a block.\r\n // We use contains and not equals, since the national significant number may be present with\r\n // a prefix such as a national number prefix, or the country code itself.\r\n if (candidateGroups.length == 1\r\n || candidateGroups[candidateNumberGroupIndex].contains(\r\n util.getNationalSignificantNumber(number)))\r\n {\r\n return true\r\n }\r\n\r\n // Starting from the end, go through in reverse, excluding the first group, and check the\r\n // candidate and number groups are the same.\r\n let formattedNumberGroupIndex = (formattedNumberGroups.length - 1)\r\n while (formattedNumberGroupIndex > 0 && candidateNumberGroupIndex >= 0)\r\n {\r\n if (candidateGroups[candidateNumberGroupIndex] !== formattedNumberGroups[formattedNumberGroupIndex])\r\n {\r\n return false\r\n }\r\n formattedNumberGroupIndex--\r\n candidateNumberGroupIndex--\r\n }\r\n\r\n // Now check the first group. There may be a national prefix at the start, so we only check\r\n // that the candidate group ends with the formatted number group.\r\n return (candidateNumberGroupIndex >= 0\r\n && endsWith(candidateGroups[candidateNumberGroupIndex], formattedNumberGroups[0]))\r\n}\r\n\r\n\r\nfunction allNumberGroupsRemainGrouped\r\n(\r\n\tmetadata,\r\n\tnumber,\r\n\tnormalizedCandidate,\r\n\tformattedNumberGroups\r\n)\r\n{\r\n let fromIndex = 0\r\n if (number.getCountryCodeSource() !== CountryCodeSource.FROM_DEFAULT_COUNTRY)\r\n {\r\n // First skip the country code if the normalized candidate contained it.\r\n const countryCode = String(number.getCountryCode())\r\n fromIndex = normalizedCandidate.indexOf(countryCode) + countryCode.length()\r\n }\r\n\r\n // Check each group of consecutive digits are not broken into separate groupings in the\r\n // {@code normalizedCandidate} string.\r\n for (let i = 0; i < formattedNumberGroups.length; i++)\r\n {\r\n // Fails if the substring of {@code normalizedCandidate} starting from {@code fromIndex}\r\n // doesn't contain the consecutive digits in formattedNumberGroups[i].\r\n fromIndex = normalizedCandidate.indexOf(formattedNumberGroups[i], fromIndex)\r\n if (fromIndex < 0) {\r\n return false\r\n }\r\n // Moves {@code fromIndex} forward.\r\n fromIndex += formattedNumberGroups[i].length()\r\n if (i == 0 && fromIndex < normalizedCandidate.length())\r\n {\r\n // We are at the position right after the NDC. We get the region used for formatting\r\n // information based on the country code in the phone number, rather than the number itself,\r\n // as we do not need to distinguish between different countries with the same country\r\n // calling code and this is faster.\r\n const region = util.getRegionCodeForCountryCode(number.getCountryCode())\r\n if (util.getNddPrefixForRegion(region, true) != null\r\n && Character.isDigit(normalizedCandidate.charAt(fromIndex))) {\r\n // This means there is no formatting symbol after the NDC. In this case, we only\r\n // accept the number if there is no formatting symbol at all in the number, except\r\n // for extensions. This is only important for countries with national prefixes.\r\n const nationalSignificantNumber = util.getNationalSignificantNumber(number)\r\n return startsWith\r\n (\r\n \t normalizedCandidate.slice(fromIndex - formattedNumberGroups[i].length),\r\n nationalSignificantNumber\r\n )\r\n }\r\n }\r\n }\r\n\r\n // The check here makes sure that we haven't mistakenly already used the extension to\r\n // match the last group of the subscriber number. Note the extension cannot have\r\n // formatting in-between digits.\r\n return normalizedCandidate.slice(fromIndex).contains(number.getExtension())\r\n}"],"file":"Leniency.js"}