extractCountryCallingCode.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import stripIddPrefix from './stripIddPrefix.js';
  2. import extractCountryCallingCodeFromInternationalNumberWithoutPlusSign from './extractCountryCallingCodeFromInternationalNumberWithoutPlusSign.js';
  3. import Metadata from '../metadata.js';
  4. import { MAX_LENGTH_COUNTRY_CODE } from '../constants.js';
  5. /**
  6. * Converts a phone number digits (possibly with a `+`)
  7. * into a calling code and the rest phone number digits.
  8. * The "rest phone number digits" could include
  9. * a national prefix, carrier code, and national
  10. * (significant) number.
  11. * @param {string} number — Phone number digits (possibly with a `+`).
  12. * @param {string} [country] — Default country.
  13. * @param {string} [callingCode] — Default calling code (some phone numbering plans are non-geographic).
  14. * @param {object} metadata
  15. * @return {object} `{ countryCallingCodeSource: string?, countryCallingCode: string?, number: string }`
  16. * @example
  17. * // Returns `{ countryCallingCode: "1", number: "2133734253" }`.
  18. * extractCountryCallingCode('2133734253', 'US', null, metadata)
  19. * extractCountryCallingCode('2133734253', null, '1', metadata)
  20. * extractCountryCallingCode('+12133734253', null, null, metadata)
  21. * extractCountryCallingCode('+12133734253', 'RU', null, metadata)
  22. */
  23. export default function extractCountryCallingCode(number, country, callingCode, metadata) {
  24. if (!number) {
  25. return {};
  26. }
  27. var isNumberWithIddPrefix; // If this is not an international phone number,
  28. // then either extract an "IDD" prefix, or extract a
  29. // country calling code from a number by autocorrecting it
  30. // by prepending a leading `+` in cases when it starts
  31. // with the country calling code.
  32. // https://wikitravel.org/en/International_dialling_prefix
  33. // https://github.com/catamphetamine/libphonenumber-js/issues/376
  34. if (number[0] !== '+') {
  35. // Convert an "out-of-country" dialing phone number
  36. // to a proper international phone number.
  37. var numberWithoutIDD = stripIddPrefix(number, country, callingCode, metadata); // If an IDD prefix was stripped then
  38. // convert the number to international one
  39. // for subsequent parsing.
  40. if (numberWithoutIDD && numberWithoutIDD !== number) {
  41. isNumberWithIddPrefix = true;
  42. number = '+' + numberWithoutIDD;
  43. } else {
  44. // Check to see if the number starts with the country calling code
  45. // for the default country. If so, we remove the country calling code,
  46. // and do some checks on the validity of the number before and after.
  47. // https://github.com/catamphetamine/libphonenumber-js/issues/376
  48. if (country || callingCode) {
  49. var _extractCountryCallin = extractCountryCallingCodeFromInternationalNumberWithoutPlusSign(number, country, callingCode, metadata),
  50. countryCallingCode = _extractCountryCallin.countryCallingCode,
  51. shorterNumber = _extractCountryCallin.number;
  52. if (countryCallingCode) {
  53. return {
  54. countryCallingCodeSource: 'FROM_NUMBER_WITHOUT_PLUS_SIGN',
  55. countryCallingCode: countryCallingCode,
  56. number: shorterNumber
  57. };
  58. }
  59. }
  60. return {
  61. // No need to set it to `UNSPECIFIED`. It can be just `undefined`.
  62. // countryCallingCodeSource: 'UNSPECIFIED',
  63. number: number
  64. };
  65. }
  66. } // Fast abortion: country codes do not begin with a '0'
  67. if (number[1] === '0') {
  68. return {};
  69. }
  70. metadata = new Metadata(metadata); // The thing with country phone codes
  71. // is that they are orthogonal to each other
  72. // i.e. there's no such country phone code A
  73. // for which country phone code B exists
  74. // where B starts with A.
  75. // Therefore, while scanning digits,
  76. // if a valid country code is found,
  77. // that means that it is the country code.
  78. //
  79. var i = 2;
  80. while (i - 1 <= MAX_LENGTH_COUNTRY_CODE && i <= number.length) {
  81. var _countryCallingCode = number.slice(1, i);
  82. if (metadata.hasCallingCode(_countryCallingCode)) {
  83. metadata.selectNumberingPlan(_countryCallingCode);
  84. return {
  85. countryCallingCodeSource: isNumberWithIddPrefix ? 'FROM_NUMBER_WITH_IDD' : 'FROM_NUMBER_WITH_PLUS_SIGN',
  86. countryCallingCode: _countryCallingCode,
  87. number: number.slice(i)
  88. };
  89. }
  90. i++;
  91. }
  92. return {};
  93. } // The possible values for the returned `countryCallingCodeSource` are:
  94. //
  95. // Copy-pasted from:
  96. // https://github.com/google/libphonenumber/blob/master/resources/phonenumber.proto
  97. //
  98. // // The source from which the country_code is derived. This is not set in the
  99. // // general parsing method, but in the method that parses and keeps raw_input.
  100. // // New fields could be added upon request.
  101. // enum CountryCodeSource {
  102. // // Default value returned if this is not set, because the phone number was
  103. // // created using parse, not parseAndKeepRawInput. hasCountryCodeSource will
  104. // // return false if this is the case.
  105. // UNSPECIFIED = 0;
  106. //
  107. // // The country_code is derived based on a phone number with a leading "+",
  108. // // e.g. the French number "+33 1 42 68 53 00".
  109. // FROM_NUMBER_WITH_PLUS_SIGN = 1;
  110. //
  111. // // The country_code is derived based on a phone number with a leading IDD,
  112. // // e.g. the French number "011 33 1 42 68 53 00", as it is dialled from US.
  113. // FROM_NUMBER_WITH_IDD = 5;
  114. //
  115. // // The country_code is derived based on a phone number without a leading
  116. // // "+", e.g. the French number "33 1 42 68 53 00" when defaultCountry is
  117. // // supplied as France.
  118. // FROM_NUMBER_WITHOUT_PLUS_SIGN = 10;
  119. //
  120. // // The country_code is derived NOT based on the phone number itself, but
  121. // // from the defaultCountry parameter provided in the parsing function by the
  122. // // clients. This happens mostly for numbers written in the national format
  123. // // (without country code). For example, this would be set when parsing the
  124. // // French number "01 42 68 53 00", when defaultCountry is supplied as
  125. // // France.
  126. // FROM_DEFAULT_COUNTRY = 20;
  127. // }
  128. //# sourceMappingURL=extractCountryCallingCode.js.map