feat(path/unstable): support URL in first arg of join() (#5863)

Co-authored-by: Asher Gomez <ashersaupingomez@gmail.com>
This commit is contained in:
Yoshiya Hinosawa 2024-08-30 13:18:12 +09:00 committed by GitHub
parent 8782bdb699
commit 94a7e1b34b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 84 additions and 17 deletions

View File

@ -23,6 +23,26 @@ import { join as windowsJoin } from "./windows/join.ts";
* @param paths Paths to be joined and normalized.
* @returns The joined and normalized path.
*/
export function join(...paths: string[]): string {
return isWindows ? windowsJoin(...paths) : posixJoin(...paths);
export function join(...paths: string[]): string;
/**
* Join all given a sequence of `paths`, then normalizes the resulting path.
*
* @experimental **UNSTABLE**: New API, yet to be vetted.
*
* @example Usage
* ```ts
* import { join } from "@std/path/posix/join";
* import { assertEquals } from "@std/assert";
*
* const path = join(new URL("file:///foo"), "bar", "baz/asdf", "quux", "..");
* assertEquals(path, "/foo/bar/baz/asdf");
* ```
*
* @param path The path to join. This can be string or file URL.
* @param paths The paths to join.
* @returns The joined path.
*/
export function join(path?: URL | string, ...paths: string[]): string;
export function join(path?: URL | string, ...paths: string[]): string {
return isWindows ? windowsJoin(path, ...paths) : posixJoin(path, ...paths);
}

View File

@ -6,7 +6,9 @@ import { join } from "./join.ts";
const backslashRE = /\\/g;
const joinTests =
type TestCase = [string[] | [URL, ...string[]], string];
const joinTests: TestCase[] =
// arguments result
[
[[".", "x/b", "..", "/b/c.js"], "x/b/c.js"],
@ -56,10 +58,18 @@ const joinTests =
[["/", "", "/foo"], "/foo"],
[["", "/", "foo"], "/foo"],
[["", "/", "/foo"], "/foo"],
// URLs
[[new URL("file:///"), "x/b", "..", "/b/c.js"], "/x/b/c.js"],
[[new URL("file:///foo"), "../../../bar"], "/bar"],
[
[new URL("file:///foo"), "bar", "baz/asdf", "quux", ".."],
"/foo/bar/baz/asdf",
],
];
// Windows-specific join tests
const windowsJoinTests = [
const windowsJoinTests: TestCase[] = [
// arguments result
// UNC path expected
[["//foo/bar"], "\\\\foo\\bar\\"],
@ -106,11 +116,15 @@ const windowsJoinTests = [
[["c:.", "file"], "c:file"],
[["c:", "/"], "c:\\"],
[["c:", "file"], "c:\\file"],
// URLs
[[new URL("file:///c:")], "c:\\"],
[[new URL("file:///c:"), "file"], "c:\\file"],
[[new URL("file:///c:/"), "file"], "c:\\file"],
];
Deno.test("posix.join()", function () {
joinTests.forEach(function (p) {
const _p = p[0] as string[];
const _p = p[0];
const actual = posix.join.apply(null, _p);
assertEquals(actual, p[1]);
});
@ -118,12 +132,12 @@ Deno.test("posix.join()", function () {
Deno.test("windows.join()", function () {
joinTests.forEach(function (p) {
const _p = p[0] as string[];
const _p = p[0];
const actual = windows.join.apply(null, _p).replace(backslashRE, "/");
assertEquals(actual, p[1]);
});
windowsJoinTests.forEach(function (p) {
const _p = p[0] as string[];
const _p = p[0];
const actual = windows.join.apply(null, _p);
assertEquals(actual, p[1]);
});

View File

@ -3,6 +3,7 @@
import { assertPath } from "../_common/assert_path.ts";
import { normalize } from "./normalize.ts";
import { fromFileUrl } from "./from_file_url.ts";
/**
* Join all given a sequence of `paths`,then normalizes the resulting path.
@ -16,24 +17,33 @@ import { normalize } from "./normalize.ts";
* assertEquals(path, "/foo/bar/baz/asdf");
* ```
*
* @example Working with URLs
* @param paths The paths to join.
* @returns The joined path.
*/
export function join(...paths: string[]): string;
/**
* Join all given a sequence of `paths`, then normalizes the resulting path.
*
* @experimental **UNSTABLE**: New API, yet to be vetted.
*
* @example Usage
* ```ts
* import { join } from "@std/path/posix/join";
* import { assertEquals } from "@std/assert";
*
* const url = new URL("https://deno.land");
* url.pathname = join("std", "path", "mod.ts");
* assertEquals(url.href, "https://deno.land/std/path/mod.ts");
*
* url.pathname = join("//std", "path/", "/mod.ts");
* assertEquals(url.href, "https://deno.land/std/path/mod.ts");
* const path = join(new URL("file:///foo"), "bar", "baz/asdf", "quux", "..");
* assertEquals(path, "/foo/bar/baz/asdf");
* ```
*
* @param path The path to join. This can be string or file URL.
* @param paths The paths to join.
* @returns The joined path.
*/
export function join(...paths: string[]): string {
if (paths.length === 0) return ".";
export function join(path?: URL | string, ...paths: string[]): string;
export function join(path?: URL | string, ...paths: string[]): string {
if (path === undefined) return ".";
path = path instanceof URL ? fromFileUrl(path) : path;
paths = path ? [path, ...paths] : paths;
paths.forEach((path) => assertPath(path));
const joined = paths.filter((path) => path.length > 0).join("/");
return joined === "" ? "." : normalize(joined);

View File

@ -4,6 +4,7 @@
import { assertPath } from "../_common/assert_path.ts";
import { isPathSeparator } from "./_util.ts";
import { normalize } from "./normalize.ts";
import { fromFileUrl } from "./from_file_url.ts";
/**
* Join all given a sequence of `paths`,then normalizes the resulting path.
@ -20,7 +21,29 @@ import { normalize } from "./normalize.ts";
* @param paths The paths to join.
* @returns The joined path.
*/
export function join(...paths: string[]): string {
export function join(...paths: string[]): string;
/**
* Join all given a sequence of `paths`, then normalizes the resulting path.
*
* @experimental **UNSTABLE**: New API, yet to be vetted.
*
* @example Usage
* ```ts
* import { join } from "@std/path/windows/join";
* import { assertEquals } from "@std/assert";
*
* const joined = join(new URL("file:///C:/foo"), "bar", "baz\\..");
* assertEquals(joined, "C:\\foo\\bar");
* ```
*
* @param path The path to join. This can be string or file URL.
* @param paths The paths to join.
* @returns The joined path.
*/
export function join(path?: URL | string, ...paths: string[]): string;
export function join(path?: URL | string, ...paths: string[]): string {
path = path instanceof URL ? fromFileUrl(path) : path;
paths = path ? [path, ...paths] : paths;
paths.forEach((path) => assertPath(path));
paths = paths.filter((path) => path.length > 0);
if (paths.length === 0) return ".";