identifier.js 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Ivan Kopeykin @vankop
  4. */
  5. "use strict";
  6. const PATH_QUERY_FRAGMENT_REGEXP =
  7. /^(#?(?:\0.|[^?#\0])*)(\?(?:\0.|[^#\0])*)?(#.*)?$/;
  8. const ZERO_ESCAPE_REGEXP = /\0(.)/g;
  9. /**
  10. * @param {string} identifier identifier
  11. * @returns {[string, string, string]|null} parsed identifier
  12. */
  13. function parseIdentifier(identifier) {
  14. if (!identifier) {
  15. return null;
  16. }
  17. const firstEscape = identifier.indexOf("\0");
  18. if (firstEscape < 0) {
  19. // Fast path for inputs that don't use \0 escaping.
  20. const queryStart = identifier.indexOf("?");
  21. // Start at index 1 to ignore a possible leading hash.
  22. const fragmentStart = identifier.indexOf("#", 1);
  23. if (fragmentStart < 0) {
  24. if (queryStart < 0) {
  25. // No fragment, no query
  26. return [identifier, "", ""];
  27. }
  28. // Query, no fragment
  29. return [
  30. identifier.slice(0, queryStart),
  31. identifier.slice(queryStart),
  32. ""
  33. ];
  34. }
  35. if (queryStart < 0 || fragmentStart < queryStart) {
  36. // Fragment, no query
  37. return [
  38. identifier.slice(0, fragmentStart),
  39. "",
  40. identifier.slice(fragmentStart)
  41. ];
  42. }
  43. // Query and fragment
  44. return [
  45. identifier.slice(0, queryStart),
  46. identifier.slice(queryStart, fragmentStart),
  47. identifier.slice(fragmentStart)
  48. ];
  49. }
  50. const match = PATH_QUERY_FRAGMENT_REGEXP.exec(identifier);
  51. if (!match) return null;
  52. return [
  53. match[1].replace(ZERO_ESCAPE_REGEXP, "$1"),
  54. match[2] ? match[2].replace(ZERO_ESCAPE_REGEXP, "$1") : "",
  55. match[3] || ""
  56. ];
  57. }
  58. module.exports.parseIdentifier = parseIdentifier;