You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.4 KiB

4 years ago
  1. "use strict";
  2. const path = require("path");
  3. /**
  4. * @param {string} context context for relative path
  5. * @param {string} relativePath path
  6. * @returns {string} absolute path
  7. */
  8. const requestToAbsolute = (context, relativePath) => {
  9. if (relativePath.startsWith("./") || relativePath.startsWith("../"))
  10. return path.join(context, relativePath);
  11. return relativePath;
  12. };
  13. /**
  14. * @typedef {Object} MakeRelativePathsCache
  15. * @property {Map<string, Map<string, string>>=} relativePaths
  16. */
  17. /**
  18. *
  19. * @param {string} maybeAbsolutePath path to check
  20. * @returns {boolean} returns true if path is "Absolute Path"-like
  21. */
  22. const looksLikeAbsolutePath = maybeAbsolutePath => {
  23. if (/^\/.*\/$/.test(maybeAbsolutePath)) {
  24. // this 'path' is actually a regexp generated by dynamic requires.
  25. // Don't treat it as an absolute path.
  26. return false;
  27. }
  28. return /^(?:[a-z]:\\|\/)/i.test(maybeAbsolutePath);
  29. };
  30. /**
  31. *
  32. * @param {string} p path to normalize
  33. * @returns {string} normalized version of path
  34. */
  35. const normalizePathSeparator = p => p.replace(/\\/g, "/");
  36. /**
  37. *
  38. * @param {string} context context for relative path
  39. * @param {string} identifier identifier for path
  40. * @returns {string} a converted relative path
  41. */
  42. const _makePathsRelative = (context, identifier) => {
  43. return identifier
  44. .split(/([|! ])/)
  45. .map(str =>
  46. looksLikeAbsolutePath(str)
  47. ? normalizePathSeparator(path.relative(context, str))
  48. : str
  49. )
  50. .join("");
  51. };
  52. /**
  53. *
  54. * @param {string} context context used to create relative path
  55. * @param {string} identifier identifier used to create relative path
  56. * @param {MakeRelativePathsCache=} cache the cache object being set
  57. * @returns {string} the returned relative path
  58. */
  59. exports.makePathsRelative = (context, identifier, cache) => {
  60. if (!cache) return _makePathsRelative(context, identifier);
  61. const relativePaths =
  62. cache.relativePaths || (cache.relativePaths = new Map());
  63. let cachedResult;
  64. let contextCache = relativePaths.get(context);
  65. if (contextCache === undefined) {
  66. relativePaths.set(context, (contextCache = new Map()));
  67. } else {
  68. cachedResult = contextCache.get(identifier);
  69. }
  70. if (cachedResult !== undefined) {
  71. return cachedResult;
  72. } else {
  73. const relativePath = _makePathsRelative(context, identifier);
  74. contextCache.set(identifier, relativePath);
  75. return relativePath;
  76. }
  77. };
  78. /**
  79. * @param {string} context absolute context path
  80. * @param {string} request any request string may containing absolute paths, query string, etc.
  81. * @returns {string} a new request string avoiding absolute paths when possible
  82. */
  83. exports.contextify = (context, request) => {
  84. return request
  85. .split("!")
  86. .map(r => {
  87. const splitPath = r.split("?", 2);
  88. if (/^[a-zA-Z]:\\/.test(splitPath[0])) {
  89. splitPath[0] = path.win32.relative(context, splitPath[0]);
  90. if (!/^[a-zA-Z]:\\/.test(splitPath[0])) {
  91. splitPath[0] = splitPath[0].replace(/\\/g, "/");
  92. }
  93. }
  94. if (/^\//.test(splitPath[0])) {
  95. splitPath[0] = path.posix.relative(context, splitPath[0]);
  96. }
  97. if (!/^(\.\.\/|\/|[a-zA-Z]:\\)/.test(splitPath[0])) {
  98. splitPath[0] = "./" + splitPath[0];
  99. }
  100. return splitPath.join("?");
  101. })
  102. .join("!");
  103. };
  104. /**
  105. * @param {string} context absolute context path
  106. * @param {string} request any request string
  107. * @returns {string} a new request string using absolute paths when possible
  108. */
  109. const _absolutify = (context, request) => {
  110. return request
  111. .split("!")
  112. .map(r => requestToAbsolute(context, r))
  113. .join("!");
  114. };
  115. exports.absolutify = _absolutify;