{"version":3,"file":"correct-path.mjs","names":["currentDir","cwd","_fileURLToPath","_pathToFileURL"],"sources":["../src/correct-path.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n                       ⚡ Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website:                  https://stormsoftware.com\n Repository:               https://github.com/storm-software/stryke\n Documentation:            https://docs.stormsoftware.com/projects/stryke\n Contact:                  https://stormsoftware.com/contact\n\n SPDX-License-Identifier:  Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport {\n  fileURLToPath as _fileURLToPath,\n  pathToFileURL as _pathToFileURL\n} from \"node:url\";\nimport { appendPath } from \"./append\";\nimport { cwd as currentDir } from \"./cwd\";\nimport { isAbsolutePath } from \"./is-type\";\nimport { joinPaths } from \"./join-paths\";\nimport {\n  DRIVE_LETTER_REGEX,\n  DRIVE_LETTER_START_REGEX,\n  UNC_REGEX\n} from \"./regex\";\nimport { slash } from \"./slash\";\n\n// Util to normalize windows paths to posix\nexport function normalizeWindowsPath(input = \"\") {\n  if (!input) {\n    return input;\n  }\n\n  return slash(input).replace(DRIVE_LETTER_START_REGEX, r => r.toUpperCase());\n}\n\n/**\n * Corrects/normalized a file path.\n *\n * @param path - The path to correct.\n * @returns The corrected path.\n */\nexport function correctPath(path?: string) {\n  if (!path || path.length === 0) {\n    return \".\";\n  }\n\n  // Normalize windows argument\n  path = normalizeWindowsPath(path);\n\n  const isUNCPath = path.match(UNC_REGEX);\n  const isPathAbsolute = isAbsolutePath(path);\n  const trailingSeparator = path.endsWith(\"/\");\n\n  // Normalize the path\n  path = normalizeString(path, !isPathAbsolute);\n\n  if (path.length === 0) {\n    if (isPathAbsolute) {\n      return \"/\";\n    }\n    return trailingSeparator ? \"./\" : \".\";\n  }\n\n  if (trailingSeparator) {\n    path += \"/\";\n  }\n  if (DRIVE_LETTER_REGEX.test(path)) {\n    path += \"/\";\n  }\n\n  if (isUNCPath) {\n    if (!isPathAbsolute) {\n      return `//./${path}`;\n    }\n    return `//${path}`;\n  }\n\n  return !path.startsWith(\"/\") &&\n    isPathAbsolute &&\n    !DRIVE_LETTER_REGEX.test(path)\n    ? `/${path}`\n    : path;\n}\n\n/**\n * Remove any star tokens (*) from the end of the file path\n *\n * @example\n * stripStars(\"src/**\") // returns \"src\"\n * stripStars(\"src/*\") // returns \"src\"\n * stripStars(\"src/**\\/*\") // returns \"src\"\n * stripStars(\"src/**\\/*.txt\") // returns \"src\"\n * stripStars(\"src/**\\/file.txt\") // returns \"src\"\n * stripStars(\"src/file.txt\") // returns \"src/file.txt\"\n * stripStars(\"\") // returns \".\"\n *\n * @param path - The path to correct.\n * @returns The corrected path.\n */\nexport function stripStars(path?: string) {\n  if (!path || path.length === 0) {\n    return \".\";\n  }\n\n  path = correctPath(path);\n\n  let found = false;\n\n  return `${path.startsWith(\"/\") ? \"/\" : \"\"}${path\n    .split(\"/\")\n    .reduce((ret, segment) => {\n      if (!segment?.trim()) {\n        return ret;\n      }\n\n      if (found || segment.includes(\"*\")) {\n        found = true;\n        return ret;\n      }\n\n      return ret + (ret ? `/${segment}` : segment);\n    }, \"\")}`;\n}\n\n/**\n * Resolves a string path, resolving '.' and '.' segments and allowing paths above the root.\n *\n * @param path - The path to normalize.\n * @param allowAboveRoot - Whether to allow the resulting path to be above the root directory.\n * @returns the normalize path string.\n */\nexport function normalizeString(path: string, allowAboveRoot: boolean) {\n  let res = \"\";\n  let lastSegmentLength = 0;\n  let lastSlash = -1;\n  let dots = 0;\n  let char: string | null = null;\n  for (let index = 0; index <= path.length; ++index) {\n    if (index < path.length) {\n      // casted because we know it exists thanks to the length check\n      char = path[index] as string;\n    } else if (char === \"/\") {\n      break;\n    } else {\n      char = \"/\";\n    }\n    if (char === \"/\") {\n      if (lastSlash === index - 1 || dots === 1) {\n        // NOOP\n      } else if (dots === 2) {\n        if (\n          res.length < 2 ||\n          lastSegmentLength !== 2 ||\n          res[res.length - 1] !== \".\" ||\n          res[res.length - 2] !== \".\"\n        ) {\n          if (res.length > 2) {\n            const lastSlashIndex = res.lastIndexOf(\"/\");\n            if (lastSlashIndex === -1) {\n              res = \"\";\n              lastSegmentLength = 0;\n            } else {\n              res = res.slice(0, lastSlashIndex);\n              lastSegmentLength = res.length - 1 - res.lastIndexOf(\"/\");\n            }\n            lastSlash = index;\n            dots = 0;\n            continue;\n          } else if (res.length > 0) {\n            res = \"\";\n            lastSegmentLength = 0;\n            lastSlash = index;\n            dots = 0;\n            continue;\n          }\n        }\n        if (allowAboveRoot) {\n          res += res.length > 0 ? \"/..\" : \"..\";\n          lastSegmentLength = 2;\n        }\n      } else {\n        if (res.length > 0) {\n          res += `/${path.slice(lastSlash + 1, index)}`;\n        } else {\n          res = path.slice(lastSlash + 1, index);\n        }\n        lastSegmentLength = index - lastSlash - 1;\n      }\n      lastSlash = index;\n      dots = 0;\n    } else if (char === \".\" && dots !== -1) {\n      ++dots;\n    } else {\n      dots = -1;\n    }\n  }\n  return res;\n}\n\n/**\n * Converts a given path to an absolute path based on the current working directory.\n *\n * @param path - The path to convert to an absolute path.\n * @param cwd - The current working directory to use as the base path if the path is not absolute.\n * @returns The absolute path.\n */\nexport function toAbsolutePath(path: string, cwd = currentDir()): string {\n  if (isAbsolutePath(path)) {\n    return path;\n  }\n\n  return slash(normalizeString(appendPath(path, cwd), true));\n}\n\n/**\n * Converts a given path to a relative path based on the current working directory.\n *\n * @param path - The path to convert to a relative path.\n * @param cwd - The current working directory to use as the base path if the path is not absolute.\n * @returns The relative path.\n */\nexport function toRelativePath(path: string, cwd = currentDir()): string {\n  if (!path || path.length === 0) {\n    return \".\";\n  }\n\n  if (isAbsolutePath(path)) {\n    path = slash(normalizeString(path, true));\n  } else {\n    path = slash(normalizeString(joinPaths(cwd, path), true));\n  }\n\n  if (path.startsWith(\"./\")) {\n    return path.slice(2);\n  }\n\n  return path;\n}\n\n/**\n * Adds a trailing slash to a path if it doesn't already have one.\n *\n * @param path - The path to modify.\n * @returns The modified path with a trailing slash.\n */\nexport function withTrailingSlash(path: string): string {\n  const result = correctPath(path);\n\n  return result.endsWith(\"/\") ? result : `${result}/`;\n}\n\n/**\n * Removes a trailing slash from a path if it has one.\n *\n * @param path - The path to modify.\n * @returns The modified path without a trailing slash.\n */\nexport function withoutTrailingSlash(path: string): string {\n  const result = correctPath(path);\n\n  return result.endsWith(\"/\") ? result.slice(0, -1) : result;\n}\n\n/**\n * Converts a file URL to a local file system path with normalized slashes.\n *\n * @example\n * ```ts\n * let filePath = fileURLToPath(\"file:///C:/Users/user/Documents/file.txt\");\n * // filePath = \"C:/Users/user/Documents/file.txt\"\n *\n * filePath = fileURLToPath(new URL(\"file:///C:/Users/user/Documents/file.txt\"));\n * // filePath = \"C:/Users/user/Documents/file.txt\"\n * ```\n *\n * @param id - The file URL or local path to convert.\n * @returns A normalized file system path.\n */\nexport function fileURLToPath(id: string | URL): string {\n  if (typeof id === \"string\" && !id.startsWith(\"file://\")) {\n    return correctPath(id);\n  }\n  return correctPath(_fileURLToPath(id));\n}\n\n/**\n * Converts a local file system path to a file URL.\n *\n * @example\n * ```ts\n * let fileUrl = pathToFileURL(\"C:/Users/user/Documents/file.txt\");\n * // fileUrl = new URL(\"file:///C:/Users/user/Documents/file.txt\")\n *\n * fileUrl = pathToFileURL(new URL(\"C:/Users/user/Documents/file.txt\"));\n * // fileUrl = new URL(\"file:///C:/Users/user/Documents/file.txt\")\n * ```\n *\n * @param id - The file system path to convert.\n * @returns The resulting file URL as a URL object.\n */\nexport function pathToFileURL(id: string | URL): URL {\n  return _pathToFileURL(fileURLToPath(id));\n}\n\n/**\n * Converts a local file system path to a file URL string.\n *\n * @example\n * ```ts\n * let fileUrl = pathToFileURLString(\"C:/Users/user/Documents/file.txt\");\n * // fileUrl = \"file:///C:/Users/user/Documents/file.txt\"\n *\n * fileUrl = pathToFileURLString(new URL(\"C:/Users/user/Documents/file.txt\"));\n * // fileUrl = \"file:///C:/Users/user/Documents/file.txt\"\n * ```\n *\n * @param id - The file system path to convert.\n * @returns The resulting file URL as a string.\n */\nexport function pathToFileURLString(id: string | URL): string {\n  return pathToFileURL(id).toString();\n}\n"],"mappings":";;;;;;;;;AAkCA,SAAgB,qBAAqB,QAAQ,IAAI;AAC/C,KAAI,CAAC,MACH,QAAO;AAGT,QAAO,MAAM,MAAM,CAAC,QAAQ,2BAA0B,MAAK,EAAE,aAAa,CAAC;;;;;;;;AAS7E,SAAgB,YAAY,MAAe;AACzC,KAAI,CAAC,QAAQ,KAAK,WAAW,EAC3B,QAAO;AAIT,QAAO,qBAAqB,KAAK;CAEjC,MAAM,YAAY,KAAK,MAAM,UAAU;CACvC,MAAM,iBAAiB,eAAe,KAAK;CAC3C,MAAM,oBAAoB,KAAK,SAAS,IAAI;AAG5C,QAAO,gBAAgB,MAAM,CAAC,eAAe;AAE7C,KAAI,KAAK,WAAW,GAAG;AACrB,MAAI,eACF,QAAO;AAET,SAAO,oBAAoB,OAAO;;AAGpC,KAAI,kBACF,SAAQ;AAEV,KAAI,mBAAmB,KAAK,KAAK,CAC/B,SAAQ;AAGV,KAAI,WAAW;AACb,MAAI,CAAC,eACH,QAAO,OAAO;AAEhB,SAAO,KAAK;;AAGd,QAAO,CAAC,KAAK,WAAW,IAAI,IAC1B,kBACA,CAAC,mBAAmB,KAAK,KAAK,GAC5B,IAAI,SACJ;;;;;;;;;;;;;;;;;AAkBN,SAAgB,WAAW,MAAe;AACxC,KAAI,CAAC,QAAQ,KAAK,WAAW,EAC3B,QAAO;AAGT,QAAO,YAAY,KAAK;CAExB,IAAI,QAAQ;AAEZ,QAAO,GAAG,KAAK,WAAW,IAAI,GAAG,MAAM,KAAK,KACzC,MAAM,IAAI,CACV,QAAQ,KAAK,YAAY;AACxB,MAAI,CAAC,SAAS,MAAM,CAClB,QAAO;AAGT,MAAI,SAAS,QAAQ,SAAS,IAAI,EAAE;AAClC,WAAQ;AACR,UAAO;;AAGT,SAAO,OAAO,MAAM,IAAI,YAAY;IACnC,GAAG;;;;;;;;;AAUV,SAAgB,gBAAgB,MAAc,gBAAyB;CACrE,IAAI,MAAM;CACV,IAAI,oBAAoB;CACxB,IAAI,YAAY;CAChB,IAAI,OAAO;CACX,IAAI,OAAsB;AAC1B,MAAK,IAAI,QAAQ,GAAG,SAAS,KAAK,QAAQ,EAAE,OAAO;AACjD,MAAI,QAAQ,KAAK,OAEf,QAAO,KAAK;WACH,SAAS,IAClB;MAEA,QAAO;AAET,MAAI,SAAS,KAAK;AAChB,OAAI,cAAc,QAAQ,KAAK,SAAS,GAAG,YAEhC,SAAS,GAAG;AACrB,QACE,IAAI,SAAS,KACb,sBAAsB,KACtB,IAAI,IAAI,SAAS,OAAO,OACxB,IAAI,IAAI,SAAS,OAAO,KAExB;SAAI,IAAI,SAAS,GAAG;MAClB,MAAM,iBAAiB,IAAI,YAAY,IAAI;AAC3C,UAAI,mBAAmB,IAAI;AACzB,aAAM;AACN,2BAAoB;aACf;AACL,aAAM,IAAI,MAAM,GAAG,eAAe;AAClC,2BAAoB,IAAI,SAAS,IAAI,IAAI,YAAY,IAAI;;AAE3D,kBAAY;AACZ,aAAO;AACP;gBACS,IAAI,SAAS,GAAG;AACzB,YAAM;AACN,0BAAoB;AACpB,kBAAY;AACZ,aAAO;AACP;;;AAGJ,QAAI,gBAAgB;AAClB,YAAO,IAAI,SAAS,IAAI,QAAQ;AAChC,yBAAoB;;UAEjB;AACL,QAAI,IAAI,SAAS,EACf,QAAO,IAAI,KAAK,MAAM,YAAY,GAAG,MAAM;QAE3C,OAAM,KAAK,MAAM,YAAY,GAAG,MAAM;AAExC,wBAAoB,QAAQ,YAAY;;AAE1C,eAAY;AACZ,UAAO;aACE,SAAS,OAAO,SAAS,GAClC,GAAE;MAEF,QAAO;;AAGX,QAAO;;;;;;;;;AAUT,SAAgB,eAAe,MAAc,QAAMA,KAAY,EAAU;AACvE,KAAI,eAAe,KAAK,CACtB,QAAO;AAGT,QAAO,MAAM,gBAAgB,WAAW,MAAMC,MAAI,EAAE,KAAK,CAAC;;;;;;;;;AAU5D,SAAgB,eAAe,MAAc,QAAMD,KAAY,EAAU;AACvE,KAAI,CAAC,QAAQ,KAAK,WAAW,EAC3B,QAAO;AAGT,KAAI,eAAe,KAAK,CACtB,QAAO,MAAM,gBAAgB,MAAM,KAAK,CAAC;KAEzC,QAAO,MAAM,gBAAgB,UAAUC,OAAK,KAAK,EAAE,KAAK,CAAC;AAG3D,KAAI,KAAK,WAAW,KAAK,CACvB,QAAO,KAAK,MAAM,EAAE;AAGtB,QAAO;;;;;;;;AAST,SAAgB,kBAAkB,MAAsB;CACtD,MAAM,SAAS,YAAY,KAAK;AAEhC,QAAO,OAAO,SAAS,IAAI,GAAG,SAAS,GAAG,OAAO;;;;;;;;AASnD,SAAgB,qBAAqB,MAAsB;CACzD,MAAM,SAAS,YAAY,KAAK;AAEhC,QAAO,OAAO,SAAS,IAAI,GAAG,OAAO,MAAM,GAAG,GAAG,GAAG;;;;;;;;;;;;;;;;;AAkBtD,SAAgB,cAAc,IAA0B;AACtD,KAAI,OAAO,OAAO,YAAY,CAAC,GAAG,WAAW,UAAU,CACrD,QAAO,YAAY,GAAG;AAExB,QAAO,YAAYC,gBAAe,GAAG,CAAC;;;;;;;;;;;;;;;;;AAkBxC,SAAgB,cAAc,IAAuB;AACnD,QAAOC,gBAAe,cAAc,GAAG,CAAC;;;;;;;;;;;;;;;;;AAkB1C,SAAgB,oBAAoB,IAA0B;AAC5D,QAAO,cAAc,GAAG,CAAC,UAAU"}