mirror of
https://github.com/denoland/deno.git
synced 2024-11-26 16:09:27 -05:00
feat(std/node): first pass at url module (#4700)
This commit is contained in:
parent
7630326b4c
commit
22da75b8e5
3 changed files with 196 additions and 0 deletions
|
@ -39,3 +39,8 @@ export function intoCallbackAPIWithIntercept<T1, T2>(
|
|||
.then((value) => cb && cb(null, interceptor(value)))
|
||||
.catch((err) => cb && cb(err, null));
|
||||
}
|
||||
|
||||
export function spliceOne(list: string[], index: number): void {
|
||||
for (; index + 1 < list.length; index++) list[index] = list[index + 1];
|
||||
list.pop();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ interface ParseOptions {
|
|||
decodeURIComponent?: (string: string) => string;
|
||||
maxKeys?: number;
|
||||
}
|
||||
export const hexTable = new Array(256);
|
||||
for (let i = 0; i < 256; ++i)
|
||||
hexTable[i] = "%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase();
|
||||
|
||||
export function parse(
|
||||
str: string,
|
||||
|
@ -43,6 +46,67 @@ interface StringifyOptions {
|
|||
encodeURIComponent?: (string: string) => string;
|
||||
}
|
||||
|
||||
export function encodeStr(
|
||||
str: string,
|
||||
noEscapeTable: number[],
|
||||
hexTable: string[]
|
||||
): string {
|
||||
const len = str.length;
|
||||
if (len === 0) return "";
|
||||
|
||||
let out = "";
|
||||
let lastPos = 0;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
let c = str.charCodeAt(i);
|
||||
// ASCII
|
||||
if (c < 0x80) {
|
||||
if (noEscapeTable[c] === 1) continue;
|
||||
if (lastPos < i) out += str.slice(lastPos, i);
|
||||
lastPos = i + 1;
|
||||
out += hexTable[c];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastPos < i) out += str.slice(lastPos, i);
|
||||
|
||||
// Multi-byte characters ...
|
||||
if (c < 0x800) {
|
||||
lastPos = i + 1;
|
||||
out += hexTable[0xc0 | (c >> 6)] + hexTable[0x80 | (c & 0x3f)];
|
||||
continue;
|
||||
}
|
||||
if (c < 0xd800 || c >= 0xe000) {
|
||||
lastPos = i + 1;
|
||||
out +=
|
||||
hexTable[0xe0 | (c >> 12)] +
|
||||
hexTable[0x80 | ((c >> 6) & 0x3f)] +
|
||||
hexTable[0x80 | (c & 0x3f)];
|
||||
continue;
|
||||
}
|
||||
// Surrogate pair
|
||||
++i;
|
||||
|
||||
// This branch should never happen because all URLSearchParams entries
|
||||
// should already be converted to USVString. But, included for
|
||||
// completion's sake anyway.
|
||||
if (i >= len) throw new Deno.errors.InvalidData("invalid URI");
|
||||
|
||||
const c2 = str.charCodeAt(i) & 0x3ff;
|
||||
|
||||
lastPos = i + 1;
|
||||
c = 0x10000 + (((c & 0x3ff) << 10) | c2);
|
||||
out +=
|
||||
hexTable[0xf0 | (c >> 18)] +
|
||||
hexTable[0x80 | ((c >> 12) & 0x3f)] +
|
||||
hexTable[0x80 | ((c >> 6) & 0x3f)] +
|
||||
hexTable[0x80 | (c & 0x3f)];
|
||||
}
|
||||
if (lastPos === 0) return str;
|
||||
if (lastPos < len) return out + str.slice(lastPos);
|
||||
return out;
|
||||
}
|
||||
|
||||
export function stringify(
|
||||
obj: object,
|
||||
sep = "&",
|
||||
|
|
127
std/node/url.ts
Normal file
127
std/node/url.ts
Normal file
|
@ -0,0 +1,127 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import {
|
||||
CHAR_LOWERCASE_A,
|
||||
CHAR_LOWERCASE_Z,
|
||||
CHAR_FORWARD_SLASH,
|
||||
CHAR_BACKWARD_SLASH,
|
||||
} from "../path/_constants.ts";
|
||||
import * as path from "./path.ts";
|
||||
|
||||
const isWindows = Deno.build.os === "windows";
|
||||
|
||||
const forwardSlashRegEx = /\//g;
|
||||
const percentRegEx = /%/g;
|
||||
const backslashRegEx = /\\/g;
|
||||
const newlineRegEx = /\n/g;
|
||||
const carriageReturnRegEx = /\r/g;
|
||||
const tabRegEx = /\t/g;
|
||||
|
||||
export function fileURLToPath(path: string | URL): string {
|
||||
if (typeof path === "string") path = new URL(path);
|
||||
else if (!(path instanceof URL))
|
||||
throw new Deno.errors.InvalidData(
|
||||
"invalid argument path , must be a string or URL"
|
||||
);
|
||||
if (path.protocol !== "file:")
|
||||
throw new Deno.errors.InvalidData("invalid url scheme");
|
||||
return isWindows ? getPathFromURLWin(path) : getPathFromURLPosix(path);
|
||||
}
|
||||
|
||||
function getPathFromURLWin(url: URL): string {
|
||||
const hostname = url.hostname;
|
||||
let pathname = url.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === "%") {
|
||||
const third = pathname.codePointAt(n + 2) || 0x20;
|
||||
if (
|
||||
(pathname[n + 1] === "2" && third === 102) || // 2f 2F /
|
||||
(pathname[n + 1] === "5" && third === 99)
|
||||
) {
|
||||
// 5c 5C \
|
||||
throw new Deno.errors.InvalidData(
|
||||
"must not include encoded \\ or / characters"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pathname = pathname.replace(forwardSlashRegEx, "\\");
|
||||
pathname = decodeURIComponent(pathname);
|
||||
if (hostname !== "") {
|
||||
//TODO add support for punycode encodings
|
||||
return `\\\\${hostname}${pathname}`;
|
||||
} else {
|
||||
// Otherwise, it's a local path that requires a drive letter
|
||||
const letter = pathname.codePointAt(1) || 0x20;
|
||||
const sep = pathname[2];
|
||||
if (
|
||||
letter < CHAR_LOWERCASE_A ||
|
||||
letter > CHAR_LOWERCASE_Z || // a..z A..Z
|
||||
sep !== ":"
|
||||
) {
|
||||
throw new Deno.errors.InvalidData("file url path must be absolute");
|
||||
}
|
||||
return pathname.slice(1);
|
||||
}
|
||||
}
|
||||
|
||||
function getPathFromURLPosix(url: URL): string {
|
||||
if (url.hostname !== "") {
|
||||
throw new Deno.errors.InvalidData("invalid file url hostname");
|
||||
}
|
||||
const pathname = url.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === "%") {
|
||||
const third = pathname.codePointAt(n + 2) || 0x20;
|
||||
if (pathname[n + 1] === "2" && third === 102) {
|
||||
throw new Deno.errors.InvalidData(
|
||||
"must not include encoded / characters"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return decodeURIComponent(pathname);
|
||||
}
|
||||
|
||||
export function pathToFileURL(filepath: string): URL {
|
||||
let resolved = path.resolve(filepath);
|
||||
// path.resolve strips trailing slashes so we must add them back
|
||||
const filePathLast = filepath.charCodeAt(filepath.length - 1);
|
||||
if (
|
||||
(filePathLast === CHAR_FORWARD_SLASH ||
|
||||
(isWindows && filePathLast === CHAR_BACKWARD_SLASH)) &&
|
||||
resolved[resolved.length - 1] !== path.sep
|
||||
)
|
||||
resolved += "/";
|
||||
const outURL = new URL("file://");
|
||||
if (resolved.includes("%")) resolved = resolved.replace(percentRegEx, "%25");
|
||||
// In posix, "/" is a valid character in paths
|
||||
if (!isWindows && resolved.includes("\\"))
|
||||
resolved = resolved.replace(backslashRegEx, "%5C");
|
||||
if (resolved.includes("\n")) resolved = resolved.replace(newlineRegEx, "%0A");
|
||||
if (resolved.includes("\r"))
|
||||
resolved = resolved.replace(carriageReturnRegEx, "%0D");
|
||||
if (resolved.includes("\t")) resolved = resolved.replace(tabRegEx, "%09");
|
||||
outURL.pathname = resolved;
|
||||
return outURL;
|
||||
}
|
Loading…
Reference in a new issue