RFC3966.js 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import isViablePhoneNumber from './isViablePhoneNumber.js'
  2. // https://www.ietf.org/rfc/rfc3966.txt
  3. /**
  4. * @param {string} text - Phone URI (RFC 3966).
  5. * @return {object} `{ ?number, ?ext }`.
  6. */
  7. export function parseRFC3966(text) {
  8. let number
  9. let ext
  10. // Replace "tel:" with "tel=" for parsing convenience.
  11. text = text.replace(/^tel:/, 'tel=')
  12. for (const part of text.split(';')) {
  13. const [name, value] = part.split('=')
  14. switch (name) {
  15. case 'tel':
  16. number = value
  17. break
  18. case 'ext':
  19. ext = value
  20. break
  21. case 'phone-context':
  22. // Only "country contexts" are supported.
  23. // "Domain contexts" are ignored.
  24. if (value[0] === '+') {
  25. number = value + number
  26. }
  27. break
  28. }
  29. }
  30. // If the phone number is not viable, then abort.
  31. if (!isViablePhoneNumber(number)) {
  32. return {}
  33. }
  34. const result = { number }
  35. if (ext) {
  36. result.ext = ext
  37. }
  38. return result
  39. }
  40. /**
  41. * @param {object} - `{ ?number, ?extension }`.
  42. * @return {string} Phone URI (RFC 3966).
  43. */
  44. export function formatRFC3966({ number, ext }) {
  45. if (!number) {
  46. return ''
  47. }
  48. if (number[0] !== '+') {
  49. throw new Error(`"formatRFC3966()" expects "number" to be in E.164 format.`)
  50. }
  51. return `tel:${number}${ext ? ';ext=' + ext : ''}`
  52. }