0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-10-29 08:58:01 -04:00

feat(std/path): Add toFileUrl() (#7971)

This commit is contained in:
Nayeem Rahman 2020-10-19 13:36:53 +01:00 committed by GitHub
parent 342b151b5d
commit 19b918d112
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 5 deletions

View file

@ -24,6 +24,7 @@ export const {
relative,
resolve,
sep,
toFileUrl,
toNamespacedPath,
} = path;

View file

@ -440,3 +440,16 @@ export function fromFileUrl(url: string | URL): string {
url.pathname.replace(/%(?![0-9A-Fa-f]{2})/g, "%25"),
);
}
/** Converts a path string to a file URL.
*
* toFileUrl("/home/foo"); // new URL("file:///home/foo")
*/
export function toFileUrl(path: string): URL {
if (!isAbsolute(path)) {
throw new TypeError("Must be an absolute path.");
}
const url = new URL("file:///");
url.pathname = path.replace(/%/g, "%25").replace(/\\/g, "%5C");
return url;
}

View file

@ -0,0 +1,49 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { posix, win32 } from "./mod.ts";
import { assertEquals, assertThrows } from "../testing/asserts.ts";
Deno.test("[path] toFileUrl", function () {
assertEquals(posix.toFileUrl("/home/foo").href, "file:///home/foo");
assertEquals(posix.toFileUrl("/home/ ").href, "file:///home/%20");
assertEquals(posix.toFileUrl("/home/%20").href, "file:///home/%2520");
assertEquals(posix.toFileUrl("/home\\foo").href, "file:///home%5Cfoo");
assertThrows(
() => posix.toFileUrl("foo").href,
TypeError,
"Must be an absolute path.",
);
assertThrows(
() => posix.toFileUrl("C:/"),
TypeError,
"Must be an absolute path.",
);
assertEquals(
posix.toFileUrl("//localhost/home/foo").href,
"file:////localhost/home/foo",
);
assertEquals(posix.toFileUrl("//localhost/").href, "file:////localhost/");
assertEquals(posix.toFileUrl("//:/home/foo").href, "file:////:/home/foo");
});
Deno.test("[path] toFileUrl (win32)", function () {
assertEquals(win32.toFileUrl("/home/foo").href, "file:///home/foo");
assertEquals(win32.toFileUrl("/home/ ").href, "file:///home/%20");
assertEquals(win32.toFileUrl("/home/%20").href, "file:///home/%2520");
assertEquals(win32.toFileUrl("/home\\foo").href, "file:///home/foo");
assertThrows(
() => win32.toFileUrl("foo").href,
TypeError,
"Must be an absolute path.",
);
assertEquals(win32.toFileUrl("C:/").href, "file:///C:/");
assertEquals(
win32.toFileUrl("//localhost/home/foo").href,
"file://localhost/home/foo",
);
assertEquals(win32.toFileUrl("//localhost/").href, "file:////localhost/");
assertThrows(
() => win32.toFileUrl("//:/home/foo").href,
TypeError,
"Invalid hostname.",
);
});

View file

@ -917,11 +917,8 @@ export function fromFileUrl(url: string | URL): string {
throw new TypeError("Must be a file URL.");
}
let path = decodeURIComponent(
url.pathname
.replace(/^\/*([A-Za-z]:)(\/|$)/, "$1/")
.replace(/\//g, "\\")
.replace(/%(?![0-9A-Fa-f]{2})/g, "%25"),
);
url.pathname.replace(/\//g, "\\").replace(/%(?![0-9A-Fa-f]{2})/g, "%25"),
).replace(/^\\*([A-Za-z]:)(\\|$)/, "$1\\");
if (url.hostname != "") {
// Note: The `URL` implementation guarantees that the drive letter and
// hostname are mutually exclusive. Otherwise it would not have been valid
@ -930,3 +927,27 @@ export function fromFileUrl(url: string | URL): string {
}
return path;
}
/** Converts a path string to a file URL.
*
* toFileUrl("\\home\\foo"); // new URL("file:///home/foo")
* toFileUrl("C:\\Users\\foo"); // new URL("file:///C:/Users/foo")
* toFileUrl("\\\\localhost\\home\\foo"); // new URL("file://localhost/home/foo")
*/
export function toFileUrl(path: string): URL {
if (!isAbsolute(path)) {
throw new TypeError("Must be an absolute path.");
}
const [, hostname, pathname] = path.match(
/^(?:[/\\]{2}([^/\\]+)(?=[/\\][^/\\]))?(.*)/,
)!;
const url = new URL("file:///");
url.pathname = pathname.replace(/%/g, "%25");
if (hostname != null) {
url.hostname = hostname;
if (!url.hostname) {
throw new TypeError("Invalid hostname.");
}
}
return url;
}