identifier.js 1.7 KB

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