| |
| |
| function assertPath(path) { |
| if (typeof path !== "string") { |
| throw new TypeError(`Path must be a string, received "${JSON.stringify(path)}"`); |
| } |
| } |
|
|
| |
| |
| function stripSuffix(name, suffix) { |
| if (suffix.length >= name.length) { |
| return name; |
| } |
| const lenDiff = name.length - suffix.length; |
| for(let i = suffix.length - 1; i >= 0; --i){ |
| if (name.charCodeAt(lenDiff + i) !== suffix.charCodeAt(i)) { |
| return name; |
| } |
| } |
| return name.slice(0, -suffix.length); |
| } |
| function lastPathSegment(path, isSep, start = 0) { |
| let matchedNonSeparator = false; |
| let end = path.length; |
| for(let i = path.length - 1; i >= start; --i){ |
| if (isSep(path.charCodeAt(i))) { |
| if (matchedNonSeparator) { |
| start = i + 1; |
| break; |
| } |
| } else if (!matchedNonSeparator) { |
| matchedNonSeparator = true; |
| end = i + 1; |
| } |
| } |
| return path.slice(start, end); |
| } |
| function assertArgs$1(path, suffix) { |
| assertPath(path); |
| if (path.length === 0) return path; |
| if (typeof suffix !== "string") { |
| throw new TypeError(`Suffix must be a string, received "${JSON.stringify(suffix)}"`); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| const CHAR_UPPERCASE_A = 65; |
| const CHAR_LOWERCASE_A = 97; |
| const CHAR_UPPERCASE_Z = 90; |
| const CHAR_LOWERCASE_Z = 122; |
| |
| const CHAR_DOT = 46; |
| const CHAR_FORWARD_SLASH = 47; |
| const CHAR_BACKWARD_SLASH = 92; |
| const CHAR_COLON = 58; |
| const CHAR_QUESTION_MARK = 63; |
|
|
| |
| |
| |
| |
| function stripTrailingSeparators(segment, isSep) { |
| if (segment.length <= 1) { |
| return segment; |
| } |
| let end = segment.length; |
| for(let i = segment.length - 1; i > 0; i--){ |
| if (isSep(segment.charCodeAt(i))) { |
| end = i; |
| } else { |
| break; |
| } |
| } |
| return segment.slice(0, end); |
| } |
|
|
| |
| |
| |
| |
| function isPosixPathSeparator(code) { |
| return code === CHAR_FORWARD_SLASH; |
| } |
| function isPathSeparator(code) { |
| return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; |
| } |
| function isWindowsDeviceRoot(code) { |
| return code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z || code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function basename(path, suffix = "") { |
| assertArgs$1(path, suffix); |
| |
| |
| |
| let start = 0; |
| if (path.length >= 2) { |
| const drive = path.charCodeAt(0); |
| if (isWindowsDeviceRoot(drive)) { |
| if (path.charCodeAt(1) === CHAR_COLON) start = 2; |
| } |
| } |
| const lastSegment = lastPathSegment(path, isPathSeparator, start); |
| const strippedSegment = stripTrailingSeparators(lastSegment, isPathSeparator); |
| return suffix ? stripSuffix(strippedSegment, suffix) : strippedSegment; |
| } |
|
|
| |
| |
| |
| |
| const DELIMITER = ";"; |
| |
| |
| const SEPARATOR = "\\"; |
| |
| |
| const SEPARATOR_PATTERN = /[\\/]+/; |
|
|
| |
| |
| function assertArg$3(path) { |
| assertPath(path); |
| if (path.length === 0) return "."; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function dirname(path) { |
| assertArg$3(path); |
| const len = path.length; |
| let rootEnd = -1; |
| let end = -1; |
| let matchedSlash = true; |
| let offset = 0; |
| const code = path.charCodeAt(0); |
| |
| if (len > 1) { |
| if (isPathSeparator(code)) { |
| |
| rootEnd = offset = 1; |
| if (isPathSeparator(path.charCodeAt(1))) { |
| |
| let j = 2; |
| let last = j; |
| |
| for(; j < len; ++j){ |
| if (isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j < len && j !== last) { |
| |
| last = j; |
| |
| for(; j < len; ++j){ |
| if (!isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j < len && j !== last) { |
| |
| last = j; |
| |
| for(; j < len; ++j){ |
| if (isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j === len) { |
| |
| return path; |
| } |
| if (j !== last) { |
| |
| |
| |
| rootEnd = offset = j + 1; |
| } |
| } |
| } |
| } |
| } else if (isWindowsDeviceRoot(code)) { |
| |
| if (path.charCodeAt(1) === CHAR_COLON) { |
| rootEnd = offset = 2; |
| if (len > 2) { |
| if (isPathSeparator(path.charCodeAt(2))) rootEnd = offset = 3; |
| } |
| } |
| } |
| } else if (isPathSeparator(code)) { |
| |
| |
| return path; |
| } |
| for(let i = len - 1; i >= offset; --i){ |
| if (isPathSeparator(path.charCodeAt(i))) { |
| if (!matchedSlash) { |
| end = i; |
| break; |
| } |
| } else { |
| |
| matchedSlash = false; |
| } |
| } |
| if (end === -1) { |
| if (rootEnd === -1) return "."; |
| else end = rootEnd; |
| } |
| return stripTrailingSeparators(path.slice(0, end), isPosixPathSeparator); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function extname(path) { |
| assertPath(path); |
| let start = 0; |
| let startDot = -1; |
| let startPart = 0; |
| let end = -1; |
| let matchedSlash = true; |
| |
| |
| let preDotState = 0; |
| |
| |
| |
| if (path.length >= 2 && path.charCodeAt(1) === CHAR_COLON && isWindowsDeviceRoot(path.charCodeAt(0))) { |
| start = startPart = 2; |
| } |
| for(let i = path.length - 1; i >= start; --i){ |
| const code = path.charCodeAt(i); |
| if (isPathSeparator(code)) { |
| |
| |
| if (!matchedSlash) { |
| startPart = i + 1; |
| break; |
| } |
| continue; |
| } |
| if (end === -1) { |
| |
| |
| matchedSlash = false; |
| end = i + 1; |
| } |
| if (code === CHAR_DOT) { |
| |
| if (startDot === -1) startDot = i; |
| else if (preDotState !== 1) preDotState = 1; |
| } else if (startDot !== -1) { |
| |
| |
| preDotState = -1; |
| } |
| } |
| if (startDot === -1 || end === -1 || |
| preDotState === 0 || |
| preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { |
| return ""; |
| } |
| return path.slice(startDot, end); |
| } |
|
|
| |
| |
| function _format(sep, pathObject) { |
| const dir = pathObject.dir || pathObject.root; |
| const base = pathObject.base || (pathObject.name ?? "") + (pathObject.ext ?? ""); |
| if (!dir) return base; |
| if (base === sep) return dir; |
| if (dir === pathObject.root) return dir + base; |
| return dir + sep + base; |
| } |
| function assertArg$2(pathObject) { |
| if (pathObject === null || typeof pathObject !== "object") { |
| throw new TypeError(`The "pathObject" argument must be of type Object, received type "${typeof pathObject}"`); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function format(pathObject) { |
| assertArg$2(pathObject); |
| return _format("\\", pathObject); |
| } |
|
|
| |
| |
| function assertArg$1(url) { |
| url = url instanceof URL ? url : new URL(url); |
| if (url.protocol !== "file:") { |
| throw new TypeError(`URL must be a file URL: received "${url.protocol}"`); |
| } |
| return url; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function fromFileUrl(url) { |
| url = assertArg$1(url); |
| let path = decodeURIComponent(url.pathname.replace(/\//g, "\\").replace(/%(?![0-9A-Fa-f]{2})/g, "%25")).replace(/^\\*([A-Za-z]:)(\\|$)/, "$1\\"); |
| if (url.hostname !== "") { |
| |
| |
| |
| path = `\\\\${url.hostname}${path}`; |
| } |
| return path; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function isAbsolute(path) { |
| assertPath(path); |
| const len = path.length; |
| if (len === 0) return false; |
| const code = path.charCodeAt(0); |
| if (isPathSeparator(code)) { |
| return true; |
| } else if (isWindowsDeviceRoot(code)) { |
| |
| if (len > 2 && path.charCodeAt(1) === CHAR_COLON) { |
| if (isPathSeparator(path.charCodeAt(2))) return true; |
| } |
| } |
| return false; |
| } |
|
|
| |
| |
| function assertArg(path) { |
| assertPath(path); |
| if (path.length === 0) return "."; |
| } |
|
|
| |
| |
| |
| |
| |
| function normalizeString(path, allowAboveRoot, separator, isPathSeparator) { |
| let res = ""; |
| let lastSegmentLength = 0; |
| let lastSlash = -1; |
| let dots = 0; |
| let code; |
| for(let i = 0; i <= path.length; ++i){ |
| if (i < path.length) code = path.charCodeAt(i); |
| else if (isPathSeparator(code)) break; |
| else code = CHAR_FORWARD_SLASH; |
| if (isPathSeparator(code)) { |
| if (lastSlash === i - 1 || dots === 1) ; else if (lastSlash !== i - 1 && dots === 2) { |
| if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== CHAR_DOT || res.charCodeAt(res.length - 2) !== CHAR_DOT) { |
| if (res.length > 2) { |
| const lastSlashIndex = res.lastIndexOf(separator); |
| if (lastSlashIndex === -1) { |
| res = ""; |
| lastSegmentLength = 0; |
| } else { |
| res = res.slice(0, lastSlashIndex); |
| lastSegmentLength = res.length - 1 - res.lastIndexOf(separator); |
| } |
| lastSlash = i; |
| dots = 0; |
| continue; |
| } else if (res.length === 2 || res.length === 1) { |
| res = ""; |
| lastSegmentLength = 0; |
| lastSlash = i; |
| dots = 0; |
| continue; |
| } |
| } |
| if (allowAboveRoot) { |
| if (res.length > 0) res += `${separator}..`; |
| else res = ".."; |
| lastSegmentLength = 2; |
| } |
| } else { |
| if (res.length > 0) res += separator + path.slice(lastSlash + 1, i); |
| else res = path.slice(lastSlash + 1, i); |
| lastSegmentLength = i - lastSlash - 1; |
| } |
| lastSlash = i; |
| dots = 0; |
| } else if (code === CHAR_DOT && dots !== -1) { |
| ++dots; |
| } else { |
| dots = -1; |
| } |
| } |
| return res; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function normalize(path) { |
| assertArg(path); |
| const len = path.length; |
| let rootEnd = 0; |
| let device; |
| let isAbsolute = false; |
| const code = path.charCodeAt(0); |
| |
| if (len > 1) { |
| if (isPathSeparator(code)) { |
| |
| |
| |
| isAbsolute = true; |
| if (isPathSeparator(path.charCodeAt(1))) { |
| |
| let j = 2; |
| let last = j; |
| |
| for(; j < len; ++j){ |
| if (isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j < len && j !== last) { |
| const firstPart = path.slice(last, j); |
| |
| last = j; |
| |
| for(; j < len; ++j){ |
| if (!isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j < len && j !== last) { |
| |
| last = j; |
| |
| for(; j < len; ++j){ |
| if (isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j === len) { |
| |
| |
| |
| return `\\\\${firstPart}\\${path.slice(last)}\\`; |
| } else if (j !== last) { |
| |
| device = `\\\\${firstPart}\\${path.slice(last, j)}`; |
| rootEnd = j; |
| } |
| } |
| } |
| } else { |
| rootEnd = 1; |
| } |
| } else if (isWindowsDeviceRoot(code)) { |
| |
| if (path.charCodeAt(1) === CHAR_COLON) { |
| device = path.slice(0, 2); |
| rootEnd = 2; |
| if (len > 2) { |
| if (isPathSeparator(path.charCodeAt(2))) { |
| |
| |
| isAbsolute = true; |
| rootEnd = 3; |
| } |
| } |
| } |
| } |
| } else if (isPathSeparator(code)) { |
| |
| |
| return "\\"; |
| } |
| let tail; |
| if (rootEnd < len) { |
| tail = normalizeString(path.slice(rootEnd), !isAbsolute, "\\", isPathSeparator); |
| } else { |
| tail = ""; |
| } |
| if (tail.length === 0 && !isAbsolute) tail = "."; |
| if (tail.length > 0 && isPathSeparator(path.charCodeAt(len - 1))) { |
| tail += "\\"; |
| } |
| if (device === undefined) { |
| if (isAbsolute) { |
| if (tail.length > 0) return `\\${tail}`; |
| else return "\\"; |
| } |
| return tail; |
| } else if (isAbsolute) { |
| if (tail.length > 0) return `${device}\\${tail}`; |
| else return `${device}\\`; |
| } |
| return device + tail; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function join(...paths) { |
| paths.forEach((path)=>assertPath(path)); |
| paths = paths.filter((path)=>path.length > 0); |
| if (paths.length === 0) return "."; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| let needsReplace = true; |
| let slashCount = 0; |
| const firstPart = paths[0]; |
| if (isPathSeparator(firstPart.charCodeAt(0))) { |
| ++slashCount; |
| const firstLen = firstPart.length; |
| if (firstLen > 1) { |
| if (isPathSeparator(firstPart.charCodeAt(1))) { |
| ++slashCount; |
| if (firstLen > 2) { |
| if (isPathSeparator(firstPart.charCodeAt(2))) ++slashCount; |
| else { |
| |
| needsReplace = false; |
| } |
| } |
| } |
| } |
| } |
| let joined = paths.join("\\"); |
| if (needsReplace) { |
| |
| for(; slashCount < joined.length; ++slashCount){ |
| if (!isPathSeparator(joined.charCodeAt(slashCount))) break; |
| } |
| |
| if (slashCount >= 2) joined = `\\${joined.slice(slashCount)}`; |
| } |
| return normalize(joined); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function parse(path) { |
| assertPath(path); |
| const ret = { |
| root: "", |
| dir: "", |
| base: "", |
| ext: "", |
| name: "" |
| }; |
| const len = path.length; |
| if (len === 0) return ret; |
| let rootEnd = 0; |
| let code = path.charCodeAt(0); |
| |
| if (len > 1) { |
| if (isPathSeparator(code)) { |
| |
| rootEnd = 1; |
| if (isPathSeparator(path.charCodeAt(1))) { |
| |
| let j = 2; |
| let last = j; |
| |
| for(; j < len; ++j){ |
| if (isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j < len && j !== last) { |
| |
| last = j; |
| |
| for(; j < len; ++j){ |
| if (!isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j < len && j !== last) { |
| |
| last = j; |
| |
| for(; j < len; ++j){ |
| if (isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j === len) { |
| |
| rootEnd = j; |
| } else if (j !== last) { |
| |
| rootEnd = j + 1; |
| } |
| } |
| } |
| } |
| } else if (isWindowsDeviceRoot(code)) { |
| |
| if (path.charCodeAt(1) === CHAR_COLON) { |
| rootEnd = 2; |
| if (len > 2) { |
| if (isPathSeparator(path.charCodeAt(2))) { |
| if (len === 3) { |
| |
| |
| ret.root = ret.dir = path; |
| ret.base = "\\"; |
| return ret; |
| } |
| rootEnd = 3; |
| } |
| } else { |
| |
| |
| ret.root = ret.dir = path; |
| return ret; |
| } |
| } |
| } |
| } else if (isPathSeparator(code)) { |
| |
| |
| ret.root = ret.dir = path; |
| ret.base = "\\"; |
| return ret; |
| } |
| if (rootEnd > 0) ret.root = path.slice(0, rootEnd); |
| let startDot = -1; |
| let startPart = rootEnd; |
| let end = -1; |
| let matchedSlash = true; |
| let i = path.length - 1; |
| |
| |
| let preDotState = 0; |
| |
| for(; i >= rootEnd; --i){ |
| code = path.charCodeAt(i); |
| if (isPathSeparator(code)) { |
| |
| |
| if (!matchedSlash) { |
| startPart = i + 1; |
| break; |
| } |
| continue; |
| } |
| if (end === -1) { |
| |
| |
| matchedSlash = false; |
| end = i + 1; |
| } |
| if (code === CHAR_DOT) { |
| |
| if (startDot === -1) startDot = i; |
| else if (preDotState !== 1) preDotState = 1; |
| } else if (startDot !== -1) { |
| |
| |
| preDotState = -1; |
| } |
| } |
| if (startDot === -1 || end === -1 || |
| preDotState === 0 || |
| preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { |
| if (end !== -1) { |
| ret.base = ret.name = path.slice(startPart, end); |
| } |
| } else { |
| ret.name = path.slice(startPart, startDot); |
| ret.base = path.slice(startPart, end); |
| ret.ext = path.slice(startDot, end); |
| } |
| |
| ret.base = ret.base || "\\"; |
| |
| |
| |
| if (startPart > 0 && startPart !== rootEnd) { |
| ret.dir = path.slice(0, startPart - 1); |
| } else ret.dir = ret.root; |
| return ret; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function resolve(...pathSegments) { |
| let resolvedDevice = ""; |
| let resolvedTail = ""; |
| let resolvedAbsolute = false; |
| for(let i = pathSegments.length - 1; i >= -1; i--){ |
| let path; |
| |
| const { Deno } = globalThis; |
| if (i >= 0) { |
| path = pathSegments[i]; |
| } else if (!resolvedDevice) { |
| if (typeof Deno?.cwd !== "function") { |
| throw new TypeError("Resolved a drive-letter-less path without a current working directory (CWD)"); |
| } |
| path = Deno.cwd(); |
| } else { |
| if (typeof Deno?.env?.get !== "function" || typeof Deno?.cwd !== "function") { |
| throw new TypeError("Resolved a relative path without a current working directory (CWD)"); |
| } |
| path = Deno.cwd(); |
| |
| |
| if (path === undefined || path.slice(0, 3).toLowerCase() !== `${resolvedDevice.toLowerCase()}\\`) { |
| path = `${resolvedDevice}\\`; |
| } |
| } |
| assertPath(path); |
| const len = path.length; |
| |
| if (len === 0) continue; |
| let rootEnd = 0; |
| let device = ""; |
| let isAbsolute = false; |
| const code = path.charCodeAt(0); |
| |
| if (len > 1) { |
| if (isPathSeparator(code)) { |
| |
| |
| |
| isAbsolute = true; |
| if (isPathSeparator(path.charCodeAt(1))) { |
| |
| let j = 2; |
| let last = j; |
| |
| for(; j < len; ++j){ |
| if (isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j < len && j !== last) { |
| const firstPart = path.slice(last, j); |
| |
| last = j; |
| |
| for(; j < len; ++j){ |
| if (!isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j < len && j !== last) { |
| |
| last = j; |
| |
| for(; j < len; ++j){ |
| if (isPathSeparator(path.charCodeAt(j))) break; |
| } |
| if (j === len) { |
| |
| device = `\\\\${firstPart}\\${path.slice(last)}`; |
| rootEnd = j; |
| } else if (j !== last) { |
| |
| device = `\\\\${firstPart}\\${path.slice(last, j)}`; |
| rootEnd = j; |
| } |
| } |
| } |
| } else { |
| rootEnd = 1; |
| } |
| } else if (isWindowsDeviceRoot(code)) { |
| |
| if (path.charCodeAt(1) === CHAR_COLON) { |
| device = path.slice(0, 2); |
| rootEnd = 2; |
| if (len > 2) { |
| if (isPathSeparator(path.charCodeAt(2))) { |
| |
| |
| isAbsolute = true; |
| rootEnd = 3; |
| } |
| } |
| } |
| } |
| } else if (isPathSeparator(code)) { |
| |
| rootEnd = 1; |
| isAbsolute = true; |
| } |
| if (device.length > 0 && resolvedDevice.length > 0 && device.toLowerCase() !== resolvedDevice.toLowerCase()) { |
| continue; |
| } |
| if (resolvedDevice.length === 0 && device.length > 0) { |
| resolvedDevice = device; |
| } |
| if (!resolvedAbsolute) { |
| resolvedTail = `${path.slice(rootEnd)}\\${resolvedTail}`; |
| resolvedAbsolute = isAbsolute; |
| } |
| if (resolvedAbsolute && resolvedDevice.length > 0) break; |
| } |
| |
| |
| |
| |
| resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, "\\", isPathSeparator); |
| return resolvedDevice + (resolvedAbsolute ? "\\" : "") + resolvedTail || "."; |
| } |
|
|
| |
| |
| function assertArgs(from, to) { |
| assertPath(from); |
| assertPath(to); |
| if (from === to) return ""; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function relative(from, to) { |
| assertArgs(from, to); |
| const fromOrig = resolve(from); |
| const toOrig = resolve(to); |
| if (fromOrig === toOrig) return ""; |
| from = fromOrig.toLowerCase(); |
| to = toOrig.toLowerCase(); |
| if (from === to) return ""; |
| |
| let fromStart = 0; |
| let fromEnd = from.length; |
| for(; fromStart < fromEnd; ++fromStart){ |
| if (from.charCodeAt(fromStart) !== CHAR_BACKWARD_SLASH) break; |
| } |
| |
| for(; fromEnd - 1 > fromStart; --fromEnd){ |
| if (from.charCodeAt(fromEnd - 1) !== CHAR_BACKWARD_SLASH) break; |
| } |
| const fromLen = fromEnd - fromStart; |
| |
| let toStart = 0; |
| let toEnd = to.length; |
| for(; toStart < toEnd; ++toStart){ |
| if (to.charCodeAt(toStart) !== CHAR_BACKWARD_SLASH) break; |
| } |
| |
| for(; toEnd - 1 > toStart; --toEnd){ |
| if (to.charCodeAt(toEnd - 1) !== CHAR_BACKWARD_SLASH) break; |
| } |
| const toLen = toEnd - toStart; |
| |
| const length = fromLen < toLen ? fromLen : toLen; |
| let lastCommonSep = -1; |
| let i = 0; |
| for(; i <= length; ++i){ |
| if (i === length) { |
| if (toLen > length) { |
| if (to.charCodeAt(toStart + i) === CHAR_BACKWARD_SLASH) { |
| |
| |
| return toOrig.slice(toStart + i + 1); |
| } else if (i === 2) { |
| |
| |
| return toOrig.slice(toStart + i); |
| } |
| } |
| if (fromLen > length) { |
| if (from.charCodeAt(fromStart + i) === CHAR_BACKWARD_SLASH) { |
| |
| |
| lastCommonSep = i; |
| } else if (i === 2) { |
| |
| |
| lastCommonSep = 3; |
| } |
| } |
| break; |
| } |
| const fromCode = from.charCodeAt(fromStart + i); |
| const toCode = to.charCodeAt(toStart + i); |
| if (fromCode !== toCode) break; |
| else if (fromCode === CHAR_BACKWARD_SLASH) lastCommonSep = i; |
| } |
| |
| |
| if (i !== length && lastCommonSep === -1) { |
| return toOrig; |
| } |
| let out = ""; |
| if (lastCommonSep === -1) lastCommonSep = 0; |
| |
| |
| for(i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i){ |
| if (i === fromEnd || from.charCodeAt(i) === CHAR_BACKWARD_SLASH) { |
| if (out.length === 0) out += ".."; |
| else out += "\\.."; |
| } |
| } |
| |
| |
| if (out.length > 0) { |
| return out + toOrig.slice(toStart + lastCommonSep, toEnd); |
| } else { |
| toStart += lastCommonSep; |
| if (toOrig.charCodeAt(toStart) === CHAR_BACKWARD_SLASH) ++toStart; |
| return toOrig.slice(toStart, toEnd); |
| } |
| } |
|
|
| |
| |
| const WHITESPACE_ENCODINGS = { |
| "\u0009": "%09", |
| "\u000A": "%0A", |
| "\u000B": "%0B", |
| "\u000C": "%0C", |
| "\u000D": "%0D", |
| "\u0020": "%20" |
| }; |
| function encodeWhitespace(string) { |
| return string.replaceAll(/[\s]/g, (c)=>{ |
| return WHITESPACE_ENCODINGS[c] ?? c; |
| }); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function toFileUrl(path) { |
| if (!isAbsolute(path)) { |
| throw new TypeError(`Path must be absolute: received "${path}"`); |
| } |
| const [, hostname, pathname] = path.match(/^(?:[/\\]{2}([^/\\]+)(?=[/\\](?:[^/\\]|$)))?(.*)/); |
| const url = new URL("file:///"); |
| url.pathname = encodeWhitespace(pathname.replace(/%/g, "%25")); |
| if (hostname !== undefined && hostname !== "localhost") { |
| url.hostname = hostname; |
| if (!url.hostname) { |
| throw new TypeError(`Invalid hostname: "${url.hostname}"`); |
| } |
| } |
| return url; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function toNamespacedPath(path) { |
| |
| if (typeof path !== "string") return path; |
| if (path.length === 0) return ""; |
| const resolvedPath = resolve(path); |
| if (resolvedPath.length >= 3) { |
| if (resolvedPath.charCodeAt(0) === CHAR_BACKWARD_SLASH) { |
| |
| if (resolvedPath.charCodeAt(1) === CHAR_BACKWARD_SLASH) { |
| const code = resolvedPath.charCodeAt(2); |
| if (code !== CHAR_QUESTION_MARK && code !== CHAR_DOT) { |
| |
| return `\\\\?\\UNC\\${resolvedPath.slice(2)}`; |
| } |
| } |
| } else if (isWindowsDeviceRoot(resolvedPath.charCodeAt(0))) { |
| |
| if (resolvedPath.charCodeAt(1) === CHAR_COLON && resolvedPath.charCodeAt(2) === CHAR_BACKWARD_SLASH) { |
| |
| return `\\\\?\\${resolvedPath}`; |
| } |
| } |
| } |
| return path; |
| } |
|
|
| |
| |
| function common$1(paths, sep) { |
| const [first = "", ...remaining] = paths; |
| const parts = first.split(sep); |
| let endOfPrefix = parts.length; |
| let append = ""; |
| for (const path of remaining){ |
| const compare = path.split(sep); |
| if (compare.length <= endOfPrefix) { |
| endOfPrefix = compare.length; |
| append = ""; |
| } |
| for(let i = 0; i < endOfPrefix; i++){ |
| if (compare[i] !== parts[i]) { |
| endOfPrefix = i; |
| append = i === 0 ? "" : sep; |
| break; |
| } |
| } |
| } |
| return parts.slice(0, endOfPrefix).join(sep) + append; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function common(paths) { |
| return common$1(paths, SEPARATOR); |
| } |
|
|
| |
| |
| |
| |
| |
| const REG_EXP_ESCAPE_CHARS = [ |
| "!", |
| "$", |
| "(", |
| ")", |
| "*", |
| "+", |
| ".", |
| "=", |
| "?", |
| "[", |
| "\\", |
| "^", |
| "{", |
| "|" |
| ]; |
| const RANGE_ESCAPE_CHARS = [ |
| "-", |
| "\\", |
| "]" |
| ]; |
| function _globToRegExp(c, glob, { extended = true, globstar: globstarOption = true, // os = osType, |
| caseInsensitive = false } = {}) { |
| if (glob === "") { |
| return /(?!)/; |
| } |
| |
| let newLength = glob.length; |
| for(; newLength > 1 && c.seps.includes(glob[newLength - 1]); newLength--); |
| glob = glob.slice(0, newLength); |
| let regExpString = ""; |
| |
| for(let j = 0; j < glob.length;){ |
| let segment = ""; |
| const groupStack = []; |
| let inRange = false; |
| let inEscape = false; |
| let endsWithSep = false; |
| let i = j; |
| |
| for(; i < glob.length && !c.seps.includes(glob[i]); i++){ |
| if (inEscape) { |
| inEscape = false; |
| const escapeChars = inRange ? RANGE_ESCAPE_CHARS : REG_EXP_ESCAPE_CHARS; |
| segment += escapeChars.includes(glob[i]) ? `\\${glob[i]}` : glob[i]; |
| continue; |
| } |
| if (glob[i] === c.escapePrefix) { |
| inEscape = true; |
| continue; |
| } |
| if (glob[i] === "[") { |
| if (!inRange) { |
| inRange = true; |
| segment += "["; |
| if (glob[i + 1] === "!") { |
| i++; |
| segment += "^"; |
| } else if (glob[i + 1] === "^") { |
| i++; |
| segment += "\\^"; |
| } |
| continue; |
| } else if (glob[i + 1] === ":") { |
| let k = i + 1; |
| let value = ""; |
| while(glob[k + 1] !== undefined && glob[k + 1] !== ":"){ |
| value += glob[k + 1]; |
| k++; |
| } |
| if (glob[k + 1] === ":" && glob[k + 2] === "]") { |
| i = k + 2; |
| if (value === "alnum") segment += "\\dA-Za-z"; |
| else if (value === "alpha") segment += "A-Za-z"; |
| else if (value === "ascii") segment += "\x00-\x7F"; |
| else if (value === "blank") segment += "\t "; |
| else if (value === "cntrl") segment += "\x00-\x1F\x7F"; |
| else if (value === "digit") segment += "\\d"; |
| else if (value === "graph") segment += "\x21-\x7E"; |
| else if (value === "lower") segment += "a-z"; |
| else if (value === "print") segment += "\x20-\x7E"; |
| else if (value === "punct") { |
| segment += "!\"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^_‘{|}~"; |
| } else if (value === "space") segment += "\\s\v"; |
| else if (value === "upper") segment += "A-Z"; |
| else if (value === "word") segment += "\\w"; |
| else if (value === "xdigit") segment += "\\dA-Fa-f"; |
| continue; |
| } |
| } |
| } |
| if (glob[i] === "]" && inRange) { |
| inRange = false; |
| segment += "]"; |
| continue; |
| } |
| if (inRange) { |
| segment += glob[i]; |
| continue; |
| } |
| if (glob[i] === ")" && groupStack.length > 0 && groupStack[groupStack.length - 1] !== "BRACE") { |
| segment += ")"; |
| const type = groupStack.pop(); |
| if (type === "!") { |
| segment += c.wildcard; |
| } else if (type !== "@") { |
| segment += type; |
| } |
| continue; |
| } |
| if (glob[i] === "|" && groupStack.length > 0 && groupStack[groupStack.length - 1] !== "BRACE") { |
| segment += "|"; |
| continue; |
| } |
| if (glob[i] === "+" && extended && glob[i + 1] === "(") { |
| i++; |
| groupStack.push("+"); |
| segment += "(?:"; |
| continue; |
| } |
| if (glob[i] === "@" && extended && glob[i + 1] === "(") { |
| i++; |
| groupStack.push("@"); |
| segment += "(?:"; |
| continue; |
| } |
| if (glob[i] === "?") { |
| if (extended && glob[i + 1] === "(") { |
| i++; |
| groupStack.push("?"); |
| segment += "(?:"; |
| } else { |
| segment += "."; |
| } |
| continue; |
| } |
| if (glob[i] === "!" && extended && glob[i + 1] === "(") { |
| i++; |
| groupStack.push("!"); |
| segment += "(?!"; |
| continue; |
| } |
| if (glob[i] === "{") { |
| groupStack.push("BRACE"); |
| segment += "(?:"; |
| continue; |
| } |
| if (glob[i] === "}" && groupStack[groupStack.length - 1] === "BRACE") { |
| groupStack.pop(); |
| segment += ")"; |
| continue; |
| } |
| if (glob[i] === "," && groupStack[groupStack.length - 1] === "BRACE") { |
| segment += "|"; |
| continue; |
| } |
| if (glob[i] === "*") { |
| if (extended && glob[i + 1] === "(") { |
| i++; |
| groupStack.push("*"); |
| segment += "(?:"; |
| } else { |
| const prevChar = glob[i - 1]; |
| let numStars = 1; |
| while(glob[i + 1] === "*"){ |
| i++; |
| numStars++; |
| } |
| const nextChar = glob[i + 1]; |
| if (globstarOption && numStars === 2 && [ |
| ...c.seps, |
| undefined |
| ].includes(prevChar) && [ |
| ...c.seps, |
| undefined |
| ].includes(nextChar)) { |
| segment += c.globstar; |
| endsWithSep = true; |
| } else { |
| segment += c.wildcard; |
| } |
| } |
| continue; |
| } |
| segment += REG_EXP_ESCAPE_CHARS.includes(glob[i]) ? `\\${glob[i]}` : glob[i]; |
| } |
| |
| if (groupStack.length > 0 || inRange || inEscape) { |
| |
| segment = ""; |
| for (const c of glob.slice(j, i)){ |
| segment += REG_EXP_ESCAPE_CHARS.includes(c) ? `\\${c}` : c; |
| endsWithSep = false; |
| } |
| } |
| regExpString += segment; |
| if (!endsWithSep) { |
| regExpString += i < glob.length ? c.sep : c.sepMaybe; |
| endsWithSep = true; |
| } |
| |
| while(c.seps.includes(glob[i]))i++; |
| j = i; |
| } |
| regExpString = `^${regExpString}$`; |
| return new RegExp(regExpString, caseInsensitive ? "i" : ""); |
| } |
|
|
| |
| |
| const constants = { |
| sep: "(?:\\\\|/)+", |
| sepMaybe: "(?:\\\\|/)*", |
| seps: [ |
| "\\", |
| "/" |
| ], |
| globstar: "(?:[^\\\\/]*(?:\\\\|/|$)+)*", |
| wildcard: "[^\\\\/]*", |
| escapePrefix: "`" |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function globToRegExp(glob, options = {}) { |
| return _globToRegExp(constants, glob, options); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function isGlob(str) { |
| const chars = { |
| "{": "}", |
| "(": ")", |
| "[": "]" |
| }; |
| const regex = /\\(.)|(^!|\*|\?|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; |
| if (str === "") { |
| return false; |
| } |
| let match; |
| while(match = regex.exec(str)){ |
| if (match[2]) return true; |
| let idx = match.index + match[0].length; |
| |
| |
| const open = match[1]; |
| const close = open ? chars[open] : null; |
| if (open && close) { |
| const n = str.indexOf(close, idx); |
| if (n !== -1) { |
| idx = n + 1; |
| } |
| } |
| str = str.slice(idx); |
| } |
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function normalizeGlob(glob, options = {}) { |
| const { globstar = false } = options; |
| if (glob.match(/\0/g)) { |
| throw new Error(`Glob contains invalid characters: "${glob}"`); |
| } |
| if (!globstar) { |
| return normalize(glob); |
| } |
| const s = SEPARATOR_PATTERN.source; |
| const badParentPattern = new RegExp(`(?<=(${s}|^)\\*\\*${s})\\.\\.(?=${s}|$)`, "g"); |
| return normalize(glob.replace(badParentPattern, "\0")).replace(/\0/g, ".."); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function joinGlobs(globs, options = {}) { |
| const { globstar = false } = options; |
| if (!globstar || globs.length === 0) { |
| return join(...globs); |
| } |
| let joined; |
| for (const glob of globs){ |
| const path = glob; |
| if (path.length > 0) { |
| if (!joined) joined = path; |
| else joined += `${SEPARATOR}${path}`; |
| } |
| } |
| if (!joined) return "."; |
| return normalizeGlob(joined, { |
| globstar |
| }); |
| } |
|
|
| export { DELIMITER, SEPARATOR, SEPARATOR_PATTERN, basename, common, dirname, extname, format, fromFileUrl, globToRegExp, isAbsolute, isGlob, join, joinGlobs, normalize, normalizeGlob, parse, relative, resolve, toFileUrl, toNamespacedPath }; |
|
|