231 lines
7.7 KiB
Plaintext
231 lines
7.7 KiB
Plaintext
const require_utils = require("./utils.cjs");
|
|
const require_new_process_route_tree = require("./new-process-route-tree.cjs");
|
|
let _tanstack_router_core_isServer = require("@tanstack/router-core/isServer");
|
|
//#region src/path.ts
|
|
/** Join path segments, cleaning duplicate slashes between parts. */
|
|
function joinPaths(paths) {
|
|
return cleanPath(paths.filter((val) => {
|
|
return val !== void 0;
|
|
}).join("/"));
|
|
}
|
|
/** Remove repeated slashes from a path string. */
|
|
function cleanPath(path) {
|
|
return path.replace(/\/{2,}/g, "/");
|
|
}
|
|
/** Trim leading slashes (except preserving root '/'). */
|
|
function trimPathLeft(path) {
|
|
return path === "/" ? path : path.replace(/^\/{1,}/, "");
|
|
}
|
|
/** Trim trailing slashes (except preserving root '/'). */
|
|
function trimPathRight(path) {
|
|
const len = path.length;
|
|
return len > 1 && path[len - 1] === "/" ? path.replace(/\/{1,}$/, "") : path;
|
|
}
|
|
/** Trim both leading and trailing slashes. */
|
|
function trimPath(path) {
|
|
return trimPathRight(trimPathLeft(path));
|
|
}
|
|
/** Remove a trailing slash from value when appropriate for comparisons. */
|
|
function removeTrailingSlash(value, basepath) {
|
|
if (value?.endsWith("/") && value !== "/" && value !== `${basepath}/`) return value.slice(0, -1);
|
|
return value;
|
|
}
|
|
/**
|
|
* Compare two pathnames for exact equality after normalizing trailing slashes
|
|
* relative to the provided `basepath`.
|
|
*/
|
|
function exactPathTest(pathName1, pathName2, basepath) {
|
|
return removeTrailingSlash(pathName1, basepath) === removeTrailingSlash(pathName2, basepath);
|
|
}
|
|
/**
|
|
* Resolve a destination path against a base, honoring trailing-slash policy
|
|
* and supporting relative segments (`.`/`..`) and absolute `to` values.
|
|
*/
|
|
function resolvePath({ base, to, trailingSlash = "never", cache }) {
|
|
const isAbsolute = to.startsWith("/");
|
|
const isBase = !isAbsolute && to === ".";
|
|
let key;
|
|
if (cache) {
|
|
key = isAbsolute ? to : isBase ? base : base + "\0" + to;
|
|
const cached = cache.get(key);
|
|
if (cached) return cached;
|
|
}
|
|
let baseSegments;
|
|
if (isBase) baseSegments = base.split("/");
|
|
else if (isAbsolute) baseSegments = to.split("/");
|
|
else {
|
|
baseSegments = base.split("/");
|
|
while (baseSegments.length > 1 && require_utils.last(baseSegments) === "") baseSegments.pop();
|
|
const toSegments = to.split("/");
|
|
for (let index = 0, length = toSegments.length; index < length; index++) {
|
|
const value = toSegments[index];
|
|
if (value === "") {
|
|
if (!index) baseSegments = [value];
|
|
else if (index === length - 1) baseSegments.push(value);
|
|
} else if (value === "..") baseSegments.pop();
|
|
else if (value === ".") {} else baseSegments.push(value);
|
|
}
|
|
}
|
|
if (baseSegments.length > 1) {
|
|
if (require_utils.last(baseSegments) === "") {
|
|
if (trailingSlash === "never") baseSegments.pop();
|
|
} else if (trailingSlash === "always") baseSegments.push("");
|
|
}
|
|
const result = cleanPath(baseSegments.join("/")) || "/";
|
|
if (key && cache) cache.set(key, result);
|
|
return result;
|
|
}
|
|
/**
|
|
* Create a pre-compiled decode config from allowed characters.
|
|
* This should be called once at router initialization.
|
|
*/
|
|
function compileDecodeCharMap(pathParamsAllowedCharacters) {
|
|
const charMap = new Map(pathParamsAllowedCharacters.map((char) => [encodeURIComponent(char), char]));
|
|
const pattern = Array.from(charMap.keys()).map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
const regex = new RegExp(pattern, "g");
|
|
return (encoded) => encoded.replace(regex, (match) => charMap.get(match) ?? match);
|
|
}
|
|
function encodeParam(key, params, decoder) {
|
|
const value = params[key];
|
|
if (typeof value !== "string") return value;
|
|
if (key === "_splat") {
|
|
if (/^[a-zA-Z0-9\-._~!/]*$/.test(value)) return value;
|
|
return value.split("/").map((segment) => encodePathParam(segment, decoder)).join("/");
|
|
} else return encodePathParam(value, decoder);
|
|
}
|
|
/**
|
|
* Interpolate params and wildcards into a route path template.
|
|
*
|
|
* - Encodes params safely (configurable allowed characters)
|
|
* - Supports `{-$optional}` segments, `{prefix{$id}suffix}` and `{$}` wildcards
|
|
*/
|
|
function interpolatePath({ path, params, decoder, ...rest }) {
|
|
let isMissingParams = false;
|
|
const usedParams = Object.create(null);
|
|
if (!path || path === "/") return {
|
|
interpolatedPath: "/",
|
|
usedParams,
|
|
isMissingParams
|
|
};
|
|
if (!path.includes("$")) return {
|
|
interpolatedPath: path,
|
|
usedParams,
|
|
isMissingParams
|
|
};
|
|
if (_tanstack_router_core_isServer.isServer ?? rest.server) {
|
|
if (path.indexOf("{") === -1) {
|
|
const length = path.length;
|
|
let cursor = 0;
|
|
let joined = "";
|
|
while (cursor < length) {
|
|
while (cursor < length && path.charCodeAt(cursor) === 47) cursor++;
|
|
if (cursor >= length) break;
|
|
const start = cursor;
|
|
let end = path.indexOf("/", cursor);
|
|
if (end === -1) end = length;
|
|
cursor = end;
|
|
const part = path.substring(start, end);
|
|
if (!part) continue;
|
|
if (part.charCodeAt(0) === 36) if (part.length === 1) {
|
|
const splat = params._splat;
|
|
usedParams._splat = splat;
|
|
usedParams["*"] = splat;
|
|
if (!splat) {
|
|
isMissingParams = true;
|
|
continue;
|
|
}
|
|
const value = encodeParam("_splat", params, decoder);
|
|
joined += "/" + value;
|
|
} else {
|
|
const key = part.substring(1);
|
|
if (!isMissingParams && !(key in params)) isMissingParams = true;
|
|
usedParams[key] = params[key];
|
|
const value = encodeParam(key, params, decoder) ?? "undefined";
|
|
joined += "/" + value;
|
|
}
|
|
else joined += "/" + part;
|
|
}
|
|
if (path.endsWith("/")) joined += "/";
|
|
return {
|
|
usedParams,
|
|
interpolatedPath: joined || "/",
|
|
isMissingParams
|
|
};
|
|
}
|
|
}
|
|
const length = path.length;
|
|
let cursor = 0;
|
|
let segment;
|
|
let joined = "";
|
|
while (cursor < length) {
|
|
const start = cursor;
|
|
segment = require_new_process_route_tree.parseSegment(path, start, segment);
|
|
const end = segment[5];
|
|
cursor = end + 1;
|
|
if (start === end) continue;
|
|
const kind = segment[0];
|
|
if (kind === 0) {
|
|
joined += "/" + path.substring(start, end);
|
|
continue;
|
|
}
|
|
if (kind === 2) {
|
|
const splat = params._splat;
|
|
usedParams._splat = splat;
|
|
usedParams["*"] = splat;
|
|
const prefix = path.substring(start, segment[1]);
|
|
const suffix = path.substring(segment[4], end);
|
|
if (!splat) {
|
|
isMissingParams = true;
|
|
if (prefix || suffix) joined += "/" + prefix + suffix;
|
|
continue;
|
|
}
|
|
const value = encodeParam("_splat", params, decoder);
|
|
joined += "/" + prefix + value + suffix;
|
|
continue;
|
|
}
|
|
if (kind === 1) {
|
|
const key = path.substring(segment[2], segment[3]);
|
|
if (!isMissingParams && !(key in params)) isMissingParams = true;
|
|
usedParams[key] = params[key];
|
|
const prefix = path.substring(start, segment[1]);
|
|
const suffix = path.substring(segment[4], end);
|
|
const value = encodeParam(key, params, decoder) ?? "undefined";
|
|
joined += "/" + prefix + value + suffix;
|
|
continue;
|
|
}
|
|
if (kind === 3) {
|
|
const key = path.substring(segment[2], segment[3]);
|
|
const valueRaw = params[key];
|
|
if (valueRaw == null) continue;
|
|
usedParams[key] = valueRaw;
|
|
const prefix = path.substring(start, segment[1]);
|
|
const suffix = path.substring(segment[4], end);
|
|
const value = encodeParam(key, params, decoder) ?? "";
|
|
joined += "/" + prefix + value + suffix;
|
|
continue;
|
|
}
|
|
}
|
|
if (path.endsWith("/")) joined += "/";
|
|
return {
|
|
usedParams,
|
|
interpolatedPath: joined || "/",
|
|
isMissingParams
|
|
};
|
|
}
|
|
function encodePathParam(value, decoder) {
|
|
const encoded = encodeURIComponent(value);
|
|
return decoder?.(encoded) ?? encoded;
|
|
}
|
|
//#endregion
|
|
exports.cleanPath = cleanPath;
|
|
exports.compileDecodeCharMap = compileDecodeCharMap;
|
|
exports.exactPathTest = exactPathTest;
|
|
exports.interpolatePath = interpolatePath;
|
|
exports.joinPaths = joinPaths;
|
|
exports.removeTrailingSlash = removeTrailingSlash;
|
|
exports.resolvePath = resolvePath;
|
|
exports.trimPath = trimPath;
|
|
exports.trimPathLeft = trimPathLeft;
|
|
exports.trimPathRight = trimPathRight;
|
|
|
|
//# sourceMappingURL=path.cjs.map |