@flex-development/pathe
Version:
Universal drop-in replacement for node:path
57 lines (56 loc) • 1.97 kB
JavaScript
import { DRIVE_PATH_REGEX } from "#internal/constants";
import validateString from "#internal/validate-string";
import dot from "#lib/dot";
import isSep from "#lib/is-sep";
import resolveWith from "#lib/resolve-with";
import sep from "#lib/sep";
var relative_default = relative;
function relative(from, to, options) {
if (!Array.isArray(from)) validateString(from, "from");
if (!Array.isArray(to)) validateString(to, "to");
if (from === to) return "";
from = resolveWith(from, options);
to = resolveWith(to, options);
if (from.toLowerCase() === to.toLowerCase()) return "";
const [fromLen, fromStart, fromEnd] = measure(from);
const [toLen, toStart, toEnd] = measure(to);
const length = fromLen < toLen ? fromLen : toLen;
let lastCommonSep = -1;
let i = 0;
for (; i < length; i++) {
const char = from.at(fromStart + i);
if (char.toLowerCase() !== to.at(toStart + i).toLowerCase()) break;
else if (isSep(char)) lastCommonSep = i;
}
if (i === length) {
if (toLen > length) {
if (isSep(to.at(toStart + i))) return to.slice(toStart + i + 1);
if (i === 0 && isSep(from)) return to.slice(toStart + i);
}
if (fromLen > length) {
if (isSep(from.at(fromStart + i))) lastCommonSep = i;
else if (i === 0 && isSep(to)) lastCommonSep = i;
}
} else {
if (lastCommonSep === -1) {
if (DRIVE_PATH_REGEX.test(from) || DRIVE_PATH_REGEX.test(to)) return to;
}
}
let out = "";
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
if (i === fromEnd || isSep(from[i])) {
out += `${out.length === 0 ? "" : sep}${dot.repeat(2)}`;
}
}
return `${out}${to.slice(toStart + lastCommonSep, toEnd)}`;
}
function measure(path) {
let start = 0;
let end = path.length;
while (start < path.length && isSep(path.at(start))) start++;
while (end - 1 > start && isSep(path.at(end - 1))) end--;
return [end - start, start, end];
}
export {
relative_default as default
};