UNPKG

@stryke/path

Version:

A package containing various utilities that expand the functionality of NodeJs's built-in `path` module

226 lines (224 loc) 7.41 kB
import { cwd } from "./cwd.mjs"; import { DRIVE_LETTER_REGEX, DRIVE_LETTER_START_REGEX, UNC_REGEX } from "./regex.mjs"; import { isAbsolutePath } from "./is-type.mjs"; import { slash } from "./slash.mjs"; import { joinPaths } from "./join-paths.mjs"; import { appendPath } from "./append.mjs"; import { fileURLToPath as fileURLToPath$1, pathToFileURL as pathToFileURL$1 } from "node:url"; //#region src/correct-path.ts function normalizeWindowsPath(input = "") { if (!input) return input; return slash(input).replace(DRIVE_LETTER_START_REGEX, (r) => r.toUpperCase()); } /** * Corrects/normalized a file path. * * @param path - The path to correct. * @returns The corrected path. */ function correctPath(path) { if (!path || path.length === 0) return "."; path = normalizeWindowsPath(path); const isUNCPath = path.match(UNC_REGEX); const isPathAbsolute = isAbsolutePath(path); const trailingSeparator = path.endsWith("/"); path = normalizeString(path, !isPathAbsolute); if (path.length === 0) { if (isPathAbsolute) return "/"; return trailingSeparator ? "./" : "."; } if (trailingSeparator) path += "/"; if (DRIVE_LETTER_REGEX.test(path)) path += "/"; if (isUNCPath) { if (!isPathAbsolute) return `//./${path}`; return `//${path}`; } return !path.startsWith("/") && isPathAbsolute && !DRIVE_LETTER_REGEX.test(path) ? `/${path}` : path; } /** * Remove any star tokens (*) from the end of the file path * * @example * stripStars("src/**") // returns "src" * stripStars("src/*") // returns "src" * stripStars("src/**\/*") // returns "src" * stripStars("src/**\/*.txt") // returns "src" * stripStars("src/**\/file.txt") // returns "src" * stripStars("src/file.txt") // returns "src/file.txt" * stripStars("") // returns "." * * @param path - The path to correct. * @returns The corrected path. */ function stripStars(path) { if (!path || path.length === 0) return "."; path = correctPath(path); let found = false; return `${path.startsWith("/") ? "/" : ""}${path.split("/").reduce((ret, segment) => { if (!segment?.trim()) return ret; if (found || segment.includes("*")) { found = true; return ret; } return ret + (ret ? `/${segment}` : segment); }, "")}`; } /** * Resolves a string path, resolving '.' and '.' segments and allowing paths above the root. * * @param path - The path to normalize. * @param allowAboveRoot - Whether to allow the resulting path to be above the root directory. * @returns the normalize path string. */ function normalizeString(path, allowAboveRoot) { let res = ""; let lastSegmentLength = 0; let lastSlash = -1; let dots = 0; let char = null; for (let index = 0; index <= path.length; ++index) { if (index < path.length) char = path[index]; else if (char === "/") break; else char = "/"; if (char === "/") { if (lastSlash === index - 1 || dots === 1) {} else if (dots === 2) { if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") { if (res.length > 2) { const lastSlashIndex = res.lastIndexOf("/"); if (lastSlashIndex === -1) { res = ""; lastSegmentLength = 0; } else { res = res.slice(0, lastSlashIndex); lastSegmentLength = res.length - 1 - res.lastIndexOf("/"); } lastSlash = index; dots = 0; continue; } else if (res.length > 0) { res = ""; lastSegmentLength = 0; lastSlash = index; dots = 0; continue; } } if (allowAboveRoot) { res += res.length > 0 ? "/.." : ".."; lastSegmentLength = 2; } } else { if (res.length > 0) res += `/${path.slice(lastSlash + 1, index)}`; else res = path.slice(lastSlash + 1, index); lastSegmentLength = index - lastSlash - 1; } lastSlash = index; dots = 0; } else if (char === "." && dots !== -1) ++dots; else dots = -1; } return res; } /** * Converts a given path to an absolute path based on the current working directory. * * @param path - The path to convert to an absolute path. * @param cwd - The current working directory to use as the base path if the path is not absolute. * @returns The absolute path. */ function toAbsolutePath(path, cwd$1 = cwd()) { if (isAbsolutePath(path)) return path; return slash(normalizeString(appendPath(path, cwd$1), true)); } /** * Converts a given path to a relative path based on the current working directory. * * @param path - The path to convert to a relative path. * @param cwd - The current working directory to use as the base path if the path is not absolute. * @returns The relative path. */ function toRelativePath(path, cwd$2 = cwd()) { if (!path || path.length === 0) return "."; if (isAbsolutePath(path)) path = slash(normalizeString(path, true)); else path = slash(normalizeString(joinPaths(cwd$2, path), true)); if (path.startsWith("./")) return path.slice(2); return path; } /** * Adds a trailing slash to a path if it doesn't already have one. * * @param path - The path to modify. * @returns The modified path with a trailing slash. */ function withTrailingSlash(path) { const result = correctPath(path); return result.endsWith("/") ? result : `${result}/`; } /** * Removes a trailing slash from a path if it has one. * * @param path - The path to modify. * @returns The modified path without a trailing slash. */ function withoutTrailingSlash(path) { const result = correctPath(path); return result.endsWith("/") ? result.slice(0, -1) : result; } /** * Converts a file URL to a local file system path with normalized slashes. * * @example * ```ts * let filePath = fileURLToPath("file:///C:/Users/user/Documents/file.txt"); * // filePath = "C:/Users/user/Documents/file.txt" * * filePath = fileURLToPath(new URL("file:///C:/Users/user/Documents/file.txt")); * // filePath = "C:/Users/user/Documents/file.txt" * ``` * * @param id - The file URL or local path to convert. * @returns A normalized file system path. */ function fileURLToPath(id) { if (typeof id === "string" && !id.startsWith("file://")) return correctPath(id); return correctPath(fileURLToPath$1(id)); } /** * Converts a local file system path to a file URL. * * @example * ```ts * let fileUrl = pathToFileURL("C:/Users/user/Documents/file.txt"); * // fileUrl = new URL("file:///C:/Users/user/Documents/file.txt") * * fileUrl = pathToFileURL(new URL("C:/Users/user/Documents/file.txt")); * // fileUrl = new URL("file:///C:/Users/user/Documents/file.txt") * ``` * * @param id - The file system path to convert. * @returns The resulting file URL as a URL object. */ function pathToFileURL(id) { return pathToFileURL$1(fileURLToPath(id)); } /** * Converts a local file system path to a file URL string. * * @example * ```ts * let fileUrl = pathToFileURLString("C:/Users/user/Documents/file.txt"); * // fileUrl = "file:///C:/Users/user/Documents/file.txt" * * fileUrl = pathToFileURLString(new URL("C:/Users/user/Documents/file.txt")); * // fileUrl = "file:///C:/Users/user/Documents/file.txt" * ``` * * @param id - The file system path to convert. * @returns The resulting file URL as a string. */ function pathToFileURLString(id) { return pathToFileURL(id).toString(); } //#endregion export { correctPath, fileURLToPath, normalizeString, normalizeWindowsPath, pathToFileURL, pathToFileURLString, stripStars, toAbsolutePath, toRelativePath, withTrailingSlash, withoutTrailingSlash }; //# sourceMappingURL=correct-path.mjs.map