parseIncompletePhoneNumber.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import { parseDigit } from './helpers/parseDigits.js'
  2. /**
  3. * Parses phone number characters from a string.
  4. * Drops all punctuation leaving only digits and the leading `+` sign (if any).
  5. * Also converts wide-ascii and arabic-indic numerals to conventional numerals.
  6. * E.g. in Iraq they don't write `+442323234` but rather `+٤٤٢٣٢٣٢٣٤`.
  7. * @param {string} string
  8. * @return {string}
  9. * @example
  10. * ```js
  11. * // Outputs '8800555'.
  12. * parseIncompletePhoneNumber('8 (800) 555')
  13. * // Outputs '+7800555'.
  14. * parseIncompletePhoneNumber('+7 800 555')
  15. * ```
  16. */
  17. export default function parseIncompletePhoneNumber(string) {
  18. let result = ''
  19. // Using `.split('')` here instead of normal `for ... of`
  20. // because the importing application doesn't neccessarily include an ES6 polyfill.
  21. // The `.split('')` approach discards "exotic" UTF-8 characters
  22. // (the ones consisting of four bytes) but digits
  23. // (including non-European ones) don't fall into that range
  24. // so such "exotic" characters would be discarded anyway.
  25. for (const character of string.split('')) {
  26. result += parsePhoneNumberCharacter(character, result) || ''
  27. }
  28. return result
  29. }
  30. /**
  31. * Parses next character while parsing phone number digits (including a `+`)
  32. * from text: discards everything except `+` and digits, and `+` is only allowed
  33. * at the start of a phone number.
  34. * For example, is used in `react-phone-number-input` where it uses
  35. * [`input-format`](https://gitlab.com/catamphetamine/input-format).
  36. * @param {string} character - Yet another character from raw input string.
  37. * @param {string?} prevParsedCharacters - Previous parsed characters.
  38. * @param {function?} emitEvent - An optional "emit event" function.
  39. * @return {string?} The parsed character.
  40. */
  41. export function parsePhoneNumberCharacter(character, prevParsedCharacters, emitEvent) {
  42. // Only allow a leading `+`.
  43. if (character === '+') {
  44. // If this `+` is not the first parsed character
  45. // then discard it.
  46. if (prevParsedCharacters) {
  47. // `emitEvent` argument was added to this `export`ed function on Dec 26th, 2023.
  48. // Any 3rd-party code that used to `import` and call this function before that
  49. // won't be passing any `emitEvent` argument.
  50. //
  51. // The addition of the `emitEvent` argument was to fix the slightly-weird behavior
  52. // of parsing an input string when the user inputs something like `"2+7"
  53. // https://github.com/catamphetamine/react-phone-number-input/issues/437
  54. //
  55. // If the parser encounters an unexpected `+` in a string being parsed
  56. // then it simply discards that out-of-place `+` and any following characters.
  57. //
  58. if (typeof emitEvent === 'function') {
  59. emitEvent('end')
  60. }
  61. return
  62. }
  63. return '+'
  64. }
  65. // Allow digits.
  66. return parseDigit(character)
  67. }