Skip to content

Commit

Permalink
feat(path/unstable): support file URL arg in normalize() (#5902)
Browse files Browse the repository at this point in the history
  • Loading branch information
kt3k authored Sep 4, 2024
1 parent 7e26160 commit 6aaf191
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 14 deletions.
30 changes: 29 additions & 1 deletion path/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,34 @@ import { normalize as windowsNormalize } from "./windows/normalize.ts";
* @param path Path to be normalized
* @returns The normalized path.
*/
export function normalize(path: string): string {
export function normalize(path: string): string;
/**
* Normalize the path, resolving `'..'` and `'.'` segments.
*
* @experimental **UNSTABLE**: New API, yet to be vetted.
*
* Note: Resolving these segments does not necessarily mean that all will be
* eliminated. A `'..'` at the top-level will be preserved, and an empty path is
* canonically `'.'`.
*
* @example Usage
* ```ts
* import { normalize } from "@std/path/normalize";
* import { assertEquals } from "@std/assert";
*
* if (Deno.build.os === "windows") {
* assertEquals(normalize("C:\\foo\\bar\\..\\baz\\quux"), "C:\\foo\\baz\\quux");
* assertEquals(normalize(new URL("file:///C:/foo/bar/../baz/quux")), "C:\\foo\\baz\\quux");
* } else {
* assertEquals(normalize("/foo/bar/../baz/quux"), "/foo/baz/quux");
* assertEquals(normalize(new URL("file:///foo/bar/../baz/quux")), "/foo/baz/quux");
* }
* ```
*
* @param path Path to be normalized. Path can be a string or a file URL object.
* @returns The normalized path.
*/
export function normalize(path: string | URL): string;
export function normalize(path: string | URL): string {
return isWindows ? windowsNormalize(path) : posixNormalize(path);
}
15 changes: 15 additions & 0 deletions path/normalize_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,24 @@ Deno.test(`normalize() returns "." if input is empty`, function () {
assertEquals(windows.normalize(""), ".");
});

Deno.test("posix.normalize() normalizes posix specific paths", () => {
assertEquals(
posix.normalize("/foo/bar//baz/asdf/quux/.."),
"/foo/bar/baz/asdf",
);
assertEquals(
posix.normalize(new URL("file:///foo/bar//baz/asdf/quux/..")),
"/foo/bar/baz/asdf/",
);
});

Deno.test("windows.normalize() normalizes windows specific paths", () => {
assertEquals(
windows.normalize("//server/share/dir/file.ext"),
"\\\\server\\share\\dir\\file.ext",
);
assertEquals(
windows.normalize(new URL("file:///C:/foo/bar/../baz/quux")),
"C:\\foo\\baz\\quux",
);
});
29 changes: 17 additions & 12 deletions path/posix/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { assertArg } from "../_common/normalize.ts";
import { normalizeString } from "../_common/normalize_string.ts";
import { isPosixPathSeparator } from "./_util.ts";
import { fromFileUrl } from "./from_file_url.ts";

/**
* Normalize the `path`, resolving `'..'` and `'.'` segments.
Expand All @@ -19,28 +20,32 @@ import { isPosixPathSeparator } from "./_util.ts";
* assertEquals(path, "/foo/bar/baz/asdf");
* ```
*
* @example Working with URLs
* @param path The path to normalize.
* @returns The normalized path.
*/
export function normalize(path: string): string;
/**
* Normalize the `path`, resolving `'..'` and `'.'` segments.
* Note that resolving these segments does not necessarily mean that all will be eliminated.
* A `'..'` at the top-level will be preserved, and an empty path is canonically `'.'`.
*
* Note: This function will remove the double slashes from a URL's scheme.
* Hence, do not pass a full URL to this function. Instead, pass the pathname of
* the URL.
* @experimental **UNSTABLE**: New API, yet to be vetted.
*
* @example Usage
* ```ts
* import { normalize } from "@std/path/posix/normalize";
* import { assertEquals } from "@std/assert";
*
* const url = new URL("https://deno.land");
* url.pathname = normalize("//std//assert//.//mod.ts");
* assertEquals(url.href, "https://deno.land/std/assert/mod.ts");
*
* url.pathname = normalize("std/assert/../async/retry.ts");
* assertEquals(url.href, "https://deno.land/std/async/retry.ts");
* assertEquals(normalize("/foo/bar//baz/asdf/quux/.."), "/foo/bar/baz/asdf");
* assertEquals(normalize(new URL("file:///foo/bar//baz/asdf/quux/..")), "/foo/bar/baz/asdf/");
* ```
*
* @param path The path to normalize.
* @param path The path to normalize. Path can be a string or a file URL object.
* @returns The normalized path.
*/
export function normalize(path: string): string {
export function normalize(path: string | URL): string;
export function normalize(path: string | URL): string {
path = path instanceof URL ? fromFileUrl(path) : path;
assertArg(path);

const isAbsolute = isPosixPathSeparator(path.charCodeAt(0));
Expand Down
25 changes: 24 additions & 1 deletion path/windows/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { assertArg } from "../_common/normalize.ts";
import { CHAR_COLON } from "../_common/constants.ts";
import { normalizeString } from "../_common/normalize_string.ts";
import { isPathSeparator, isWindowsDeviceRoot } from "./_util.ts";
import { fromFileUrl } from "./from_file_url.ts";

/**
* Normalize the `path`, resolving `'..'` and `'.'` segments.
Expand All @@ -23,7 +24,29 @@ import { isPathSeparator, isWindowsDeviceRoot } from "./_util.ts";
* @param path The path to normalize
* @returns The normalized path
*/
export function normalize(path: string): string {
export function normalize(path: string): string;
/**
* Normalize the `path`, resolving `'..'` and `'.'` segments.
* Note that resolving these segments does not necessarily mean that all will be eliminated.
* A `'..'` at the top-level will be preserved, and an empty path is canonically `'.'`.
*
* @experimental **UNSTABLE**: New API, yet to be vetted.
*
* @example Usage
* ```ts
* import { normalize } from "@std/path/windows/normalize";
* import { assertEquals } from "@std/assert";
*
* assertEquals(normalize("C:\\foo\\..\\bar"), "C:\\bar");
* assertEquals(normalize(new URL("file:///C:/foo/../bar")), "C:\\bar");
* ```
*
* @param path The path to normalize. Path can be a string or a file URL object.
* @returns The normalized path
*/
export function normalize(path: string | URL): string;
export function normalize(path: string | URL): string {
path = path instanceof URL ? fromFileUrl(path) : path;
assertArg(path);

const len = path.length;
Expand Down

0 comments on commit 6aaf191

Please sign in to comment.