1 | # libphonenumber-js
|
2 |
|
3 | [![npm version](https://img.shields.io/npm/v/libphonenumber-js.svg?style=flat-square)](https://www.npmjs.com/package/libphonenumber-js)
|
4 | [![npm downloads](https://img.shields.io/npm/dm/libphonenumber-js.svg?style=flat-square)](https://www.npmjs.com/package/libphonenumber-js)
|
5 | [![coverage](https://img.shields.io/coveralls/catamphetamine/libphonenumber-js/master.svg?style=flat-square)](https://coveralls.io/r/catamphetamine/libphonenumber-js?branch=master)
|
6 |
|
7 | A simpler and smaller rewrite of Google Android's [`libphonenumber`](https://github.com/google/libphonenumber/blob/master/java/libphonenumber/) library in javascript.
|
8 |
|
9 | [See Demo](https://catamphetamine.gitlab.io/libphonenumber-js/)
|
10 |
|
11 | If you’re trying to build a React component with it, take a look at [`react-phone-number-input`](https://www.npmjs.com/package/react-phone-number-input).
|
12 |
|
13 | ## LibPhoneNumber
|
14 |
|
15 | Google's [`libphonenumber`](https://github.com/googlei18n/libphonenumber) is an ultimate phone number formatting and parsing library developed by Google for [Android](https://en.wikipedia.org/wiki/Android_(operating_system)) phones. It is written in C++ and Java, and, while it has an [official autogenerated javascript port](https://github.com/googlei18n/libphonenumber/tree/master/javascript), that port is tightly coupled to Google's `closure` javascript framework, and, when compiled into a [bundle](https://github.com/ruimarinho/google-libphonenumber), weighs about 550 kB (350 kB code + 200 kB metadata).
|
16 |
|
17 | With many websites today asking for user's phone number, the internet could benefit from a simpler and smaller library that would just get the parsing and formatting right, and that's what `libphonenumber-js` is.
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | One part of me was curious about how all this phone number parsing and formatting machinery worked, and another part of me was curious if there was a way to reduce those 530 kilobytes to something more reasonable while also getting rid of all the unnecessary bulk and rewriting it all in pure javascript. The resulting library does everything a modern web application needs while maintaining a much smaller size of about 130 kilobytes.
|
23 | -->
|
24 |
|
25 | ## Difference from Google's `libphonenumber`
|
26 |
|
27 | * Smaller footprint: 145 kB (65 kB code + 80 kB sufficient metadata) vs the original Google's 550 kB (350 kB code + 200 kB full metadata).
|
28 |
|
29 | * Can search for phone numbers in text (Google's autogenerated javascript port can't).
|
30 |
|
31 | * Doesn't parse or format special "local"-only phone numbers: numbers specific to a "local" area (for example, a city) with the "area code" omitted (like `456-789` with the "area code" `(123)` omitted vs. the full `(123) 456-789` number), emergency phone numbers like `911`, ["short codes"](https://support.twilio.com/hc/en-us/articles/223182068-What-is-a-short-code-) (short SMS-only numbers), numbers starting with a [`*`](https://github.com/googlei18n/libphonenumber/blob/master/FALSEHOODS.md) (like `*555`), etc. The aim of this library is parsing and formatting people's phone numbers.
|
32 |
|
33 | * Doesn't provide an equivalent of `formatNumberForMobileDialing()` function that returns a number formatted in such a way that it can be dialed from a mobile phone within a specific country. For example, it adds ["carrier codes"](https://www.bandwidth.com/glossary/carrier-identification-code-cic/) when dialing within certain countries (Brazil, Colombia). Since this is not a dialing library, it doesn't provide such a function and doesn't use "carrier codes" when formatting phone numbers.
|
34 |
|
35 |
|
36 |
|
37 | |
38 | for (var code of Object.keys(metadata.countries)) {
|
39 | var country = metadata.countries[code]
|
40 | if (country.formats && country.formats.find(_ => _.domestic_carrier_code_formatting_rule)) {
|
41 | console.log(code)
|
42 | }
|
43 | }
|
44 | -->
|
45 |
|
46 | * Doesn't parse alphabetic phone numbers like `1-800-GOT-MILK`: people don't input their phone numbers in this format, it's only used in advertisement.
|
47 |
|
48 | * Doesn't parse "combined" extensions into two separate numbers (example: `(530) 583-6985 x302/x2303`): people don't input their phone numbers in this format.
|
49 |
|
50 | * Doesn't use hyphens and brackets when formatting international phone numbers, only whitespace: seems more logical this way.
|
51 |
|
52 | * Doesn't use the `"001"` country code for ["non-geographic"](#non-geographic) phone numbers. Instead, `PhoneNumber` class has an `.isNonGeographic()` method.
|
53 |
|
54 | |
55 | * Doesn't use ["carrier codes"](https://github.com/googlei18n/libphonenumber/blob/master/FALSEHOODS.md) when formatting numbers: "carrier codes" are only used in Colombia and Brazil and only when dialing within those countries from a mobile phone to a fixed line number.
|
56 | (`.formatNumberForMobileDialing()` method is not implemented therefore there's no need to format carrier codes)
|
57 | -->
|
58 |
|
59 | ## GitHub
|
60 |
|
61 | On March 9th, 2020, GitHub, Inc. silently [banned](https://medium.com/@catamphetamine/how-github-blocked-me-and-all-my-libraries-c32c61f061d3) my account (erasing all my repos, issues and comments) without any notice or explanation. Because of that, all source codes had to be promptly moved to GitLab. The [GitHub repo](https://github.com/catamphetamine/libphonenumber-js) is now only used as a backup (you can star the repo there too), and the primary repo is now the [GitLab one](https://gitlab.com/catamphetamine/libphonenumber-js). Issues can be reported in any repo.
|
62 |
|
63 | ## Install
|
64 |
|
65 | via [npm](https://npmjs.org/)
|
66 |
|
67 | ```sh
|
68 | $ npm install libphonenumber-js --save
|
69 | ```
|
70 |
|
71 | via [yarn](https://yarnpkg.com)
|
72 |
|
73 | ```sh
|
74 | $ yarn add libphonenumber-js
|
75 | ```
|
76 |
|
77 | If you're not using a bundler then use a [standalone version from a CDN](https://gitlab.com/catamphetamine/libphonenumber-js/#cdn).
|
78 |
|
79 | ## Use
|
80 |
|
81 | ### Parse phone number
|
82 |
|
83 |
|
84 | _(new API)_
|
85 | -->
|
86 |
|
87 | ```js
|
88 | import parsePhoneNumber from 'libphonenumber-js'
|
89 |
|
90 | const phoneNumber = parsePhoneNumber('Phone: 8 (800) 555 35 35.', 'RU')
|
91 | if (phoneNumber) {
|
92 | phoneNumber.country === 'RU'
|
93 | phoneNumber.number === '+78005553535'
|
94 | phoneNumber.isValid() === true
|
95 | // Note: `.getType()` requires `/max` metadata: see below for an explanation.
|
96 | phoneNumber.getType() === 'TOLL_FREE'
|
97 | }
|
98 | ```
|
99 |
|
100 |
|
101 | <details>
|
102 | <summary>Legacy API</summary>
|
103 |
|
104 | ```js
|
105 | import { parseNumber } from 'libphonenumber-js'
|
106 |
|
107 | parseNumber('Phone: 8 (800) 555 35 35.', 'RU')
|
108 | // Outputs: { country: 'RU', phone: '8005553535' }
|
109 | ```
|
110 | </details>
|
111 | -->
|
112 |
|
113 | ### Format phone number
|
114 |
|
115 |
|
116 | _(new API)_
|
117 | -->
|
118 |
|
119 | ```js
|
120 | import parsePhoneNumber from 'libphonenumber-js'
|
121 |
|
122 | const phoneNumber = parsePhoneNumber('+12133734253')
|
123 |
|
124 | phoneNumber.formatInternational() === '+1 213 373 4253'
|
125 | phoneNumber.formatNational() === '(213) 373-4253'
|
126 | phoneNumber.getURI() === 'tel:+12133734253'
|
127 | ```
|
128 |
|
129 |
|
130 | <details>
|
131 | <summary>Legacy API</summary>
|
132 |
|
133 | ```js
|
134 | import { formatNumber } from 'libphonenumber-js'
|
135 |
|
136 | formatNumber('+12133734253', 'INTERNATIONAL')
|
137 | // Outputs: '+1 213 373 4253'
|
138 |
|
139 | formatNumber('+12133734253', 'NATIONAL')
|
140 | // Outputs: '(213) 373-4253'
|
141 |
|
142 | formatNumber({ country: 'US', phone: '2133734253' }, 'INTERNATIONAL')
|
143 | // Outputs: '+1 213 373 4253'
|
144 |
|
145 | formatNumber({ country: 'US', phone: '2133734253' }, 'NATIONAL')
|
146 | // Outputs: '(213) 373-4253'
|
147 | ```
|
148 | </details>
|
149 | -->
|
150 |
|
151 | ### "As You Type" formatter
|
152 |
|
153 | ```js
|
154 | import { AsYouType } from 'libphonenumber-js'
|
155 |
|
156 | new AsYouType().input('+12133734')
|
157 | // Outputs: '+1 213 373 4'
|
158 |
|
159 | new AsYouType('US').input('2133734')
|
160 | // Outputs: '(213) 373-4'
|
161 | ```
|
162 |
|
163 | ### Full-text search
|
164 |
|
165 |
|
166 | _(new API)_
|
167 | -->
|
168 |
|
169 | ```js
|
170 | import { findPhoneNumbersInText } from 'libphonenumber-js'
|
171 |
|
172 | findPhoneNumbersInText(`
|
173 | For tech support call +7 (800) 555-35-35 internationally
|
174 | or reach a local US branch at (213) 373-4253 ext. 1234.
|
175 | `, 'US')
|
176 |
|
177 | // Outputs:
|
178 | //
|
179 | // [{
|
180 | // number: PhoneNumber {
|
181 | // country: 'RU',
|
182 | // countryCallingCode: '7',
|
183 | // number: '+78005553535',
|
184 | // nationalNumber: '8005553535'
|
185 | // },
|
186 | // startsAt : 22,
|
187 | // endsAt : 40
|
188 | // }, {
|
189 | // number: PhoneNumber {
|
190 | // country: 'US',
|
191 | // countryCallingCode: '1',
|
192 | // number: '+12133734253',
|
193 | // nationalNumber: '2133734253',
|
194 | // ext: '1234'
|
195 | // },
|
196 | // startsAt : 86,
|
197 | // endsAt : 110
|
198 | // }]
|
199 | ```
|
200 |
|
201 | ## "min" vs "max" vs "mobile" vs "core"
|
202 |
|
203 | This library provides different "metadata" sets, "metadata" being a list of phone number parsing and formatting rules for all countries. The complete list of those rules is huge, so this library provides a way to optimize bundle size by choosing between `max`, `min`, `mobile` and "custom" metadata:
|
204 |
|
205 | * `max` — The complete metadata set, is about `145 kilobytes` in size (`libphonenumber-js/metadata.full.json`). Choose this when you need the most strict version of `isValid()`, or if you need to detect phone number type ("fixed line", "mobile", etc).
|
206 |
|
207 | * `min` — (default) The smallest metadata set, is about `80 kilobytes` in size (`libphonenumber-js/metadata.min.json`). Choose this by default: when you don't need to detect phone number type ("fixed line", "mobile", etc), or when a basic version of `isValid()` is enough. The `min` metadata set doesn't contain the regular expressions for phone number digits validation (via [`.isValid()`](#isvalid)) and detecting phone number type (via [`.getType()`](#gettype)) for most countries. In this case, `.isValid()` still performs some basic phone number validation (for example, checks phone number length), but it doesn't validate phone number digits themselves the way `max` metadata validation does.
|
208 |
|
209 | * `mobile` — The complete metadata set for dealing with mobile numbers _only_, is about `95 kilobytes` in size (`libphonenumber-js/metadata.mobile.json`). Choose this when you need `max` metadata and when you _only_ accept mobile numbers. Other phone number types will still be parseable, but they won't be recognized as being "valid" (`.isValid()` will return `false`).
|
210 |
|
211 | To use a particular metadata set, simply import functions from a relevant sub-package:
|
212 |
|
213 | * `libphonenumber-js/max`
|
214 | * `libphonenumber-js/min`
|
215 | * `libphonenumber-js/mobile`
|
216 |
|
217 | Importing functions directly from `libphonenumber-js` effectively results in using the `min` metadata.
|
218 |
|
219 | Sometimes (rarely) not all countries are needed, and in those cases developers may want to [generate](#customizing-metadata) their own "custom" metadata set. For those cases, there's `libphonenumber-js/core` sub-package which doesn't come pre-packaged with any default metadata set and instead accepts metadata as the last argument of each exported function.
|
220 |
|
221 | ## Definitions
|
222 |
|
223 | ### Country code
|
224 |
|
225 | "Country code" means either a [two-letter ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) (like `US`).
|
226 |
|
227 | ### Non-geographic
|
228 |
|
229 | There're several calling codes that don't belong to any country:
|
230 |
|
231 | * `+800` — [Universal International Toll Free Number](https://en.wikipedia.org/wiki/Toll-free_telephone_number)
|
232 | * `+808` — [Universal International Shared Cost Number](https://en.wikipedia.org/wiki/Shared-cost_service)
|
233 | * `+870` — [Inmarsat Global Limited](https://en.wikipedia.org/wiki/Inmarsat)
|
234 | * `+878` — [Universal Personal Telecommunications](https://en.wikipedia.org/wiki/Universal_Personal_Telecommunications)
|
235 | * `+881` — [Global Mobile Satellite System](https://en.wikipedia.org/wiki/Global_Mobile_Satellite_System)
|
236 | * `+882` and `+883` — [International Networks](https://en.wikipedia.org/wiki/International_Networks_(country_code))
|
237 | * `+888` — [United Nations Office for the Coordination of Humanitarian Affairs](https://en.wikipedia.org/wiki/United_Nations_Office_for_the_Coordination_of_Humanitarian_Affairs#International_Dialing_Code)
|
238 | * `+979` — [International Premium Rate Service](https://en.wikipedia.org/wiki/International_Premium_Rate_Service)
|
239 |
|
240 | Such phone numbering plans are called "non-geographic", and their phone numbers have `country` set to `undefined`.
|
241 |
|
242 | ### National (significant) number
|
243 |
|
244 | "National (significant) number" are the national phone number digits (without "national prefix"). For example, `+1 213 373 4253` (or `(213) 373-4253` in national format) is a US phone number and its national (significant) number is `213 373 4253`. Another example is `+33 1 45 45 32 45` (or `01 45 45 32 45` in national format) which is a [French](https://en.wikipedia.org/wiki/Telephone_numbers_in_France) phone number where they add `0` "national prefix" when writing phone numbers in national format; in this case the national (significant) number is `1 45 45 32 45`.
|
245 |
|
246 | ### Country calling code
|
247 |
|
248 | "Country calling code" are the digits between the `+` and the national (significant) number when the number is written in international format. E.g. for US country calling code is `1` and for France it's `33`. Several countries can share the same "country calling code", e.g. [NANPA](https://en.wikipedia.org/wiki/North_American_Numbering_Plan) countries like USA and Canada sharing the same `1` country calling code.
|
249 |
|
250 | ## API
|
251 |
|
252 | ### parsePhoneNumberFromString(string, [options or defaultCountry]): PhoneNumber
|
253 |
|
254 | Parses a phone number from `string`.
|
255 |
|
256 | Can be imported both as a "default" export and as a "named" export.
|
257 |
|
258 | ```js
|
259 | import parsePhoneNumberFromString from 'libphonenumber-js'
|
260 | // Or: import { parsePhoneNumberFromString } from 'libphonenumber-js'
|
261 |
|
262 | const phoneNumber = parsePhoneNumberFromString('Call: (213) 373-42-53 ext. 1234.', 'US')
|
263 | if (phoneNumber) {
|
264 | console.log(phoneNumber.formatNational())
|
265 | }
|
266 | ```
|
267 |
|
268 | Returns an instance of [`PhoneNumber`](#phonenumber) class, or `undefined` if no phone number could be parsed: for example, when the string contains no phone number, or the phone number starts with a non-existent [country calling code](#country-calling-code), etc.
|
269 |
|
270 | Available `options`:
|
271 |
|
272 | * `defaultCountry` — Default country for parsing national numbers. Instead of passing `options.defaultCountry` one could pass `defaultCountry` argument directly.
|
273 |
|
274 | * `defaultCallingCode` — Default calling code for parsing national numbers. Some numbering plans are for ["non-geographic numbering plans"](#non-geographic) and they don't have a country code, so `defaultCountry` can't be specified for them.
|
275 |
|
276 | If a developer wants to know the exact reason why the phone number couldn't be parsed then they can use `parsePhoneNumberWithError()` function which throws the exact error:
|
277 |
|
278 | ```js
|
279 | import { parsePhoneNumberWithError, ParseError } from 'libphonenumber-js'
|
280 |
|
281 | try {
|
282 | const phoneNumber = parsePhoneNumberWithError('Call: (213) 373-42-53 ext. 1234.', 'US')
|
283 | } catch (error) {
|
284 | if (error instanceof ParseError) {
|
285 | // Not a phone number, non-existent country, etc.
|
286 | console.log(error.message)
|
287 | } else {
|
288 | throw error
|
289 | }
|
290 | }
|
291 | ```
|
292 |
|
293 | <details>
|
294 | <summary>Possible errors</summary>
|
295 |
|
296 | * `INVALID_COUNTRY` — When `defaultCountry` doesn't exist (`parsePhoneNumber('(111) 222-3333', 'XX')`) or isn't supported by this library, or when parsing non-international number without a `defaultCountry` (`parsePhoneNumber('(111) 222-3333')`), or when international number country calling code doesn't exist (`parsePhoneNumber('+9991112223333')`).
|
297 |
|
298 | * `NOT_A_NUMBER` — When no phone number was found. For example, when there are no digits (`"abcde"`) or when there's not enough digits (`parsePhoneNumber('2', 'US')`, `parsePhoneNumber('+1')`).
|
299 |
|
300 | * `TOO_LONG` — When national (significant) number is too long (17 digits max) or when the string being parsed is too long (250 characters max).
|
301 |
|
302 | * `TOO_SHORT` — When national (significant) number is too short (for ex. 1 digit).
|
303 | </details>
|
304 |
|
305 | ### `PhoneNumber`
|
306 |
|
307 |
|
308 | `PhoneNumber` class constructor accepts two arguments: `country`/`countryCallingCode` and `nationalNumber`. Also `metadata`.
|
309 |
|
310 | ```js
|
311 | const phoneNumber = new PhoneNumber('RU', '8005553535', metadata)
|
312 | ```
|
313 | -->
|
314 |
|
315 | `PhoneNumber` class instance has the following properties:
|
316 |
|
317 | * `number: string` — The phone number in [`E.164`](https://en.wikipedia.org/wiki/E.164) format. Example: `"+12133734253"`.
|
318 | * `countryCallingCode: string` — The [country calling code](#country-calling-code). Example: `"1"`.
|
319 | * `nationalNumber: string` — The [national (significant) number](#national-significant-number). Example: `"2133734253"`.
|
320 | * `country: string?` — The [country code](#country-code). Example: `"US"`. Will be `undefined` when no `country` could be derived from the phone number. For example, when several countries have the same `countryCallingCode` and the `nationalNumber` doesn't look like it belongs to any of them. Or when a number belongs to a [non-geographic numbering plan](#non-geographic).
|
321 | * `ext: string?` — The [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)), if any. Example: `"1234"`.
|
322 | * `carrierCode: string?` — The ["carrier code"](https://www.voip-info.org/carrier-identification-codes/), if any. Example: `"15"`. "Carrier codes" are only used in Colombia and Brazil and only when dialing within those countries from a mobile phone to a fixed line number.
|
323 |
|
324 | `PhoneNumber` class instance provides the following methods:
|
325 |
|
326 | #### `format(format: string, [options]): string`
|
327 |
|
328 | Formats the phone number into a string according to a `format`.
|
329 |
|
330 | Available `format`s:
|
331 |
|
332 | * `NATIONAL` — Example: `"(213) 373-4253"`
|
333 | * `INTERNATIONAL` — Example: `"+1 213 373 4253"`
|
334 | * [`E.164`](https://en.wikipedia.org/wiki/E.164) — Example: `"+12133734253"`
|
335 | * [`RFC3966`](https://www.ietf.org/rfc/rfc3966.txt) (the phone number URI) — Example: `"tel:+12133734253;ext=123"`
|
336 | * `IDD` — ["Out-of-country" dialing](https://wikitravel.org/en/International_dialling_prefix) format. Example: `"011 7 800 555 35 35"` for `+7 800 555 35 35` being called out of `options.fromCountry === "US"`. If no `options.fromCountry` was passed or if there's no default IDD prefix for `options.fromCountry` then returns `undefined`.
|
337 |
|
338 | Available `options`:
|
339 |
|
340 | * `formatExtension(number, extension)` — Formats `number` and `extension` into a string. By default returns `${number} ext. ${extension}` for almost all countries with rare exceptions of some special cases like `${number} x${extension}` for UK.
|
341 |
|
342 | * `nationalPrefix: Boolean` — Some phone numbers can be formatted both with national prefix and without it. In such cases the library defaults to "with national prefix" (for legacy reasons). Pass `nationalPrefix: false` option to force formatting without national prefix in such cases.
|
343 |
|
344 | Examples:
|
345 |
|
346 | ```js
|
347 | import parsePhoneNumber from 'libphonenumber-js'
|
348 |
|
349 | const phoneNumber = parsePhoneNumber('+12133734253')
|
350 |
|
351 | phoneNumber.format("NATIONAL") === '(213) 373-4253'
|
352 | phoneNumber.format("INTERNATIONAL") === '+1 213 373 4253'
|
353 | phoneNumber.format("RFC3966") === 'tel:+12133734253'
|
354 |
|
355 | // Aliases
|
356 | phoneNumber.formatNational() === phoneNumber.format("NATIONAL")
|
357 | phoneNumber.formatInternational() === phoneNumber.format("INTERNATIONAL")
|
358 | phoneNumber.getURI() === phoneNumber.format("RFC3966")
|
359 | ```
|
360 |
|
361 | #### `isPossible(): boolean`
|
362 |
|
363 | Checks if the phone number is "possible". Only checks the phone number length, doesn't check the number digits against any regular expressions.
|
364 |
|
365 | #### `isValid(): boolean`
|
366 |
|
367 | Checks if the phone number is "valid". First checks the phone number length and then checks the phone number digits against all available regular expressions.
|
368 |
|
369 | By default the library uses "minimal" metadata which is only 75 kilobytes in size but also doesn't include the precise validation regular expressions resulting in less strict validation rules (some very basic validation like length check is still included for each country). If you don't mind the extra 65 kilobytes of metadata then use ["full" metadata](#min-vs-max-vs-mobile-vs-core) instead (140 kilobytes). Google's library always uses "full" metadata so it will yield different `isValidNumber()` results compared to the "minimal" metadata used by default in this library.
|
370 |
|
371 | <details>
|
372 | <summary>See an example illustrating different results when using <code>/min</code> vs <code>/max</code> vs <code>/mobile</code></summary>
|
373 |
|
374 | ####
|
375 | ```js
|
376 | import parseMin from 'libphonenumber-js/min'
|
377 | import parseMax from 'libphonenumber-js/max'
|
378 | import parseMobile from 'libphonenumber-js/mobile'
|
379 |
|
380 | // Mobile numbers in Singapore starting from `8`
|
381 | // can only have the second digit in the range of `0..8`.
|
382 | // Here the second digit is `9` which makes it an invalid mobile number.
|
383 | // This is a "strict" (advanced) validation rule and is
|
384 | // not included in the (default) "min" bundle.
|
385 |
|
386 | // The basic number length check passes (`8..11`) and the
|
387 | // "loose" national number validation regexp check passes too:
|
388 | // `(?:1\d{3}|[369]|7000|8(?:\d{2})?)\d{7}`.
|
389 | parseMin('+6589555555').isValid() === true
|
390 |
|
391 | // The "advanced" validation regexp for mobile numbers is
|
392 | // `(?:8[1-8]|9[0-8])\\d{6}` and possible lengths are `8`.
|
393 | parseMax('+6589555555').isValid() === false
|
394 | parseMobile('+6589555555').isValid() === false
|
395 | ```
|
396 | </details>
|
397 |
|
398 | ####
|
399 |
|
400 | See also ["Using phone number validation feature"](#using-phone-number-validation-feature) considerations.
|
401 |
|
402 |
|
403 | #### `isValidForRegion(country)`
|
404 |
|
405 | Is just an alias for `this.isValid() && this.country === country`.
|
406 | https://github.com/googlei18n/libphonenumber/blob/master/FAQ.md#when-should-i-use-isvalidnumberforregion
|
407 | -->
|
408 |
|
409 | #### `getType(): string?`
|
410 |
|
411 | Returns phone number type (fixed line, mobile, toll free, etc) or `undefined` (if the number is invalid or if there are no phone number type regular expressions for this country in metadata).
|
412 |
|
413 | By default the library uses "minimal" metadata which is only 75 kilobytes in size but also doesn't include the regular expressions for determining a specific phone number type (fixed line, mobile, toll free, etc) resulting in `getType()` returning `undefined` for most countries. If you don't mind the extra 65 kilobytes of metadata then use ["full" metadata](#min-vs-max-vs-mobile-vs-core) instead (140 kilobytes). Google's library always uses "full" metadata so it will yield different `getNumberType()` results compared to the "minimal" metadata used by default in this library.
|
414 |
|
415 | <details>
|
416 | <summary>The list of possible return values</summary>
|
417 |
|
418 | ####
|
419 |
|
420 | * `MOBILE`
|
421 | * `FIXED_LINE`
|
422 | * `FIXED_LINE_OR_MOBILE`
|
423 | * `PREMIUM_RATE`
|
424 | * `TOLL_FREE`
|
425 | * `SHARED_COST`
|
426 | * `VOIP`
|
427 | * `PERSONAL_NUMBER`
|
428 | * `PAGER`
|
429 | * `UAN`
|
430 | * `VOICEMAIL`
|
431 | </details>
|
432 |
|
433 | ####
|
434 |
|
435 | <details>
|
436 | <summary>See an example illustrating different results when using <code>/min</code> vs <code>/max</code> vs <code>/mobile</code></summary>
|
437 |
|
438 | ####
|
439 | ```js
|
440 | import parseMin from 'libphonenumber-js/min'
|
441 | import parseMax from 'libphonenumber-js/max'
|
442 | import parseMobile from 'libphonenumber-js/mobile'
|
443 |
|
444 | // Singapore valid mobile number.
|
445 |
|
446 | // The (default) "min" bundle doesn't contain any regexps for
|
447 | // getting phone number type based on national number (for Singapore).
|
448 | parseMin('+6584655555').getType() === undefined
|
449 |
|
450 | // The "max" bundle contains regexps for
|
451 | // getting phone number type based on national number
|
452 | // for all possible phone number types.
|
453 | parseMax('+6584655555').getType() === 'MOBILE'
|
454 |
|
455 | // The "mobile" bundle contains regexps for
|
456 | // getting phone number type based on national number
|
457 | // for mobile phone numbers only.
|
458 | parseMobile('+6584655555').getType() === 'MOBILE'
|
459 | ```
|
460 | </details>
|
461 |
|
462 | #### `isNonGeographic(): boolean`
|
463 |
|
464 | Returns `true` if the number belongs to a ["non-geographic numbering plan"](#non-geographic).
|
465 |
|
466 | #### `isEqual(phoneNumber: PhoneNumber): boolean`
|
467 |
|
468 | Compares two `PhoneNumber`s: returns `true` if they're equal, `false` otherwise.
|
469 |
|
470 | ### `class` AsYouType([options or defaultCountry])
|
471 |
|
472 | Creates a formatter for a partially entered phone number.
|
473 |
|
474 | Available `options`:
|
475 |
|
476 | * `defaultCountry` — Default country for parsing national numbers. Instead of passing `options.defaultCountry` one could pass `defaultCountry` argument directly.
|
477 |
|
478 | * `defaultCallingCode` — Default calling code for parsing national numbers. Some numbering plans are for ["non-geographic numbering plans"](#non-geographic) and they don't have a country code, so `defaultCountry` can't be specified for them.
|
479 |
|
480 | The formatter instance has the following methods:
|
481 |
|
482 | * `input(text: string)` — Appends text to the input. Returns the formatted phone number.
|
483 |
|
484 | * `reset()` — Resets the input.
|
485 |
|
486 | ```js
|
487 | new AsYouType().input('+12133734') === '+1 213 373 4'
|
488 | new AsYouType('US').input('2133734') === '(213) 373-4'
|
489 | ```
|
490 |
|
491 | The formatter instance also provides the following getters:
|
492 |
|
493 | * `getNumber(): PhoneNumber` — Returns the [`PhoneNumber`](#phonenumber). Will return `undefined` if no [national (significant) number](#national-significant-number) digits have been entered so far, or if no `defaultCountry`/`defaultCallingCode` has been set and the user enters a phone number not in international format.
|
494 |
|
495 | * `getChars(): string` — Returns the phone number characters entered by the user: digits and a `+` sign (if present). Returns an empty string if no phone number characters have been input.
|
496 |
|
497 | * `getTemplate(): string` — Returns the template used to format the phone number characters (digits and a `+` sign, if present), which are denoted by `x`-es. Returns an empty string if no phone number characters have been input.
|
498 |
|
499 | ```js
|
500 | // National phone number input example.
|
501 |
|
502 | const asYouType = new AsYouType('US')
|
503 |
|
504 | asYouType.input('2') === '2'
|
505 | asYouType.getNumber().number === '+12'
|
506 | asYouType.getChars() === '2'
|
507 | asYouType.getTemplate() === 'x'
|
508 |
|
509 | asYouType.input('1') === '21'
|
510 | asYouType.getNumber().number === '+121'
|
511 | asYouType.getChars() === '21'
|
512 | asYouType.getTemplate() === 'xx'
|
513 |
|
514 | asYouType.input('3') === '(213)'
|
515 | asYouType.getNumber().number === '+1213'
|
516 | asYouType.getChars() === '213'
|
517 | asYouType.getTemplate() === '(xxx)'
|
518 |
|
519 | asYouType.input('3734253') === '(213) 373-4253'
|
520 | asYouType.getNumber().number === '+12133734253'
|
521 | asYouType.getChars() === '2133734253'
|
522 | asYouType.getTemplate() === '(xxx) xxx-xxxx'
|
523 |
|
524 | // International phone number input example.
|
525 |
|
526 | const asYouType = new AsYouType()
|
527 | asYouType.input('+1-213-373-4253') === '+1 213 373 4253'
|
528 | asYouType.getNumber().country === 'US'
|
529 | asYouType.getNumber().number === '+12133734253'
|
530 | asYouType.getChars() === '+12133734253'
|
531 | asYouType.getTemplate() === 'xx xxx xxx xxxx'
|
532 | ```
|
533 |
|
534 | * `isInternational(): boolean` — Returns `true` if the phone number is being input in international format. In other words, returns `true` if and only if the parsed phone number starts with a `"+"`.
|
535 |
|
536 | * `getCallingCode(): string` — Returns the ["country calling code"](#country-calling-code) part of the phone number. Returns `undefined` if the number is not being input in international format. Returns "country calling code" for ["non-geographic"](#non-geographic) phone numbering plans too.
|
537 |
|
538 | * `getCountry(): string` — Returns a two-letter [country code](#country-code) of the phone number. Returns `undefined` for ["non-geographic"](#non-geographic) phone numbering plans. Returns `undefined` if no phone number has been input yet.
|
539 |
|
540 | * `isPossible(): boolean` — Returns `true` if the phone number is "possible". Is just a shortcut for [`PhoneNumber.isPossible()`](#ispossible-boolean).
|
541 |
|
542 | * `isValid(): boolean` — Returns `true` if the phone number is "valid". Is just a shortcut for [`PhoneNumber.isValid()`](#isvalid-boolean).
|
543 |
|
544 | <details>
|
545 | <summary>Legacy API (before version <code>1.6.0</code>)</summary>
|
546 |
|
547 | ####
|
548 |
|
549 | For legacy API (before version `1.6.0`) the formatter instance provides the following getters:
|
550 |
|
551 | * `country: string?` — Phone number [country](#country-code). Will return `undefined` if the country couldn't be derived from the number.
|
552 |
|
553 | * `getNationalNumber(): string` — Returns the national (significant) number part of the phone number.
|
554 |
|
555 | * `getTemplate(): string?` — Same as the current version of `getTemplate()` with the only difference that it returns `undefined` if no suitable format was found for the number being entered (or if no [national (significant) number](#national-significant-number) has been entered so far).
|
556 |
|
557 | ```js
|
558 | // National phone number input example.
|
559 |
|
560 | const asYouType = new AsYouType('US')
|
561 |
|
562 | asYouType.input('2') === '2'
|
563 | asYouType.getNationalNumber() === '2'
|
564 |
|
565 | asYouType.input('1') === '21'
|
566 | asYouType.getNationalNumber() === '21'
|
567 |
|
568 | asYouType.input('3') === '(213)'
|
569 | asYouType.getNationalNumber() === '213'
|
570 |
|
571 | asYouType.input('3734253') === '(213) 373-4253'
|
572 | asYouType.getNationalNumber() === '2133734253'
|
573 |
|
574 | // International phone number input example.
|
575 |
|
576 | const asYouType = new AsYouType()
|
577 | asYouType.input('+1-213-373-4253') === '+1 213 373 4253'
|
578 | asYouType.country === 'US'
|
579 | asYouType.getNationalNumber() === '2133734253'
|
580 | ```
|
581 | </details>
|
582 |
|
583 | ####
|
584 |
|
585 | "As You Type" formatter was created by Google as part of their Android OS and therefore only works for numerical keyboard input, i.e. it can only accept digits (and a `+` sign in the start of an international number). When used on desktops where a user can input all kinds of punctuation (spaces, dashes, parens, etc) it simply ignores everything except digits (and a `+` sign in the start of an international number).
|
586 |
|
587 | Google's "As You Type" formatter does not support entering phone number extensions. If your project requires phone number extensions input then use a separate input field for that.
|
588 |
|
589 | ### findPhoneNumbersInText(text: string, [defaultCountry: string?], [options]): object[]
|
590 |
|
591 | Searches for phone numbers in `text`.
|
592 |
|
593 | Available `options`:
|
594 |
|
595 | * `defaultCountry` — Default country for parsing national numbers. Instead of passing `options.defaultCountry` one could pass `defaultCountry` argument directly.
|
596 |
|
597 | * `defaultCallingCode` — Default calling code for parsing national numbers. Some numbering plans are for ["non-geographic numbering plans"](#non-geographic) and they don't have a country code, so `defaultCountry` can't be specified for them.
|
598 |
|
599 | ```js
|
600 | import { findPhoneNumbersInText } from 'libphonenumber-js'
|
601 |
|
602 | findPhoneNumbersInText(`
|
603 | For tech support call +7 (800) 555-35-35 internationally
|
604 | or reach a local US branch at (213) 373-4253 ext. 1234.
|
605 | `, 'US')
|
606 |
|
607 | // Outputs:
|
608 | //
|
609 | // [{
|
610 | // number: PhoneNumber {
|
611 | // country: 'RU',
|
612 | // countryCallingCode: '7',
|
613 | // number: '+78005553535',
|
614 | // nationalNumber: '8005553535'
|
615 | // },
|
616 | // startsAt : 22,
|
617 | // endsAt : 40
|
618 | // }, {
|
619 | // number: PhoneNumber {
|
620 | // country: 'US',
|
621 | // countryCallingCode: '1',
|
622 | // number: '+12133734253',
|
623 | // nationalNumber: '2133734253',
|
624 | // ext: '1234'
|
625 | // },
|
626 | // startsAt : 86,
|
627 | // endsAt : 110
|
628 | // }]
|
629 | ```
|
630 |
|
631 | (in previous versions, it was called `findNumbers()`)
|
632 |
|
633 | <details>
|
634 | <summary>Legacy API (before version <code>1.6.0</code>) example</summary>
|
635 |
|
636 | ####
|
637 |
|
638 | ```js
|
639 | import { findNumbers } from 'libphonenumber-js'
|
640 |
|
641 | findNumbers(`
|
642 | For tech support call +7 (800) 555-35-35 internationally
|
643 | or reach a local US branch at (213) 373-4253 ext. 1234.
|
644 | `, 'US')
|
645 |
|
646 | // Outputs:
|
647 | //
|
648 | // [{
|
649 | // phone : '8005553535',
|
650 | // country : 'RU',
|
651 | // startsAt : 22,
|
652 | // endsAt : 40
|
653 | // },
|
654 | // {
|
655 | // phone : '2133734253',
|
656 | // country : 'US',
|
657 | // ext : '1234',
|
658 | // startsAt : 86,
|
659 | // endsAt : 110
|
660 | // }]
|
661 | ```
|
662 | </details>
|
663 |
|
664 | ####
|
665 |
|
666 | By default it processes the whole text and then outputs the phone numbers found. If the text is very big (say, a hundred thousand characters) then it might freeze the user interface for a couple of seconds. To avoid such lags one can employ "iterator" approach using `searchPhoneNumbersInText()` to perform the search asynchronously (e.g. using `requestIdleCallback` or `requestAnimationFrame`).
|
667 |
|
668 | (in previous versions, it was called `searchNumbers()`)
|
669 |
|
670 | <details>
|
671 | <summary>Asynchronous search example using <code>searchPhoneNumbersInText()</code></summary>
|
672 |
|
673 | ####
|
674 |
|
675 | ES6 iterator:
|
676 |
|
677 | ```js
|
678 | import { searchPhoneNumbersInText } from 'libphonenumber-js'
|
679 |
|
680 | const text = `
|
681 | For tech support call +7 (800) 555-35-35 internationally
|
682 | or reach a local US branch at (213) 373-4253 ext. 1234.
|
683 | `
|
684 |
|
685 | async function() {
|
686 | for (const number of searchPhoneNumbersInText(text, 'US')) {
|
687 | console.log(number)
|
688 | await new Promise(resolve => setTimeout(resolve, 0))
|
689 | }
|
690 | console.log('Finished')
|
691 | }
|
692 | ```
|
693 |
|
694 | Java-style iterator (for those still not using ES6):
|
695 |
|
696 | ```js
|
697 | import { PhoneNumberMatcher } from 'libphonenumber-js'
|
698 |
|
699 | const matcher = new PhoneNumberMatcher(`
|
700 | For tech support call +7 (800) 555-35-35 internationally
|
701 | or reach a local US branch at (213) 373-4253 ext. 1234.
|
702 | `, {
|
703 | defaultCountry: 'US',
|
704 | v2: true
|
705 | })
|
706 |
|
707 | // Search cycle iteration.
|
708 | const iteration = () => {
|
709 | if (matcher.hasNext()) {
|
710 | console.log(matcher.next())
|
711 | setTimeout(iteration, 0)
|
712 | } else {
|
713 | console.log('Finished')
|
714 | }
|
715 | }
|
716 |
|
717 | // Run the search.
|
718 | iteration()
|
719 | ```
|
720 | </details>
|
721 |
|
722 | ####
|
723 |
|
724 | Although Google's javascript port doesn't have the `findPhoneNumbersInText()` functionality the Java and C++ ports do. I guess Google just doesn't need to crawl phone numbers on Node.js because they can afford to hire a Java/C++ developer to do that. Still, javascript nowadays is the most popular programming language given its simplicity and user-friendliness. The `findPhoneNumbersInText()` function provided is a port of Google's `PhoneNumberMatcher.java` into javascript.
|
725 |
|
726 | ### getExampleNumber(country: string, examples: object): PhoneNumber
|
727 |
|
728 | Returns an example phone number for a [country](#country-code). Returns an instance of [`PhoneNumber`](#phonenumber) class. Will return `undefined` if `country` doesn't exist or isn't supported by this library.
|
729 |
|
730 | ```js
|
731 | import examples from 'libphonenumber-js/examples.mobile.json'
|
732 | import { getExampleNumber } from 'libphonenumber-js'
|
733 |
|
734 | const phoneNumber = getExampleNumber('RU', examples)
|
735 |
|
736 | phoneNumber.formatNational() === '8 (912) 345-67-89'
|
737 | ```
|
738 |
|
739 | ### isSupportedCountry(country: string): boolean
|
740 |
|
741 | Checks if a country is supported by this library.
|
742 |
|
743 | ```js
|
744 | isSupportedCountry('RU') === true
|
745 | isSupportedCountry('XX') === false
|
746 | ```
|
747 |
|
748 | ### getCountries(): string[]
|
749 |
|
750 | Returns a list of supported countries.
|
751 |
|
752 |
|
753 |
|
754 | ```js
|
755 | getCountries() === ["AC", "AD", ...]
|
756 | ```
|
757 |
|
758 | ### getCountryCallingCode(country: string): string
|
759 |
|
760 | Returns [country calling code](#country-calling-code) for a [country](#country-code). Will throw an error if `country` doesn't exist or isn't supported by this library.
|
761 |
|
762 | ```js
|
763 | getCountryCallingCode('RU') === '7'
|
764 | getCountryCallingCode('IL') === '972'
|
765 | ```
|
766 |
|
767 | ### getExtPrefix(country: string): string
|
768 |
|
769 | Returns phone number extension prefix for a given `country`. If no custom ext prefix is defined for a `country` then the default `" ext. "` prefix is returned.
|
770 |
|
771 | ```js
|
772 | getExtPrefix('US') === ' ext. '
|
773 | getExtPrefix('GB') === ' x'
|
774 | ```
|
775 |
|
776 |
|
777 | ### parsePhoneNumberCharacter(nextCharacter, prevParsedCharacters)
|
778 |
|
779 | Parses next character while parsing phone number digits (including a `+`) from text: discards everything except `+` and digits, and `+` is only allowed at the start of a phone number.
|
780 |
|
781 | For example, is used in [`input-format`](https://gitlab.com/catamphetamine/input-format).
|
782 |
|
783 | ```js
|
784 | // Suppose a user inputs "+1 (213) 373-42-53".
|
785 |
|
786 | parsePhoneNumberCharacter('+', undefined) === '+'
|
787 | parsePhoneNumberCharacter('1', '+') === '1'
|
788 | parsePhoneNumberCharacter(' ', '+1') === undefined
|
789 | parsePhoneNumberCharacter('(', '+1') === undefined
|
790 | parsePhoneNumberCharacter('2', '+1') === '2'
|
791 | parsePhoneNumberCharacter('1', '+12') === '1'
|
792 | parsePhoneNumberCharacter('3', '+121') === '3'
|
793 | parsePhoneNumberCharacter(')', '+1213') === undefined
|
794 | parsePhoneNumberCharacter(' ', '+1213') === undefined
|
795 | parsePhoneNumberCharacter('3', '+1213') === '3'
|
796 | parsePhoneNumberCharacter('7', '+12133') === '7'
|
797 | parsePhoneNumberCharacter('3', '+121337') === '3'
|
798 | parsePhoneNumberCharacter('-', '+121337') === undefined
|
799 | parsePhoneNumberCharacter('4', '+1213373') === '4'
|
800 | parsePhoneNumberCharacter('2', '+12133734') === '2'
|
801 | parsePhoneNumberCharacter('-', '+12133734') === undefined
|
802 | parsePhoneNumberCharacter('5', '+121337342') === '5'
|
803 | parsePhoneNumberCharacter('3', '+1213373425') === '3'
|
804 | ```
|
805 | -->
|
806 |
|
807 | ### parseDigits(text: string): string
|
808 |
|
809 | Parses digits from string. Can be used for building a phone number extension input component (e.g. [react-phone-number-input](https://gitlab.com/catamphetamine/react-phone-number-input/)).
|
810 |
|
811 | ```js
|
812 | parseDigits('x123') === '123'
|
813 | parseDigits('٤٤٢٣') === '4423'
|
814 | ```
|
815 |
|
816 | ### parseIncompletePhoneNumber(text: string): string
|
817 |
|
818 | Parses phone number characters (`+` and digits). Can be used for building a phone number input component (e.g. [react-phone-number-input](https://gitlab.com/catamphetamine/react-phone-number-input/)).
|
819 |
|
820 | ```js
|
821 | parseIncompletePhoneNumber('8 (800) 555') === '8800555'
|
822 | parseIncompletePhoneNumber('+7 800 555') === '+7800555'
|
823 | parseIncompletePhoneNumber('+٤٤٢٣٢٣٢٣٤') === '+442323234'
|
824 | ```
|
825 |
|
826 | ### formatIncompletePhoneNumber(value: string, country: string?): string
|
827 |
|
828 | Formats incomplete phone number as a national one for a given `country`. If `country` is not specified then outputs the phone number in international format. This is just an alias for `new AsYouType(country, metadata).input(value)`. Can be used for building a phone number input component (e.g. [react-phone-number-input](https://gitlab.com/catamphetamine/react-phone-number-input/)).
|
829 |
|
830 | ```js
|
831 | formatIncompletePhoneNumber('8800555', 'RU') === '8 (800) 555'
|
832 | formatIncompletePhoneNumber('+7800555') === '+7 800 555'
|
833 | ```
|
834 |
|
835 | ## Legacy API
|
836 |
|
837 | <details>
|
838 | <summary>Legacy API (before version <code>1.6.0</code>): <code>parse()</code>, <code>parseNumber()</code>, <code>format()</code>, <code>formatNumber()</code>, <code>isValidNumber()</code>, <code>getNumberType()</code>.</summary>
|
839 |
|
840 | ### parseNumber(text, [defaultCountry], [options])
|
841 |
|
842 | _(previously called `parse()`)_
|
843 |
|
844 | _(legacy API)_
|
845 |
|
846 | Attempts to parse a phone number from `text`.
|
847 |
|
848 | If [`defaultCountry`](#country-code) is passed then it's gonna be the default country for parsing non-international phone numbers.
|
849 |
|
850 | Returns `{ country, phone, ext }` object where
|
851 | * `country` is a [country code](#country-code).
|
852 | * `phone` is a [national (significant) number](#national-significant-number).
|
853 | * `ext` is a [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)).
|
854 |
|
855 | If the phone number supplied isn't valid then an empty object `{}` is returned.
|
856 |
|
857 | <details>
|
858 | <summary>Examples</summary>
|
859 |
|
860 | ```js
|
861 | // Parses international numbers.
|
862 | parseNumber('+1 213 373 4253') === { country: 'US', phone: '2133734253' }
|
863 | parseNumber('Phone: +1-213-373-4253.') === { country: 'US', phone: '2133734253' }
|
864 | parseNumber('+12133734253') === { country: 'US', phone: '2133734253' }
|
865 |
|
866 | // Parses national numbers provided a default country.
|
867 | parseNumber('Phone: (213) 373-4253.', 'US') === { country: 'US', phone: '2133734253' }
|
868 |
|
869 | // Parses phone number extensions.
|
870 | parseNumber('(213) 373-4253 ext. 123', 'US') === { country: 'US', phone: '2133734253', ext: '123' }
|
871 |
|
872 | // Parses RFC 3966 phone number URIs.
|
873 | parseNumber('tel:+78005553535;ext=123') === { country: 'RU', phone: '8005553535', ext: '123' }
|
874 | ```
|
875 |
|
876 | If the phone number supplied isn't valid then an empty object `{}` is returned.
|
877 |
|
878 | ```js
|
879 | parseNumber('+1 111 111 1111') === {}
|
880 | parseNumber('(111) 111-1111', 'US') === {}
|
881 | parseNumber('abcdefg') === {}
|
882 | ```
|
883 | </details>
|
884 |
|
885 | ####
|
886 |
|
887 | Available `options`:
|
888 |
|
889 | * `defaultCountry : string` — Same as the `defaultCountry` argument.
|
890 |
|
891 | * `extended : boolean` — If set to `true` then `parseNumber()` will attempt to parse even a remotely hypothetical phone number even if it is considered "invalid".
|
892 |
|
893 | <details>
|
894 | <summary><code>{ extended: true }</code> documentation and examples</summary>
|
895 |
|
896 | The result of "extended" parsing is an object where
|
897 |
|
898 | * `country` is a [country code](#country-code).
|
899 | * `phone` is a [national (significant) number](#national-significant-number).
|
900 | * `ext` is a [phone number extension](https://en.wikipedia.org/wiki/Extension_(telephone)).
|
901 | * `countryCallingCode` is a [country calling code](#country-calling-code).
|
902 | * [`carrierCode`](https://www.voip-info.org/carrier-identification-codes/)s are only used in Colombia and Brazil and only when dialing within those countries from a mobile phone to a fixed line number.
|
903 | * `valid: boolean` — whether it's a "valid" (real) phone number.
|
904 | * `possible: boolean` — a phone number is considered "possible" when it fits the phone number length rules for a given country. E.g. for US national (significant) number regexp is `[2-9]\d{9}` and possible national (significant) number length is `10` so a phone number `(111) 111-1111` is not a "valid" number because it doesn't match the US national (significant) number regexp but it is a "possible" number because it's `10` digits long.
|
905 | * Some or all of these properties may be absent from the result object.
|
906 |
|
907 | ```js
|
908 | // If the number is valid.
|
909 | parseNumber('Phone: (213) 373-4253.', 'US', { extended: true }) ===
|
910 | {
|
911 | country: 'US',
|
912 | phone: '2133734253',
|
913 | ext: undefined,
|
914 | countryCallingCode: 1,
|
915 | carrierCode: undefined,
|
916 | valid: true,
|
917 | possible: true
|
918 | }
|
919 |
|
920 | // If the number is not "valid" but "possible".
|
921 | parseNumber('(111) 111-1111', 'US', { extended: true }) ===
|
922 | {
|
923 | country: 'US',
|
924 | phone: '1111111111',
|
925 | ext: undefined,
|
926 | countryCallingCode: 1,
|
927 | carrierCode: undefined,
|
928 | valid: false,
|
929 | possible: true
|
930 | }
|
931 |
|
932 | // If the number is not "valid" but "possible"
|
933 | // and country can't be derived from it.
|
934 | // (e.g. can't tell if it's a US number or a Canadian number)
|
935 | parseNumber('+1 111 111 1111', { extended: true }) ===
|
936 | {
|
937 | country: undefined,
|
938 | phone: '1111111111',
|
939 | ext: undefined,
|
940 | countryCallingCode: 1,
|
941 | carrierCode: undefined,
|
942 | valid: false,
|
943 | possible: true
|
944 | }
|
945 |
|
946 | // If the number is not "possible" (invalid length).
|
947 | parseNumber('(213) 373', 'US', { extended: true }) ===
|
948 | {
|
949 | country: 'US',
|
950 | phone: '213373',
|
951 | ext: undefined,
|
952 | countryCallingCode: 1,
|
953 | carrierCode: undefined,
|
954 | valid: false,
|
955 | possible: false
|
956 | }
|
957 |
|
958 | // In some cases if the number is extremely not "possible"
|
959 | // then an empty object `{}` is returned.
|
960 | //
|
961 | // Too short (or too long) for any country's phone number.
|
962 | parseNumber('1', 'US', { extended: true }) === {}
|
963 | // Non-existent country calling code.
|
964 | parseNumber('+210', { extended: true }) === {}
|
965 | // No phone number found.
|
966 | parseNumber('abcdefg', 'US', { extended: true }) === {}
|
967 | ```
|
968 |
|
969 | The "extended" parsing mode is the default behaviour of the original Google's `libphonenumber`: it still returns parsed data even if the phone number being parsed is not considered valid (but is kinda "possible"). I guess this kind of behaviour is better for crawling websites for phone numbers because when mining "big data" it is better to extract all possible info rather than discard some pieces of it prematurely, e.g. when national (significant) number regexp for some country gets outdated which might very well happen because phone numbering plans are changing constantly around the world. Maybe after all it would make sense to make the "extended" parsing mode the default one in the next major version. I guess it would.
|
970 | </details>
|
971 |
|
972 | ####
|
973 |
|
974 | <details>
|
975 | <summary>Also parses IDD-prefixed phone numbers</summary>
|
976 |
|
977 | Sometimes users icorrectly input phone numbers in ["out-of-country" dialing](https://wikitravel.org/en/International_dialling_prefix) (IDD-prefixed) format instead of the proper international phone number format (the "+" notation). In such cases `parseNumber()` will attempt to parse such IDD-prefixed numbers if "default country" is provided:
|
978 |
|
979 | ```js
|
980 | // International format.
|
981 | parseNumber('+61 2 3456 7890') === { country: 'AU', phone: '234567890' }
|
982 | // IDD-prefixed format.
|
983 | parseNumber('011 61 2 3456 7890', 'US') === { country: 'AU', phone: '234567890' }
|
984 | ```
|
985 | </details>
|
986 |
|
987 | ### formatNumber(number, format, [options])
|
988 |
|
989 | _(previously called `format()`)_
|
990 |
|
991 | _(legacy API)_
|
992 |
|
993 | Formats a `number` into a string according to a `format`.
|
994 |
|
995 | Available `format`s and `options` are the same as for [`PhoneNumber.format(format)`](#formatformat-string-options).
|
996 |
|
997 | The `number` argument must be either a result of `parseNumber()` function call (to strip national prefix) or an E.164 phone number string (e.g. `+12133734253`).
|
998 |
|
999 | <details>
|
1000 | <summary>Examples</summary>
|
1001 |
|
1002 | ```js
|
1003 | // Formats E.164 phone numbers.
|
1004 | formatNumber('+12133734253', 'NATIONAL') === '(213) 373-4253'
|
1005 | formatNumber('+12133734253', 'INTERNATIONAL') === '+1 213 373 4253'
|
1006 |
|
1007 | // Formats E.164 phone numbers when
|
1008 | // they're not "valid" but still "possible".
|
1009 | formatNumber('+11111111111', 'NATIONAL') === '(111) 111-1111'
|
1010 | formatNumber('+11111111111', 'INTERNATIONAL') === '+1 111 111 1111'
|
1011 |
|
1012 | // Formats E.164 phone numbers when
|
1013 | // they're not "valid" and not "possible" (invalid length).
|
1014 | formatNumber('+11111', 'NATIONAL') === '1111'
|
1015 | formatNumber('+11111', 'INTERNATIONAL') === '+1 1111'
|
1016 |
|
1017 | // Formats a result of `parseNumber()` function call.
|
1018 | const parsedNumber = parseNumber('2133734253', 'US')
|
1019 | formatNumber(parsedNumber, 'NATIONAL') === '(213) 373-4253'
|
1020 | formatNumber(parsedNumber, 'INTERNATIONAL') === '+1 213 373 4253'
|
1021 |
|
1022 | // Formats a result of `parseNumber()` function call in "extended" mode
|
1023 | // when it's not a "valid" number but is still a "possible" one.
|
1024 | const possibleNumber = parseNumber('+11111111111', { extended: true })
|
1025 | formatNumber(possibleNumber, 'NATIONAL') === '(111) 111-1111'
|
1026 | formatNumber(possibleNumber, 'INTERNATIONAL') === '+1 111 111 1111'
|
1027 |
|
1028 | // Formats a result of `parseNumber()` function call in "extended" mode
|
1029 | // when it's neither a "valid" number nor a "possible" one (invalid length).
|
1030 | const possibleNumber = parseNumber('+11111', { extended: true })
|
1031 | formatNumber(possibleNumber, 'NATIONAL') === '1111'
|
1032 | formatNumber(possibleNumber, 'INTERNATIONAL') === '+1 1111'
|
1033 |
|
1034 | // Formats phone number extensions.
|
1035 | formatNumber({ country: 'US', phone: '2133734253', ext: '123' }, 'NATIONAL') === '(213) 373-4253 ext. 123'
|
1036 |
|
1037 | // When given an object not having `phone` property
|
1038 | // (e.g. a empty object `{}`) it will throw.
|
1039 | formatNumber({}) throws Error
|
1040 | ```
|
1041 | </details>
|
1042 |
|
1043 | ### getNumberType(number, [defaultCountry])
|
1044 |
|
1045 | _(legacy API)_
|
1046 |
|
1047 | See the description for [`PhoneNumber.getType()`](#gettype).
|
1048 |
|
1049 | The `number` argument can be either a result of the `parseNumber()` function call — `{ country, phone }` — or a string (phone number digits only) possibly accompanied with the second `defaultCountry` argument.
|
1050 |
|
1051 | <details>
|
1052 | <summary>Examples</summary>
|
1053 |
|
1054 | ```js
|
1055 | getNumberType('+79160151539') === 'MOBILE'
|
1056 | getNumberType('9160151539', 'RU') === 'MOBILE'
|
1057 | getNumberType({ phone: '9160151539', country: 'RU' }) === 'MOBILE'
|
1058 | ```
|
1059 | </details>
|
1060 |
|
1061 | ### isValidNumber(number, [defaultCountry])
|
1062 |
|
1063 | _(legacy API)_
|
1064 |
|
1065 | Checks if a phone number is valid, the validation is more strict than `parseNumber()`.
|
1066 |
|
1067 | The `number` argument can be either a result of the `parseNumber()` function call — `{ country, phone }` — or a string (phone number digits only) possibly accompanied with the second `defaultCountry` argument.
|
1068 |
|
1069 | <details>
|
1070 | <summary>Examples</summary>
|
1071 |
|
1072 | ```js
|
1073 | isValidNumber('+12133734253') === true
|
1074 | isValidNumber('+1213373') === false
|
1075 |
|
1076 | isValidNumber('2133734253', 'US') === true
|
1077 | isValidNumber('21337', 'US') === false
|
1078 |
|
1079 | isValidNumber({ phone: '2133734253', country: 'US' }) === true
|
1080 | ```
|
1081 | </details>
|
1082 |
|
1083 | ####
|
1084 |
|
1085 | <details>
|
1086 | <summary>The difference between using <code>parseNumber()</code> and <code>isValidNumber()</code></summary>
|
1087 |
|
1088 | The difference between using `parseNumber()` 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 `parseNumber('123456', 'DE')` would return `{ country: 'DE', phone: '123456' }` because this phone number matches the general phone number rules for Germany (basic length check, etc). But, if the metadata is compiled with `--extended` (or relevant `--types`) flag (see [Customizing metadata](#customizing-metadata) section of this document) then `isValidNumber()` is gonna use those precise regular expressions for extensive validation and `isValid('123456', 'DE')` will return `false` because the phone number `123456` doesn't actually exist in Germany.
|
1089 |
|
1090 | This is how it is implemented in the original Google's [`libphonenumber`](https://static.javadoc.io/com.googlecode.libphonenumber/libphonenumber/8.9.1/com/google/i18n/phonenumbers/PhoneNumberUtil.html#parse-java.lang.CharSequence-java.lang.String-): `parseNumber()` parses phone numbers and loosely validates them while `isValidNumber()` validates phone numbers precisely (provided the precise regular expressions are included in metadata).
|
1091 |
|
1092 | The precise regular expressions aren't included in the default metadata because that would cause the default metadata to grow twice in its size: the complete ("full") metadata size is about 145 kilobytes while the reduced ("default") metadata size is about 77 kilobytes. Hence in the default configuration `isValidNumber()` performs absolutely the same "lite" validation as `parseNumber()`. For enabling extensive phone number validation the simplest way is to import functions from `libphonenumber-js/custom` module and supply them with `libphonenumber-js/metadata.full.json`. For generating custom metadata see the instructions provided in the [Customizing metadata](#customizing-metadata) section of this document.
|
1093 | </details>
|
1094 |
|
1095 | ####
|
1096 |
|
1097 | <details>
|
1098 | <summary><code>isValidNumberForRegion()</code></summary>
|
1099 |
|
1100 | The optional `defaultCountry` argument is the _default_ country, i.e. it does not restrict to just that country, e.g. in those cases where several countries share the same phone numbering rules (NANPA, Britain, etc). For example, even though the number `07624 369230` belongs to the Isle of Man ("IM" country code) calling `isValidNumber('07624369230', 'GB')` still returns `true` because the country is not restricted to `GB`, it's just that `GB` is the default one for the phone numbering rules. For restricting the country see `isValidNumberForRegion()` though restricting a country [might not be a good idea](https://github.com/googlei18n/libphonenumber/blob/master/FAQ.md#when-should-i-use-isvalidnumberforregion).
|
1101 |
|
1102 | ```js
|
1103 | // Even though '07624 369230' number belongs to the Isle of Man ("IM")
|
1104 | // the `defaultCountry` argument "GB" still works here because
|
1105 | // "GB" and "IM" both share the same phone numbering rules ("+44").
|
1106 | isValidNumber('07624369230', 'GB') === true
|
1107 | isValidNumber('07624369230', 'IM') === true
|
1108 |
|
1109 | // Imposing country restrictions.
|
1110 | isValidNumberForRegion('07624369230', 'GB') === false
|
1111 | isValidNumberForRegion('07624369230', 'IM') === true
|
1112 | ```
|
1113 | </details>
|
1114 | </details>
|
1115 |
|
1116 | ## Using phone number validation feature
|
1117 |
|
1118 | I personally don't use strict phone number validation in my projects because telephone numbering plans sometimes change and so validation rules can change too which means that [`PhoneNumber.isValid()`](#isvalid) function may become outdated if a website isn't re-deployed regularly. For example:
|
1119 |
|
1120 | * New phone number rules can be added to Google's `libphonenumber` library after they have already been implemented in real life (which can introduce a delay).
|
1121 |
|
1122 |
|
1123 | * Then those new rules from Google's `libphonenumber` are updated automatically in this library (the scheduled update script introduces a small delay of 1 day, unless it malfunctions).
|
1124 | -->
|
1125 |
|
1126 | * After that those new rules from Google's `libphonenumber` are merged in this library (another delay).
|
1127 |
|
1128 | * And then there's still the web application itself using this library and until a developer installs `libphonenumber-js@latest` manually and rebuilds and redeploys the web application, it's gonna use the old (potentially outdated) phone number validation rules which could result in losing rare customers with newly valid (but previously non-valid) phone numbers if a website form is too strict about validating user's input.
|
1129 |
|
1130 | Phone number validation rules are [being updated regularly](https://github.com/googlei18n/libphonenumber/commits/master/resources/PhoneNumberMetadata.xml) in Google's repo. Imagine a web application (for example, a "promo-site" or a "personal website") with a "Contact Us" form being deployed once and then running for years without any maintenance.
|
1131 |
|
1132 | If it was required to validate a phone number being input by a user, then I'd personally use something like [`PhoneNumber.isPossible()`](#ispossible) that just validates phone number length.
|
1133 |
|
1134 | ## React
|
1135 |
|
1136 | If you’re trying to build a React component with this library, take a look at [`react-phone-number-input`](https://www.npmjs.com/package/react-phone-number-input).
|
1137 |
|
1138 | ## Bug reporting
|
1139 |
|
1140 | When reporting an issue one must also provide a link to [Google's `libphonenumber` demo page](https://libphonenumber.appspot.com/) illustrating the expected behaviour. This includes validation, parsing, formatting and "as you type" formatting. For example, for an Australian number `438 331 999` Google's demo [outputs four sections](https://libphonenumber.appspot.com/phonenumberparser?number=438331999&country=AU) — "Parsing Result", "Validation Results", "Formatting Results" and "AsYouTypeFormatter Results". In a bug report, first describe the observed `libphonenumber-js` demo result and then Google's demo result (with a link to it) which must differ from the observed `libphonenumber-js` demo result. If the observed `libphonenumber-js` demo result is the same as Google's demo result and you don't agree with Google's demo result then create an issue in [Google's repo](https://github.com/googlei18n/libphonenumber).
|
1141 |
|
1142 |
|
1143 | Phone number validation bugs should **only** be reported if they appear when using [custom metadata functions](#customizing-metadata) fed with `metadata.full.json` because by default all functions in this library use the reduced metadata set which results in looser validation than the original Google `libphonenumber`'s. The [demo page](https://catamphetamine.gitlab.io/libphonenumber-js/) also uses the reduced metadata set and therefore its validation is also looser than the original Google `libphonenumber`'s.
|
1144 |
|
1145 | There is also a possibility of this library's demo metadata being outdated, or this library's metadata lagging behind Google's (I have to update it manually from time to time due to `ssh-agent` not working properly on Windows).
|
1146 | -->
|
1147 |
|
1148 | When reporting `findPhoneNumbersInText()` bugs one should know that `findPhoneNumbersInText()` code was ported from [Google's Java code](https://github.com/googlei18n/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java). I didn't write it myself, I just ported it. Therefore, it is unlikely that anyone other than Google will be fixing such bugs.
|
1149 |
|
1150 | ## TypeScript
|
1151 |
|
1152 | [TypeScript support](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/index.d.ts) for this library is entirely community-driven. I myself don't use TypeScript. Send your pull requests.
|
1153 |
|
1154 | ## CDN
|
1155 |
|
1156 | One can use any npm CDN service, e.g. [unpkg.com](https://unpkg.com) or [jsdelivr.com](https://jsdelivr.com)
|
1157 |
|
1158 | ```html
|
1159 | <script src="https://unpkg.com/libphonenumber-js@[version]/bundle/libphonenumber-[type].js"></script>
|
1160 |
|
1161 | <script>
|
1162 | alert(new libphonenumber.AsYouType('US').input('213-373-4253'))
|
1163 | </script>
|
1164 | ```
|
1165 |
|
1166 | where `[version]` is an npm package version range (for example, `1.x` or `^1.7.6`) and `[type]` is the bundle type: `min`, `max` or `mobile`.
|
1167 |
|
1168 |
|
1169 | ## Standalone
|
1170 |
|
1171 | For those who aren't using bundlers for some reason there's a way to build a standalone version of the library
|
1172 |
|
1173 | * `git clone https://gitlab.com/catamphetamine/libphonenumber-js.git`
|
1174 | * `npm install`
|
1175 | * `npm run build`
|
1176 | * See the `bundle` folder for `libphonenumber-js.min.js`
|
1177 |
|
1178 | ```html
|
1179 | <script src="/scripts/libphonenumber-js.min.js"></script>
|
1180 | <script>
|
1181 | alert(new libphonenumber.AsYouType('US').input('213-373-4253'))
|
1182 | </script>
|
1183 | ```
|
1184 | -->
|
1185 |
|
1186 | ## Metadata
|
1187 |
|
1188 | Metadata is generated from Google's [`PhoneNumberMetadata.xml`](https://github.com/googlei18n/libphonenumber/blob/master/resources/PhoneNumberMetadata.xml) by transforming XML into JSON and removing unnecessary fields. See [metadata fields description](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md).
|
1189 |
|
1190 | ### Programmatic access
|
1191 |
|
1192 | Metadata can be accessed programmatically by using the exported `Metadata` class.
|
1193 |
|
1194 | ```js
|
1195 | import { Metadata } from 'libphonenumber-js/core'
|
1196 | import minMetadata from 'libphonenumber-js/metadata.min'
|
1197 |
|
1198 | const metadata = new Metadata(minMetadata)
|
1199 | // Select a country.
|
1200 | metadata.country('US')
|
1201 |
|
1202 | console.log(metadata.numberingPlan.leadingDigits())
|
1203 | console.log(metadata.numberingPlan.possibleLengths())
|
1204 | console.log(metadata.numberingPlan.IDDPrefix())
|
1205 | console.log(metadata.numberingPlan.defaultIDDPrefix())
|
1206 | ```
|
1207 |
|
1208 | As one can see, the [`Metadata` class](https://gitlab.com/catamphetamine/libphonenumber-js/-/blob/master/source/metadata.js) is not documented much. Partially, that's because its usage is not encouraged, but it's still used, for example, in [`react-phone-number-input`](https://gitlab.com/catamphetamine/react-phone-number-input/-/blob/master/source/phoneInputHelpers.js) to get "leading digits" for a country, or to get maximum phone number length for a country.
|
1209 |
|
1210 |
|
1211 | Currently I have a script set up monitoring changes to `PhoneNumberMetadata.xml` in Google's repo and automatically releasing new versions of this library when metadata in Google's repo gets updated. So this library'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:
|
1212 | -->
|
1213 |
|
1214 |
|
1215 | In case I forget to run the "autoupdate" script for a long time anyone can request metadata update via a Pull Request here on GitHub:
|
1216 |
|
1217 | * Fork this repo
|
1218 | * `npm install`
|
1219 | * `npm run metadata:update:branch`
|
1220 | * Submit a Pull Request to this repo from the `update-metadata` branch of your fork
|
1221 |
|
1222 | `npm run metadata:update:branch` command creates a new `update-metadata` branch, downloads the new [`PhoneNumberMetadata.xml`](https://github.com/googlei18n/libphonenumber/blob/master/resources/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.
|
1223 |
|
1224 | 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](#customizing-metadata) section of this document.
|
1225 | -->
|
1226 |
|
1227 | ### Customizing metadata
|
1228 |
|
1229 | This library comes prepackaged with [three types of metadata](#min-vs-max-vs-mobile-vs-core).
|
1230 |
|
1231 | Sometimes, 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 (even when including all regular expressions for validating phone number digits and detecting phone number type), then they can generate such custom metadata and pass it as the last argument to this library's "core" functions.
|
1232 |
|
1233 | See [generate custom metadata instructions](https://gitlab.com/catamphetamine/libphonenumber-metadata-generator).
|
1234 |
|
1235 | <details>
|
1236 | <summary>Then, use the generated <code>metadata.custom.json</code> file with the "core" functions.</summary>
|
1237 |
|
1238 | ####
|
1239 |
|
1240 | Pass the `metadata` argument as the last one to the "core" functions.
|
1241 |
|
1242 | In ES6 that would be:
|
1243 |
|
1244 | ```js
|
1245 | import {
|
1246 | parsePhoneNumberFromString as _parsePhoneNumberFromString,
|
1247 | findPhoneNumbersInText as _findPhoneNumbersInText,
|
1248 | AsYouType as _AsYouType
|
1249 | } from 'libphonenumber-js/core'
|
1250 |
|
1251 | import metadata from 'libphonenumber-js/metadata.full.json'
|
1252 |
|
1253 | function call(func, _arguments) {
|
1254 | var args = Array.prototype.slice.call(_arguments)
|
1255 | args.push(metadata)
|
1256 | return func.apply(this, args)
|
1257 | }
|
1258 |
|
1259 | export default function parsePhoneNumberFromString() {
|
1260 | return call(_parsePhoneNumberFromString, arguments)
|
1261 | }
|
1262 |
|
1263 | export function findPhoneNumbersInText() {
|
1264 | return call(_findPhoneNumbersInText, arguments)
|
1265 | }
|
1266 |
|
1267 | export function AsYouType(country) {
|
1268 | return _AsYouType.call(this, country, metadata)
|
1269 | }
|
1270 | AsYouType.prototype = Object.create(_AsYouType.prototype, {})
|
1271 | AsYouType.prototype.constructor = AsYouType
|
1272 | ```
|
1273 |
|
1274 | And for [Common.js](https://auth0.com/blog/javascript-module-systems-showdown/) environment that would be:
|
1275 |
|
1276 | ```js
|
1277 | var core = require('libphonenumber-js/core')
|
1278 | var metadata = require('libphonenumber-js/metadata.full.json')
|
1279 |
|
1280 | function call(func, _arguments) {
|
1281 | var args = Array.prototype.slice.call(_arguments)
|
1282 | args.push(metadata)
|
1283 | return func.apply(this, args)
|
1284 | }
|
1285 |
|
1286 | function parsePhoneNumberFromString() {
|
1287 | return call(core.parsePhoneNumberFromString, arguments)
|
1288 | }
|
1289 |
|
1290 | exports = module.exports = parsePhoneNumberFromString
|
1291 | exports['default'] = parsePhoneNumberFromString
|
1292 |
|
1293 | exports.findPhoneNumbersInText = function findPhoneNumbersInText() {
|
1294 | return call(core.findPhoneNumbersInText, arguments)
|
1295 | }
|
1296 |
|
1297 | exports.AsYouType = function AsYouType(country) {
|
1298 | return core.AsYouType.call(this, country, metadata)
|
1299 | }
|
1300 | exports.AsYouType.prototype = Object.create(core.AsYouType.prototype, {})
|
1301 | exports.AsYouType.prototype.constructor = exports.AsYouType
|
1302 | ```
|
1303 | </details>
|
1304 |
|
1305 | ####
|
1306 |
|
1307 | <details>
|
1308 | <summary>Legacy: How to use the generated <code>metadata.custom.json</code> file with the legacy "custom" functions.</summary>
|
1309 |
|
1310 | ####
|
1311 |
|
1312 | Pass the `metadata` argument as the last one to the "custom" functions.
|
1313 |
|
1314 | In ES6 that would be:
|
1315 |
|
1316 | ```js
|
1317 | import {
|
1318 | parseNumber,
|
1319 | formatNumber,
|
1320 | isValidNumber,
|
1321 | getNumberType,
|
1322 | AsYouType
|
1323 | } from 'libphonenumber-js/custom'
|
1324 |
|
1325 | import metadata from 'libphonenumber-js/metadata.full.json'
|
1326 |
|
1327 | parseNumber('+78005553535', metadata)
|
1328 | formatNumber({ phone: '8005553535', country: 'RU' }, metadata)
|
1329 | isValidNumber('+78005553535', metadata)
|
1330 | getNumberType('+78005553535', metadata)
|
1331 | new AsYouType('RU', metadata).input('+78005553535')
|
1332 | ```
|
1333 |
|
1334 | And for [Common.js](https://auth0.com/blog/javascript-module-systems-showdown/) environment that would be:
|
1335 |
|
1336 | ```js
|
1337 | var custom = require('libphonenumber-js/custom')
|
1338 | var metadata = require('libphonenumber-js/metadata.full.json')
|
1339 |
|
1340 | exports.parseNumber = function parseNumber() {
|
1341 | var parameters = Array.prototype.slice.call(arguments)
|
1342 | parameters.push(metadata)
|
1343 | return custom.parseNumber.apply(this, parameters)
|
1344 | }
|
1345 |
|
1346 | exports.formatNumber = function formatNumber() {
|
1347 | var parameters = Array.prototype.slice.call(arguments)
|
1348 | parameters.push(metadata)
|
1349 | return custom.formatNumber.apply(this, parameters)
|
1350 | }
|
1351 |
|
1352 | exports.isValidNumber = function isValidNumber() {
|
1353 | var parameters = Array.prototype.slice.call(arguments)
|
1354 | parameters.push(metadata)
|
1355 | return custom.isValidNumber.apply(this, parameters)
|
1356 | }
|
1357 |
|
1358 | exports.getNumberType = function isValidNumber() {
|
1359 | var parameters = Array.prototype.slice.call(arguments)
|
1360 | parameters.push(metadata)
|
1361 | return custom.getNumberType.apply(this, parameters)
|
1362 | }
|
1363 |
|
1364 | exports.AsYouType = function AsYouType(country) {
|
1365 | custom.AsYouType.call(this, country, metadata)
|
1366 | }
|
1367 |
|
1368 | exports.AsYouType.prototype = Object.create(custom.AsYouType.prototype, {})
|
1369 | exports.AsYouType.prototype.constructor = exports.AsYouType
|
1370 | ```
|
1371 | </details>
|
1372 |
|
1373 | Metadata should be re-generated each time the project is being deployed because Google constantly updates their metadata.
|
1374 |
|
1375 |
|
1376 |
|
1377 |
|
1378 | ## Automatic metadata update setup
|
1379 |
|
1380 | Create a daily (24 * 60 * 60) `launchd` job
|
1381 |
|
1382 | http://alvinalexander.com/mac-os-x/mac-osx-startup-crontab-launchd-jobs
|
1383 |
|
1384 | ```sh
|
1385 | mkdir /Users/kuchumovn/work/libphonenumber-js-autoupdate
|
1386 |
|
1387 | git clone https://gitlab.com/catamphetamine/libphonenumber-js.git /Users/kuchumovn/work/libphonenumber-js-autoupdate
|
1388 |
|
1389 | cd /Users/kuchumovn/work/libphonenumber-js-autoupdate
|
1390 |
|
1391 | npm install
|
1392 |
|
1393 | chmod u+x /Users/kuchumovn/work/libphonenumber-js-autoupdate/autoupdate.sh
|
1394 |
|
1395 | nano ~/Library/LaunchAgents/com.gitlab.catamphetamine.libphonenumber-js.metadata-update.plist
|
1396 |
|
1397 | <?xml version="1.0" encoding="UTF-8"?>
|
1398 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
1399 | <plist version="1.0">
|
1400 | <dict>
|
1401 | <key>Label</key>
|
1402 | <string>com.gitlab.catamphetamine.libphonenumber-js.metadata-update</string>
|
1403 |
|
1404 | <key>ProgramArguments</key>
|
1405 | <array>
|
1406 | <string>/Users/kuchumovn/work/libphonenumber-js-autoupdate/autoupdate.sh</string>
|
1407 | </array>
|
1408 |
|
1409 | <key>Nice</key>
|
1410 | <integer>1</integer>
|
1411 |
|
1412 | <key>StartInterval</key>
|
1413 | <integer>86400</integer>
|
1414 |
|
1415 | <key>RunAtLoad</key>
|
1416 | <true/>
|
1417 |
|
1418 | <key>StandardErrorPath</key>
|
1419 | <string>/tmp/libphonenumber.errors.txt</string>
|
1420 |
|
1421 | <key>StandardOutPath</key>
|
1422 | <string>/tmp/libphonenumber.output.txt</string>
|
1423 | </dict>
|
1424 | </plist>
|
1425 |
|
1426 | launchctl load ~/Library/LaunchAgents/com.gitlab.catamphetamine.libphonenumber-js.metadata-update.plist
|
1427 |
|
1428 | launchctl list | grep 'libphonenumber-js'
|
1429 | ```
|
1430 | -->
|
1431 |
|
1432 | ### Maintenance
|
1433 |
|
1434 | Google periodically releases new metadata with the changes described in the [release notes](https://github.com/googlei18n/libphonenumber/blob/master/release_notes.txt). Sometimes those are minor non-breaking updates, sometimes those are major-version breaking updates.
|
1435 |
|
1436 | Metadata update process is automated through an "autoupdate" script: see `autoupdate.cmd` (Windows) or `autoupdate.sh` (Linux/macOS). The script detects changes to `PhoneNumberMetadata.xml` in Google `libphonenumber`'s repo and if there are changes then it pulls the latest metadata, processes it, commits the changes to GitHub, builds a new version of the library and releases it to NPM. So this library's metadata is supposed to be up-to-date. I could set up this script to run automatically but on my Windows machine `ssh-agent` doesn't work properly so I run the "autoupdate" script manually from time to time.
|
1437 |
|
1438 | Also Google sometimes (very rarely) updates their code: [`phonenumberutil.js`](https://github.com/googlei18n/libphonenumber/blob/master/javascript/i18n/phonenumbers/phonenumberutil.js) (`parseNumber()`, `formatNumber()`, `isValidNumber()`, `getNumberType()`), [`AsYouTypeFormatter.java`](https://github.com/google/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java) (`AsYouType`), [`PhoneNumberMatcher`](https://github.com/googlei18n/libphonenumber/blob/master/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberMatcher.java) (`findPhoneNumbersInText()`). The latest sync-up was performed on Nov 8th, 2020.
|
1439 |
|
1440 | ## Contributing
|
1441 |
|
1442 | After cloning this repo, ensure dependencies are installed by running:
|
1443 |
|
1444 | ```sh
|
1445 | npm install
|
1446 | ```
|
1447 |
|
1448 | This module is written in ES6 and uses [Babel](http://babeljs.io/) for ES5
|
1449 | transpilation. Widely consumable JavaScript can be produced by running:
|
1450 |
|
1451 | ```sh
|
1452 | npm run build
|
1453 | ```
|
1454 |
|
1455 | Once `npm run build` has run, you may `import` or `require()` directly from
|
1456 | node.
|
1457 |
|
1458 | After developing, the full test suite can be evaluated by running:
|
1459 |
|
1460 | ```sh
|
1461 | npm test
|
1462 | ```
|
1463 |
|
1464 | Test coverage must remain at 100%:
|
1465 |
|
1466 | ```sh
|
1467 | npm run test-coverage
|
1468 | ```
|
1469 |
|
1470 | When you're ready to test your new functionality on a real project, you can run
|
1471 |
|
1472 | ```sh
|
1473 | npm pack
|
1474 | ```
|
1475 |
|
1476 | It will `build`, `test` and then create a `.tgz` archive which you can then install in your project folder
|
1477 |
|
1478 | ```sh
|
1479 | npm install [module name with version].tar.gz
|
1480 | ```
|
1481 |
|
1482 | ## Advertisement
|
1483 |
|
1484 | If you're looking for an international "2 days ago" javascript solution then check out [`javascript-time-ago`](https://gitlab.com/catamphetamine/javascript-time-ago).
|
1485 |
|
1486 | ## License
|
1487 |
|
1488 | [MIT](LICENSE)
|