Security News
TC39 Advances 10+ ECMAScript Proposals: Key Features to Watch
TC39 is meeting in Tokyo this week and they have approved nearly a dozen proposals to advance to the next stages.
libphonenumber-js
Advanced tools
A simpler (and smaller) rewrite of Google Android's popular libphonenumber library
The libphonenumber-js npm package is a JavaScript library that provides a variety of functions for handling and manipulating phone numbers. It is based on Google's libphonenumber library and allows users to parse, format, and validate phone numbers in international formats.
Parsing and formatting phone numbers
This feature allows users to parse a string into a phone number object and format it into an international format.
import { parsePhoneNumberFromString } from 'libphonenumber-js';
const phoneNumber = parsePhoneNumberFromString('+12133734253');
console.log(phoneNumber.formatInternational()); // '+1 213 373 4253'
Validating phone numbers
This feature enables users to check if a given phone number is valid according to international standards.
import { isValidPhoneNumber } from 'libphonenumber-js';
const valid = isValidPhoneNumber('+12133734253');
console.log(valid); // true
Getting phone number information
This feature provides information about the phone number, such as the country it is associated with and the type of number (e.g., mobile, fixed-line).
import { parsePhoneNumberFromString } from 'libphonenumber-js';
const phoneNumber = parsePhoneNumberFromString('+12133734253');
console.log(phoneNumber.country); // 'US'
console.log(phoneNumber.getType()); // 'MOBILE'
This is the original phone number handling library from Google that libphonenumber-js is based on. It is more feature-rich but also larger in size, which might not be ideal for front-end usage due to its impact on bundle size.
Another library for phone number parsing, validation, and formatting. It provides similar functionalities to libphonenumber-js but with a different API design and potentially different bundle size implications.
[![NPM Version][npm-badge]][npm] [![Build Status][travis-badge]][travis] [![Test Coverage][coveralls-badge]][coveralls]
A simpler (and smaller) rewrite of Google Android's famous libphonenumber
library: easy phone number parsing and formatting in javascript.
libphonenumber
is a phone number formatting and parsing library released by Google, originally developed for (and currently used in) Google's Android mobile phone operating system. Implementing a rigorous phone number formatting and parsing library was crucial for the phone OS overall usability (back then, in the early 2000s, it was originally meant to be a phone after all, not just a SnapChat device).
libphonenumber-js
is a simplified pure javascript port of the original libphonenumber
library (written in C++ and Java because those are the programming languages used in Android OS). While libphonenumber
has an official javascript port which is being maintained by Google, it is tightly coupled to Google's closure
javascript utility framework. It still can be compiled into one big bundle which weighs 220 KiloBytes — quite a size for a phone number input component. It can be reduced to a specific set of countries only but that wouldn't be an option for a worldwide international solution.
One part of me was curious about how all this phone matching machinery worked, and another part of me was curious if there's a way to reduce those 220 KiloBytes to something more reasonable while also getting rid of the closure
library and rewriting it all in pure javascript. So, that was my little hackathon for a couple of weeks, and seems that it succeeded. The resulting library does everything a modern web application needs while maintaining a much smaller size of about 75 KiloBytes.
libphonenumber
libphonenumber
metadata size is about 200 KiloBytes1-800-GOT-MILK
as we don't use telephone sets in the XXIst century that much (and we have phonebooks in your mobile phones)format
ted are internationally diallable, because that's the only type of phone numbers users are supposed to be inputting on websites (no one inputs short codes, emergency telephone numbers like 911
, etc.)possibleDigits
data to speed up phone number pre-validation (it just skips to the regular expression check itself)011 ...
in the US (again, just use the +...
notation accepted worldwide for mobile phones)tel:...
URIs (RFC 3966) because it's not relevant for user-facing web experiencenpm install libphonenumber-js --save
import { parse, format, asYouType } from 'libphonenumber-js'
parse('8 (800) 555 35 35', 'RU')
// { country: 'RU', phone: '8005553535' }
format('2133734253', 'US', 'International')
// '+1-213-373-4253'
new asYouType().input('+12133734')
// '+1 213 373 4'
new asYouType('US').input('2133734')
// '(213) 373-4'
"Country code" means either a two-letter ISO country code (like US
) or a special 001
country code used for non-geographical entities (as per Google's libphonenumber library). For example, +7 800 555 35 35
phone number belongs to Russia so it has RU
country code where as +800 1 1111 1111
phone number could belong to any country so it has 001
country code.
options
can be either an object
country:
{
restrict — (country code)
the phone number must be in this country
default — (country code)
default country to use for phone number parsing and validation
(if no country code could be derived from the phone number)
}
or just a country code which is gonna be country.restrict
.
Returns { country, phone }
where
country
is a country codephone
is a national (significant) numberIf the phone number supplied isn't valid then an empty object {}
is returned.
parse('+1-213-373-4253') === { country: 'US', phone: '2133734253' }
parse('(213) 373-4253', 'US') === { country: 'US', phone: '2133734253' }
Formats a phone number using one of the following format
s:
International
— e.g. +1 213 373 4253
International_plaintext
— (aka E.164
) e.g. +12133734253
National
— e.g. (213) 373-4253
parsed_number
argument should be taken from the result of the parse()
function call: { country, phone }
. phone
must be a national (significant) number (i.e. no national prefix). parsed_number
argument can also be expanded into two arguments:
format({ country: 'US', phone: '2133734253' }, 'International') === '+1 213 373 4253'
format('2133734253', 'US', 'International') === '+1 213 373 4253'
(aka is_valid_number
)
Checks if a phone number is valid.
The arguments can be
parse()
function call: { country, phone }
(phone, country_code)
which will then be simply passed to the parse()
function for parsingisValidNumber('+1-213-373-4253') === true
isValidNumber('+1-213-373') === false
isValidNumber('(213) 373-4253', 'US') === true
isValidNumber('(213) 37', 'US') === false
isValidNumber({ phone: '2133734253', country: 'US' }) === true
The difference between using parse()
and isValidNumber()
for phone number validation is that isValidNumber()
also checks the precise regular expressions of possible phone numbers for a country. For example, for Germany parse('123456', 'DE')
would return { country: 'DE', phone: '123456' }
because this phone number matches the general phone number rules for Germany. But, if the metadata is compiled with --extended
flag (see below) and the precise regular expressions for possible phone numbers are included in the metadata then isValidNumber()
is gonna use those precise regular expressions for validation and isValid('123456', 'DE')
will return false
because the phone number 123456
doesn't actually exist in Germany.
So, the general phone number rules for a country are mainly for phone number formatting: they dictate how different phone numbers (matching those general regular expressions) should be formatted. And parse()
uses only those general regular expressions (as per the reference Google's libphonenumber
implementation) to perform basic phone number validation. isValidNumber()
, on the other hand, is all about validation, so it digs deeper into precise regular expressions (if they're included in metadata) for possible phone numbers in a given country. And that's the difference between them: parse()
parses phone numbers and loosely validates them while isValidNumber()
validates phone number precisely (provided the precise regular expressions are included in metadata).
By default those precise regular expressions aren't included in metadata at all because that would cause metadata to grow twice in its size (the complete metadata would be about 200 KiloBytes). If anyone needs to generate custom metadata then it's very easy to do so: just follow the instructions provided in the Customizing metadata section of this document (the option to look for is --extended
).
class
asYouType(default_country_code)(aka as_you_type
)
Creates a formatter for partially entered phone number. The two-letter default_country_code
is optional and, if specified, is gonna be the default country for the phone number being input (in case it's not an international one). The instance of this class has two methods:
input(text)
— takes any text and appends it to the input; returns the formatted phone numberreset()
— resets the inputThe instance of this class has also these fields:
valid
— is the phone number being input a valid one alreadycountry
— a country code of the country this phone belongs tocountry_phone_code
— a phone code of the country
national_number
— national number part (so far)template
— currently used phone number formatting template, where digits (and the plus sign, if present) are denoted by x
-esnew asYouType().input('+12133734') === '+1 213 373 4'
new asYouType('US').input('2133734') === '(213) 373-4'
const formatter = new asYouType()
formatter.input('+1-213-373-4253') === '+1 213 373 4253'
formatter.valid === true
formatter.country === 'US'
formatter.country_phone_code = '1'
formatter.template === 'xx xxx xxx xxxx'
Metadata is generated from Google's original PhoneNumberMetadata.xml
by transforming XML into JSON and removing unnecessary fields.
Currently I have an npm script for monitoring changes to PhoneNumberMetadata.xml
in Google's repo and automatically creating a Pull Request in this repo with the fresh metadata when it is updated. What's left is to test this script and schedule it to run daily on my machine. So this project's metadata is supposed to be up-to-date. Still, in case the automatic metadata update script malfunctions some day, anyone can request metadata update via a Pull Request here on GitHub:
npm install
npm run metadata:update
update-metadata
branch of your forknpm run metadata:update
command creates a new update-metadata
branch, downloads the new PhoneNumberMetadata.xml
into the project folder replacing the old one, generates JSON metadata out of the XML one, checks if the metadata has changed, runs the tests, commits the new metadata and pushes the commit to the remote update-metadata
branch of your fork.
Alternatively, a developer may wish to update metadata urgently, without waiting for a pull request approval. In this case just perform the steps described in the Customizing metadata section of this document.
There's also a React component utilizing this library: react-phone-number-input
If you spot any inconsistencies with the original Google's libphonenumber
then create an issue in this repo.
If you're using Webpack (which you most likely are) then make sure that
json-loader
set up for *.json
files in Webpack configurationjson-loader
doesn't exclude
/node_modules/
resolve.extensions
in Webpack configuration then make sure .json
extension is present in the listFor those who aren't using bundlers for some reason there's a way to build a standalone version of the library
git clone https://github.com/halt-hammerzeit/libphonenumber-js.git
npm install
npm run browser-build
bundle
folder for libphonenumber-js.min.js
<script src="/scripts/libphonenumber-js.min.js"></script>
<script>
var libphonenumber = window['libphonenumber-js']
alert(new libphonenumber.asYouType('US').input('213-373-4253'))
</script>
If only a specific set of countries is needed in a project, and a developer really wants to reduce the resulting bundle size, say, by 50 KiloBytes, then he can generate custom metadata and pass it as an extra argument to this library's functions. Or, say, if a developer wants to use the complete metadata (which is about 200 KiloBytes) for precise phone number validation then he can also generate such complete metadata set.
First, add metadata generation script to your project's package.json
{
"scripts": {
"libphonenumber-metadata": "libphonenumber-generate-metadata metadata.min.json --countries RU,DE --extended",
}
}
And then run it like npm run libphonenumber-metadata
.
The first argument is the output metadata file path. --countries
argument is a comma-separated list of the required countries (if --countries
is omitted then all countries are included). --extended
argument may be passed to increase the precision of phone number validation but at the same time it will enlarge the resulting metadata size approximately twice.
Then use the generated metadata.min.json
with the libphonenumber-js/custom
functions
import { parse, format, isValidNumber, asYouType } from 'libphonenumber-js/custom'
import metadata from './metadata.min.json'
const parseCustomCountries = parse.bind({ metadata })
const formatCustomCountries = format.bind({ metadata })
const isValidNumberCustomCountries = isValidNumber.bind({ metadata })
const asYouTypeCustomCountries = asYouType(metadata)
For utilizing "tree-shaking" in ES6-capable bundlers (e.g. Webpack 2) libphonenumber-js/custom.es6
may be used instead.
metadata:update
and metadata:pull-request
scripts work as intended and add a daily launchd
job for npm run metadata:update && npm run metadata:pull-request
After cloning this repo, ensure dependencies are installed by running:
npm install
This module is written in ES6 and uses Babel for ES5 transpilation. Widely consumable JavaScript can be produced by running:
npm run build
Once npm run build
has run, you may import
or require()
directly from
node.
After developing, the full test suite can be evaluated by running:
npm test
When you're ready to test your new functionality on a real project, you can run
npm pack
It will build
, test
and then create a .tgz
archive which you can then install in your project folder
npm install [module name with version].tar.gz
MIT [npm]: https://www.npmjs.org/package/libphonenumber-js [npm-badge]: https://img.shields.io/npm/v/libphonenumber-js.svg?style=flat-square [travis]: https://travis-ci.org/halt-hammerzeit/libphonenumber-js [travis-badge]: https://img.shields.io/travis/halt-hammerzeit/libphonenumber-js/master.svg?style=flat-square [coveralls]: https://coveralls.io/r/halt-hammerzeit/libphonenumber-js?branch=master [coveralls-badge]: https://img.shields.io/coveralls/halt-hammerzeit/libphonenumber-js/master.svg?style=flat-square
FAQs
A simpler (and smaller) rewrite of Google Android's libphonenumber library in javascript
The npm package libphonenumber-js receives a total of 5,513,862 weekly downloads. As such, libphonenumber-js popularity was classified as popular.
We found that libphonenumber-js demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
TC39 is meeting in Tokyo this week and they have approved nearly a dozen proposals to advance to the next stages.
Security News
Our threat research team breaks down two malicious npm packages designed to exploit developer trust, steal your data, and destroy data on your machine.
Security News
A senior white house official is urging insurers to stop covering ransomware payments, indicating possible stricter regulations to deter cybercrime.