libphonenumber-js
Version:
A simpler (and smaller) rewrite of Google Android's libphonenumber library in javascript
103 lines (85 loc) • 3.45 kB
JavaScript
// When phone numbers are written in `RFC3966` format — `"tel:+12133734253"` —
// they can have their "calling code" part written separately in a `phone-context` parameter.
// Example: `"tel:12133734253;phone-context=+1"`.
// This function parses the full phone number from the local number and the `phone-context`
// when the `phone-context` contains a `+` sign.
import {
VALID_DIGITS,
// PLUS_CHARS
} from '../constants.js'
export const PLUS_SIGN = '+'
const RFC3966_VISUAL_SEPARATOR_ = '[\\-\\.\\(\\)]?'
const RFC3966_PHONE_DIGIT_ = '(' + '[' + VALID_DIGITS + ']' + '|' + RFC3966_VISUAL_SEPARATOR_ + ')'
const RFC3966_GLOBAL_NUMBER_DIGITS_ =
'^' +
'\\' +
PLUS_SIGN +
RFC3966_PHONE_DIGIT_ +
'*' +
'[' + VALID_DIGITS + ']' +
RFC3966_PHONE_DIGIT_ +
'*' +
'$'
/**
* Regular expression of valid global-number-digits for the phone-context
* parameter, following the syntax defined in RFC3966.
*/
const RFC3966_GLOBAL_NUMBER_DIGITS_PATTERN_ = new RegExp(RFC3966_GLOBAL_NUMBER_DIGITS_, 'g')
// In this port of Google's library, we don't accept alpha characters in phone numbers.
// const ALPHANUM_ = VALID_ALPHA_ + VALID_DIGITS
const ALPHANUM_ = VALID_DIGITS
const RFC3966_DOMAINLABEL_ = '[' + ALPHANUM_ + ']+((\\-)*[' + ALPHANUM_ + '])*'
const VALID_ALPHA_ = 'a-zA-Z'
const RFC3966_TOPLABEL_ = '[' + VALID_ALPHA_ + ']+((\\-)*[' + ALPHANUM_ + '])*'
const RFC3966_DOMAINNAME_ = '^(' + RFC3966_DOMAINLABEL_ + '\\.)*' + RFC3966_TOPLABEL_ + '\\.?$'
/**
* Regular expression of valid domainname for the phone-context parameter,
* following the syntax defined in RFC3966.
*/
const RFC3966_DOMAINNAME_PATTERN_ = new RegExp(RFC3966_DOMAINNAME_, 'g')
export const RFC3966_PREFIX_ = 'tel:'
export const RFC3966_PHONE_CONTEXT_ = ';phone-context='
export const RFC3966_ISDN_SUBADDRESS_ = ';isub='
/**
* Extracts the value of the phone-context parameter of `numberToExtractFrom`,
* following the syntax defined in RFC3966.
*
* @param {string} numberToExtractFrom
* @return {string|null} the extracted string (possibly empty), or `null` if no phone-context parameter is found.
*/
export default function extractPhoneContext(numberToExtractFrom) {
const indexOfPhoneContext = numberToExtractFrom.indexOf(RFC3966_PHONE_CONTEXT_)
// If no phone-context parameter is present
if (indexOfPhoneContext < 0) {
return null
}
const phoneContextStart = indexOfPhoneContext + RFC3966_PHONE_CONTEXT_.length
// If phone-context parameter is empty
if (phoneContextStart >= numberToExtractFrom.length) {
return ''
}
const phoneContextEnd = numberToExtractFrom.indexOf(';', phoneContextStart)
// If phone-context is not the last parameter
if (phoneContextEnd >= 0) {
return numberToExtractFrom.substring(phoneContextStart, phoneContextEnd)
} else {
return numberToExtractFrom.substring(phoneContextStart)
}
}
/**
* Returns whether the value of phoneContext follows the syntax defined in RFC3966.
*
* @param {string|null} phoneContext
* @return {boolean}
*/
export function isPhoneContextValid(phoneContext) {
if (phoneContext === null) {
return true
}
if (phoneContext.length === 0) {
return false
}
// Does phone-context value match pattern of global-number-digits or domainname.
return RFC3966_GLOBAL_NUMBER_DIGITS_PATTERN_.test(phoneContext) ||
RFC3966_DOMAINNAME_PATTERN_.test(phoneContext)
}