UNPKG

5.28 kBJavaScriptView Raw
1import checkNumberLength from './helpers/checkNumberLength'
2import parseDigits from './helpers/parseDigits'
3import formatNationalNumberUsingFormat from './helpers/formatNationalNumberUsingFormat'
4
5export default function formatCompleteNumber(state, format, {
6 metadata,
7 shouldTryNationalPrefixFormattingRule,
8 getSeparatorAfterNationalPrefix
9}) {
10 const matcher = new RegExp(`^(?:${format.pattern()})$`)
11 if (matcher.test(state.nationalSignificantNumber)) {
12 return formatNationalNumberWithAndWithoutNationalPrefixFormattingRule(
13 state,
14 format,
15 {
16 metadata,
17 shouldTryNationalPrefixFormattingRule,
18 getSeparatorAfterNationalPrefix
19 }
20 )
21 }
22}
23
24export function canFormatCompleteNumber(nationalSignificantNumber, metadata) {
25 return checkNumberLength(nationalSignificantNumber, metadata) === 'IS_POSSIBLE'
26}
27
28function formatNationalNumberWithAndWithoutNationalPrefixFormattingRule(state, format, {
29 metadata,
30 shouldTryNationalPrefixFormattingRule,
31 getSeparatorAfterNationalPrefix
32}) {
33 // `format` has already been checked for `nationalPrefix` requirement.
34
35 const {
36 nationalSignificantNumber,
37 international,
38 nationalPrefix,
39 carrierCode
40 } = state
41
42 // Format the number with using `national_prefix_formatting_rule`.
43 // If the resulting formatted number is a valid formatted number, then return it.
44 //
45 // Google's AsYouType formatter is different in a way that it doesn't try
46 // to format using the "national prefix formatting rule", and instead it
47 // simply prepends a national prefix followed by a " " character.
48 // This code does that too, but as a fallback.
49 // The reason is that "national prefix formatting rule" may use parentheses,
50 // which wouldn't be included has it used the simpler Google's way.
51 //
52 if (shouldTryNationalPrefixFormattingRule(format)) {
53 const formattedNumber = formatNationalNumber(state, format, {
54 useNationalPrefixFormattingRule: true,
55 getSeparatorAfterNationalPrefix,
56 metadata
57 })
58 if (formattedNumber) {
59 return formattedNumber
60 }
61 }
62
63 // Format the number without using `national_prefix_formatting_rule`.
64 return formatNationalNumber(state, format, {
65 useNationalPrefixFormattingRule: false,
66 getSeparatorAfterNationalPrefix,
67 metadata
68 })
69}
70
71function formatNationalNumber(state, format, {
72 metadata,
73 useNationalPrefixFormattingRule,
74 getSeparatorAfterNationalPrefix
75}) {
76 let formattedNationalNumber = formatNationalNumberUsingFormat(
77 state.nationalSignificantNumber,
78 format,
79 {
80 carrierCode: state.carrierCode,
81 useInternationalFormat: state.international,
82 withNationalPrefix: useNationalPrefixFormattingRule,
83 metadata
84 }
85 )
86 if (!useNationalPrefixFormattingRule) {
87 if (state.nationalPrefix) {
88 // If a national prefix was extracted, then just prepend it,
89 // followed by a " " character.
90 formattedNationalNumber = state.nationalPrefix +
91 getSeparatorAfterNationalPrefix(format) +
92 formattedNationalNumber
93 } else if (state.complexPrefixBeforeNationalSignificantNumber) {
94 formattedNationalNumber = state.complexPrefixBeforeNationalSignificantNumber +
95 ' ' +
96 formattedNationalNumber
97 }
98 }
99 if (isValidFormattedNationalNumber(formattedNationalNumber, state)) {
100 return formattedNationalNumber
101 }
102}
103
104// Check that the formatted phone number contains exactly
105// the same digits that have been input by the user.
106// For example, when "0111523456789" is input for `AR` country,
107// the extracted `this.nationalSignificantNumber` is "91123456789",
108// which means that the national part of `this.digits` isn't simply equal to
109// `this.nationalPrefix` + `this.nationalSignificantNumber`.
110//
111// Also, a `format` can add extra digits to the `this.nationalSignificantNumber`
112// being formatted via `metadata[country].national_prefix_transform_rule`.
113// For example, for `VI` country, it prepends `340` to the national number,
114// and if this check hasn't been implemented, then there would be a bug
115// when `340` "area coude" is "duplicated" during input for `VI` country:
116// https://github.com/catamphetamine/libphonenumber-js/issues/318
117//
118// So, all these "gotchas" are filtered out.
119//
120// In the original Google's code, the comments say:
121// "Check that we didn't remove nor add any extra digits when we matched
122// this formatting pattern. This usually happens after we entered the last
123// digit during AYTF. Eg: In case of MX, we swallow mobile token (1) when
124// formatted but AYTF should retain all the number entered and not change
125// in order to match a format (of same leading digits and length) display
126// in that way."
127// "If it's the same (i.e entered number and format is same), then it's
128// safe to return this in formatted number as nothing is lost / added."
129// Otherwise, don't use this format.
130// https://github.com/google/libphonenumber/commit/3e7c1f04f5e7200f87fb131e6f85c6e99d60f510#diff-9149457fa9f5d608a11bb975c6ef4bc5
131// https://github.com/google/libphonenumber/commit/3ac88c7106e7dcb553bcc794b15f19185928a1c6#diff-2dcb77e833422ee304da348b905cde0b
132//
133function isValidFormattedNationalNumber(formattedNationalNumber, state) {
134 return parseDigits(formattedNationalNumber) === state.getNationalDigits()
135}
\No newline at end of file