@rainbowatcher/path-extra
Advanced tools
+4
-1
| { | ||
| "name": "@rainbowatcher/path-extra", | ||
| "version": "0.2.0", | ||
| "version": "0.2.1", | ||
| "description": "path extra utils", | ||
@@ -12,2 +12,5 @@ "author": "rainbowatcher <rainbow-w@outlook.com>", | ||
| "types": "dist/index.d.ts", | ||
| "files": [ | ||
| "dist" | ||
| ], | ||
| "scripts": { | ||
@@ -14,0 +17,0 @@ "build": "tsup" |
| /** | ||
| * A file starting with \\?\ | ||
| * @see https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#win32-file-namespaces | ||
| */ | ||
| export const WIN32_FILE_NS = "\\\\?\\" | ||
| /** | ||
| * A file starting with \\.\ | ||
| * @see https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#win32-file-namespaces | ||
| */ | ||
| export const WIN32_DEVICE_NS = "\\\\.\\" |
| import path from "node:path" | ||
| import { describe, expect, it } from "vitest" | ||
| import { normalize, toAbsolute } from "./index" | ||
| import { WIN32_DEVICE_NS, WIN32_FILE_NS } from "./constants" | ||
| describe("toAbsolute", () => { | ||
| const cwd = "/current/working/directory" | ||
| it("should return absolute path when absolute path is given", () => { | ||
| const inputPath = "/absolute/path" | ||
| const result = toAbsolute(inputPath) | ||
| expect(result).toBe(inputPath) | ||
| }) | ||
| it("should return absolute path when relative path is given", () => { | ||
| const inputPath = "relative/path" | ||
| const cwd = "/current/working/directory" | ||
| const result = toAbsolute(inputPath, cwd) | ||
| expect(result).toBe("/current/working/directory/relative/path") | ||
| }) | ||
| it("should return current working directory when cwd is given", () => { | ||
| const cwd = "/current/working/directory" | ||
| const result = toAbsolute("", cwd) | ||
| expect(result).toBe(cwd) | ||
| }) | ||
| it("should throw error when empty string is given", () => { | ||
| const abs = toAbsolute("", cwd) | ||
| expect(abs).toBe(cwd) | ||
| }) | ||
| it("should throw error when undefined is given", () => { | ||
| // @ts-expect-error type miss match | ||
| expect(() => toAbsolute(undefined)).toThrowErrorMatchingInlineSnapshot(`[TypeError: The "path" argument must be of type string. Received undefined]`) | ||
| }) | ||
| it("windows relative path", () => { | ||
| const cwd = String.raw`C:\current\working\directory` | ||
| const result = toAbsolute("relative/path", cwd) | ||
| expect(result).toBe(String.raw`C:/current/working/directory/relative/path`) | ||
| }) | ||
| it("windows absolute path", () => { | ||
| const cwd = String.raw`C:\current\working\directory` | ||
| const result = toAbsolute(String.raw`C:\current\working\directory`, cwd) | ||
| expect(result).toBe(String.raw`C:/current/working/directory`) | ||
| }) | ||
| }) | ||
| describe("normalize", () => { | ||
| it("should return empty string for empty input", () => { | ||
| expect(normalize("")).toBe("") | ||
| }) | ||
| it("should return posix sep for posix root directory", () => { | ||
| expect(normalize(path.posix.sep)).toBe(path.posix.sep) | ||
| }) | ||
| it("should return posix sep for win32 root directory", () => { | ||
| expect(normalize(path.win32.sep)).toBe(path.posix.sep) | ||
| }) | ||
| it("should handle win32 Namespaced paths", () => { | ||
| expect(normalize(`${WIN32_FILE_NS}path/to/file`)).toBe("//?/path/to/file") | ||
| expect(normalize(`${WIN32_DEVICE_NS}path/to/file`)).toBe("//./path/to/file") | ||
| }) | ||
| it("should remove trailing slash", () => { | ||
| expect(normalize("path/to/directory/")).toBe("path/to/directory") | ||
| }) | ||
| it("should replace multiple slashes with single slash", () => { | ||
| expect(normalize("path//to/directory")).toBe("path/to/directory") | ||
| expect(normalize(String.raw`path\\to\directory`)).toBe("path/to/directory") | ||
| }) | ||
| }) |
-57
| import path from "node:path" | ||
| import process from "node:process" | ||
| import { WIN32_DEVICE_NS, WIN32_FILE_NS } from "./constants" | ||
| /** | ||
| * Returns the absolute path of the given input path. | ||
| * | ||
| * @param inputPath - the path to be converted to absolute | ||
| * @param cwd - the current working directory | ||
| * @return the absolute path | ||
| */ | ||
| export function toAbsolute(inputPath: string, cwd = process.cwd()) { | ||
| if (process.platform !== "win32" && /^[a-z]:/i.test(inputPath?.slice(0, 2))) { | ||
| return normalize(inputPath) | ||
| } | ||
| const absolutePath = path.isAbsolute(inputPath) ? inputPath : path.join(cwd, inputPath) | ||
| return normalize(absolutePath) | ||
| } | ||
| /** | ||
| * Normalizes a given file path to a consistent format. | ||
| * | ||
| * @example | ||
| * ```js | ||
| * normalize("C:\\current\\working\\directory") | ||
| * // "C:/current/working/directory" | ||
| * normalize("/current\\working//directory") | ||
| * // "/current/working/directory" | ||
| * ``` | ||
| * | ||
| * ref: <https://github.com/lint-staged/lint-staged/blob/master/lib/normalizePath.js> | ||
| * @param inputPath - the path to be normalized | ||
| * @return the normalized path | ||
| */ | ||
| export function normalize(inputPath: string) { | ||
| if (!inputPath) return inputPath | ||
| if (inputPath === path.posix.sep || inputPath === path.win32.sep) { | ||
| return path.posix.sep | ||
| } | ||
| let normalized = inputPath.replaceAll(/[/\\]+/g, "/") | ||
| /** Handle win32 Namespaced paths by changing e.g. \\.\ to //./ */ | ||
| if (inputPath.startsWith(WIN32_FILE_NS) || inputPath.startsWith(WIN32_DEVICE_NS)) { | ||
| normalized = normalized.replace(/^\/(\.|\?)/, "//$1") | ||
| } | ||
| /** Remove trailing slash */ | ||
| if (normalized.endsWith(path.posix.sep)) { | ||
| normalized = normalized.slice(0, -1) | ||
| } | ||
| return normalized | ||
| } |
| import { defineConfig } from "tsup" | ||
| export default defineConfig({ | ||
| clean: true, | ||
| dts: true, | ||
| entry: ["src/index.ts"], | ||
| format: ["esm"], | ||
| minify: true, | ||
| }) |
Trivial Package
Supply chain riskPackages less than 10 lines of code are easily copied into your own project and may not warrant the additional supply chain risk of an external dependency.
2689
-65.57%4
-50%2
-98.47%1
Infinity%