UNPKG

mjdapi

Version:
162 lines (161 loc) 5.36 kB
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. // Copyright the Browserify authors. MIT License. // Ported from https://github.com/browserify/path-browserify/ // This module is browser compatible. import { CHAR_BACKWARD_SLASH, CHAR_DOT, CHAR_FORWARD_SLASH, CHAR_LOWERCASE_A, CHAR_LOWERCASE_Z, CHAR_UPPERCASE_A, CHAR_UPPERCASE_Z, } from "./_constants.js"; export function assertPath(path) { if (typeof path !== "string") { throw new TypeError(`Path must be a string. Received ${JSON.stringify(path)}`); } } export function isPosixPathSeparator(code) { return code === CHAR_FORWARD_SLASH; } export function isPathSeparator(code) { return isPosixPathSeparator(code) || code === CHAR_BACKWARD_SLASH; } export function isWindowsDeviceRoot(code) { return ((code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z) || (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z)); } // Resolves . and .. elements in a path with directory names export function normalizeString(path, allowAboveRoot, separator, isPathSeparator) { let res = ""; let lastSegmentLength = 0; let lastSlash = -1; let dots = 0; let code; for (let i = 0, len = path.length; i <= len; ++i) { if (i < len) code = path.charCodeAt(i); else if (isPathSeparator(code)) break; else code = CHAR_FORWARD_SLASH; if (isPathSeparator(code)) { if (lastSlash === i - 1 || dots === 1) { // NOOP } 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; } export 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; } const WHITESPACE_ENCODINGS = { "\u0009": "%09", "\u000A": "%0A", "\u000B": "%0B", "\u000C": "%0C", "\u000D": "%0D", "\u0020": "%20", }; export function encodeWhitespace(string) { return string.replaceAll(/[\s]/g, (c) => { return WHITESPACE_ENCODINGS[c] ?? c; }); } export 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); } export 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); } export 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); }