normalize-uri.mjs 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. export default normalizeUri
  2. import asciiAlphanumeric from '../character/ascii-alphanumeric.mjs'
  3. import codes from '../character/codes.mjs'
  4. import values from '../character/values.mjs'
  5. import fromCharCode from '../constant/from-char-code.mjs'
  6. // Encode unsafe characters with percent-encoding, skipping already
  7. // encoded sequences.
  8. function normalizeUri(value) {
  9. var index = -1
  10. var result = []
  11. var start = 0
  12. var skip = 0
  13. var code
  14. var next
  15. var replace
  16. while (++index < value.length) {
  17. code = value.charCodeAt(index)
  18. // A correct percent encoded value.
  19. if (
  20. code === codes.percentSign &&
  21. asciiAlphanumeric(value.charCodeAt(index + 1)) &&
  22. asciiAlphanumeric(value.charCodeAt(index + 2))
  23. ) {
  24. skip = 2
  25. }
  26. // ASCII.
  27. else if (code < 128) {
  28. if (!/[!#$&-;=?-Z_a-z~]/.test(fromCharCode(code))) {
  29. replace = fromCharCode(code)
  30. }
  31. }
  32. // Astral.
  33. else if (code > 55295 && code < 57344) {
  34. next = value.charCodeAt(index + 1)
  35. // A correct surrogate pair.
  36. if (code < 56320 && next > 56319 && next < 57344) {
  37. replace = fromCharCode(code, next)
  38. skip = 1
  39. }
  40. // Lone surrogate.
  41. else {
  42. replace = values.replacementCharacter
  43. }
  44. }
  45. // Unicode.
  46. else {
  47. replace = fromCharCode(code)
  48. }
  49. if (replace) {
  50. result.push(value.slice(start, index), encodeURIComponent(replace))
  51. start = index + skip + 1
  52. replace = undefined
  53. }
  54. if (skip) {
  55. index += skip
  56. skip = 0
  57. }
  58. }
  59. return result.join('') + value.slice(start)
  60. }