@tanstack/router-core 1.132.0-alpha.8 → 1.132.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Matches.cjs +2 -1
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/fileRoute.d.cts +3 -3
- package/dist/cjs/index.cjs +7 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +8 -4
- package/dist/cjs/load-matches.cjs +5 -3
- package/dist/cjs/load-matches.cjs.map +1 -1
- package/dist/cjs/location.d.cts +38 -0
- package/dist/cjs/path.cjs +27 -64
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +6 -7
- package/dist/cjs/process-route-tree.cjs +144 -0
- package/dist/cjs/process-route-tree.cjs.map +1 -0
- package/dist/cjs/process-route-tree.d.cts +10 -0
- package/dist/cjs/redirect.cjs +1 -1
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/rewrite.cjs +63 -0
- package/dist/cjs/rewrite.cjs.map +1 -0
- package/dist/cjs/rewrite.d.cts +22 -0
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +55 -42
- package/dist/cjs/router.cjs +77 -184
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +68 -37
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/scroll-restoration.d.cts +9 -0
- package/dist/cjs/ssr/createRequestHandler.cjs +4 -1
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/transformer.d.cts +10 -8
- package/dist/cjs/ssr/server.d.cts +0 -5
- package/dist/cjs/ssr/ssr-server.cjs +5 -2
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.d.cts +4 -1
- package/dist/cjs/utils.cjs +68 -46
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/esm/Matches.js +2 -1
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/fileRoute.d.ts +3 -3
- package/dist/esm/index.d.ts +8 -4
- package/dist/esm/index.js +8 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/load-matches.js +5 -3
- package/dist/esm/load-matches.js.map +1 -1
- package/dist/esm/location.d.ts +38 -0
- package/dist/esm/path.d.ts +6 -7
- package/dist/esm/path.js +27 -64
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/process-route-tree.d.ts +10 -0
- package/dist/esm/process-route-tree.js +144 -0
- package/dist/esm/process-route-tree.js.map +1 -0
- package/dist/esm/redirect.js +1 -1
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/rewrite.d.ts +22 -0
- package/dist/esm/rewrite.js +63 -0
- package/dist/esm/rewrite.js.map +1 -0
- package/dist/esm/route.d.ts +55 -42
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +68 -37
- package/dist/esm/router.js +79 -186
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.d.ts +9 -0
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/ssr/createRequestHandler.js +4 -1
- package/dist/esm/ssr/createRequestHandler.js.map +1 -1
- package/dist/esm/ssr/serializer/transformer.d.ts +10 -8
- package/dist/esm/ssr/serializer/transformer.js.map +1 -1
- package/dist/esm/ssr/server.d.ts +0 -5
- package/dist/esm/ssr/ssr-server.d.ts +4 -1
- package/dist/esm/ssr/ssr-server.js +5 -2
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/utils.js +68 -46
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/Matches.ts +2 -1
- package/src/fileRoute.ts +16 -6
- package/src/index.ts +11 -6
- package/src/load-matches.ts +29 -19
- package/src/location.ts +38 -0
- package/src/path.ts +44 -82
- package/src/process-route-tree.ts +233 -0
- package/src/redirect.ts +1 -1
- package/src/rewrite.ts +70 -0
- package/src/route.ts +214 -80
- package/src/router.ts +208 -329
- package/src/scroll-restoration.ts +1 -1
- package/src/ssr/createRequestHandler.ts +4 -1
- package/src/ssr/serializer/transformer.ts +17 -17
- package/src/ssr/server.ts +5 -5
- package/src/ssr/ssr-server.ts +8 -5
- package/src/utils.ts +83 -61
package/dist/esm/path.js
CHANGED
|
@@ -70,17 +70,13 @@ function segmentToString(segment) {
|
|
|
70
70
|
return value;
|
|
71
71
|
}
|
|
72
72
|
function resolvePath({
|
|
73
|
-
basepath,
|
|
74
73
|
base,
|
|
75
74
|
to,
|
|
76
75
|
trailingSlash = "never",
|
|
77
|
-
caseSensitive,
|
|
78
76
|
parseCache
|
|
79
77
|
}) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
let baseSegments = parsePathname(base, parseCache).slice();
|
|
83
|
-
const toSegments = parsePathname(to, parseCache);
|
|
78
|
+
let baseSegments = parseBasePathSegments(base, parseCache).slice();
|
|
79
|
+
const toSegments = parseRoutePathSegments(to, parseCache);
|
|
84
80
|
if (baseSegments.length > 1 && last(baseSegments)?.value === "/") {
|
|
85
81
|
baseSegments.pop();
|
|
86
82
|
}
|
|
@@ -110,14 +106,16 @@ function resolvePath({
|
|
|
110
106
|
}
|
|
111
107
|
}
|
|
112
108
|
const segmentValues = baseSegments.map(segmentToString);
|
|
113
|
-
const joined = joinPaths(
|
|
109
|
+
const joined = joinPaths(segmentValues);
|
|
114
110
|
return joined;
|
|
115
111
|
}
|
|
116
|
-
const
|
|
112
|
+
const parseBasePathSegments = (pathname, cache) => parsePathname(pathname, cache, true);
|
|
113
|
+
const parseRoutePathSegments = (pathname, cache) => parsePathname(pathname, cache, false);
|
|
114
|
+
const parsePathname = (pathname, cache, basePathValues) => {
|
|
117
115
|
if (!pathname) return [];
|
|
118
116
|
const cached = cache?.get(pathname);
|
|
119
117
|
if (cached) return cached;
|
|
120
|
-
const parsed = baseParsePathname(pathname);
|
|
118
|
+
const parsed = baseParsePathname(pathname, basePathValues);
|
|
121
119
|
cache?.set(pathname, parsed);
|
|
122
120
|
return parsed;
|
|
123
121
|
};
|
|
@@ -126,7 +124,7 @@ const PARAM_W_CURLY_BRACES_RE = /^(.*?)\{(\$[a-zA-Z_$][a-zA-Z0-9_$]*)\}(.*)$/;
|
|
|
126
124
|
const OPTIONAL_PARAM_W_CURLY_BRACES_RE = /^(.*?)\{-(\$[a-zA-Z_$][a-zA-Z0-9_$]*)\}(.*)$/;
|
|
127
125
|
const WILDCARD_RE = /^\$$/;
|
|
128
126
|
const WILDCARD_W_CURLY_BRACES_RE = /^(.*?)\{\$\}(.*)$/;
|
|
129
|
-
function baseParsePathname(pathname) {
|
|
127
|
+
function baseParsePathname(pathname, basePathValues) {
|
|
130
128
|
pathname = cleanPath(pathname);
|
|
131
129
|
const segments = [];
|
|
132
130
|
if (pathname.slice(0, 1) === "/") {
|
|
@@ -142,7 +140,8 @@ function baseParsePathname(pathname) {
|
|
|
142
140
|
const split = pathname.split("/").filter(Boolean);
|
|
143
141
|
segments.push(
|
|
144
142
|
...split.map((part) => {
|
|
145
|
-
const
|
|
143
|
+
const partToMatch = !basePathValues && part.slice(-1) === "_" ? part.slice(0, -1) : part;
|
|
144
|
+
const wildcardBracesMatch = partToMatch.match(WILDCARD_W_CURLY_BRACES_RE);
|
|
146
145
|
if (wildcardBracesMatch) {
|
|
147
146
|
const prefix = wildcardBracesMatch[1];
|
|
148
147
|
const suffix = wildcardBracesMatch[2];
|
|
@@ -153,7 +152,7 @@ function baseParsePathname(pathname) {
|
|
|
153
152
|
suffixSegment: suffix || void 0
|
|
154
153
|
};
|
|
155
154
|
}
|
|
156
|
-
const optionalParamBracesMatch =
|
|
155
|
+
const optionalParamBracesMatch = partToMatch.match(
|
|
157
156
|
OPTIONAL_PARAM_W_CURLY_BRACES_RE
|
|
158
157
|
);
|
|
159
158
|
if (optionalParamBracesMatch) {
|
|
@@ -168,7 +167,7 @@ function baseParsePathname(pathname) {
|
|
|
168
167
|
suffixSegment: suffix || void 0
|
|
169
168
|
};
|
|
170
169
|
}
|
|
171
|
-
const paramBracesMatch =
|
|
170
|
+
const paramBracesMatch = partToMatch.match(PARAM_W_CURLY_BRACES_RE);
|
|
172
171
|
if (paramBracesMatch) {
|
|
173
172
|
const prefix = paramBracesMatch[1];
|
|
174
173
|
const paramName = paramBracesMatch[2];
|
|
@@ -180,8 +179,8 @@ function baseParsePathname(pathname) {
|
|
|
180
179
|
suffixSegment: suffix || void 0
|
|
181
180
|
};
|
|
182
181
|
}
|
|
183
|
-
if (PARAM_RE.test(
|
|
184
|
-
const paramName =
|
|
182
|
+
if (PARAM_RE.test(partToMatch)) {
|
|
183
|
+
const paramName = partToMatch.substring(1);
|
|
185
184
|
return {
|
|
186
185
|
type: SEGMENT_TYPE_PARAM,
|
|
187
186
|
value: "$" + paramName,
|
|
@@ -189,7 +188,7 @@ function baseParsePathname(pathname) {
|
|
|
189
188
|
suffixSegment: void 0
|
|
190
189
|
};
|
|
191
190
|
}
|
|
192
|
-
if (WILDCARD_RE.test(
|
|
191
|
+
if (WILDCARD_RE.test(partToMatch)) {
|
|
193
192
|
return {
|
|
194
193
|
type: SEGMENT_TYPE_WILDCARD,
|
|
195
194
|
value: "$",
|
|
@@ -199,7 +198,7 @@ function baseParsePathname(pathname) {
|
|
|
199
198
|
}
|
|
200
199
|
return {
|
|
201
200
|
type: SEGMENT_TYPE_PATHNAME,
|
|
202
|
-
value:
|
|
201
|
+
value: partToMatch.includes("%25") ? partToMatch.split("%25").map((segment) => decodeURI(segment)).join("%25") : decodeURI(partToMatch)
|
|
203
202
|
};
|
|
204
203
|
})
|
|
205
204
|
);
|
|
@@ -220,7 +219,7 @@ function interpolatePath({
|
|
|
220
219
|
decodeCharMap,
|
|
221
220
|
parseCache
|
|
222
221
|
}) {
|
|
223
|
-
const interpolatedPathSegments =
|
|
222
|
+
const interpolatedPathSegments = parseRoutePathSegments(path, parseCache);
|
|
224
223
|
function encodeParam(key) {
|
|
225
224
|
const value = params[key];
|
|
226
225
|
const isValueString = typeof value === "string";
|
|
@@ -239,6 +238,7 @@ function interpolatePath({
|
|
|
239
238
|
}
|
|
240
239
|
if (segment.type === SEGMENT_TYPE_WILDCARD) {
|
|
241
240
|
usedParams._splat = params._splat;
|
|
241
|
+
usedParams["*"] = params._splat;
|
|
242
242
|
const segmentPrefix = segment.prefixSegment || "";
|
|
243
243
|
const segmentSuffix = segment.suffixSegment || "";
|
|
244
244
|
if (!("_splat" in params)) {
|
|
@@ -308,63 +308,25 @@ function encodePathParam(value, decodeCharMap) {
|
|
|
308
308
|
}
|
|
309
309
|
return encoded;
|
|
310
310
|
}
|
|
311
|
-
function matchPathname(
|
|
312
|
-
const pathParams = matchByPath(
|
|
313
|
-
basepath,
|
|
314
|
-
currentPathname,
|
|
315
|
-
matchLocation,
|
|
316
|
-
parseCache
|
|
317
|
-
);
|
|
311
|
+
function matchPathname(currentPathname, matchLocation, parseCache) {
|
|
312
|
+
const pathParams = matchByPath(currentPathname, matchLocation, parseCache);
|
|
318
313
|
if (matchLocation.to && !pathParams) {
|
|
319
314
|
return;
|
|
320
315
|
}
|
|
321
316
|
return pathParams ?? {};
|
|
322
317
|
}
|
|
323
|
-
function
|
|
324
|
-
const normalizedBasepath = caseSensitive ? basepath : basepath.toLowerCase();
|
|
325
|
-
const normalizedPathname = caseSensitive ? pathname : pathname.toLowerCase();
|
|
326
|
-
switch (true) {
|
|
327
|
-
// default behaviour is to serve app from the root - pathname
|
|
328
|
-
// left untouched
|
|
329
|
-
case normalizedBasepath === "/":
|
|
330
|
-
return pathname;
|
|
331
|
-
// shortcut for removing the basepath if it matches the pathname
|
|
332
|
-
case normalizedPathname === normalizedBasepath:
|
|
333
|
-
return "";
|
|
334
|
-
// in case pathname is shorter than basepath - there is
|
|
335
|
-
// nothing to remove
|
|
336
|
-
case pathname.length < basepath.length:
|
|
337
|
-
return pathname;
|
|
338
|
-
// avoid matching partial segments - strict equality handled
|
|
339
|
-
// earlier, otherwise, basepath separated from pathname with
|
|
340
|
-
// separator, therefore lack of separator means partial
|
|
341
|
-
// segment match (`/app` should not match `/application`)
|
|
342
|
-
case normalizedPathname[normalizedBasepath.length] !== "/":
|
|
343
|
-
return pathname;
|
|
344
|
-
// remove the basepath from the pathname if it starts with it
|
|
345
|
-
case normalizedPathname.startsWith(normalizedBasepath):
|
|
346
|
-
return pathname.slice(basepath.length);
|
|
347
|
-
// otherwise, return the pathname as is
|
|
348
|
-
default:
|
|
349
|
-
return pathname;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
function matchByPath(basepath, from, {
|
|
318
|
+
function matchByPath(from, {
|
|
353
319
|
to,
|
|
354
320
|
fuzzy,
|
|
355
321
|
caseSensitive
|
|
356
322
|
}, parseCache) {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
from = removeBasepath(basepath, from, caseSensitive);
|
|
361
|
-
to = removeBasepath(basepath, `${to ?? "$"}`, caseSensitive);
|
|
362
|
-
const baseSegments = parsePathname(
|
|
323
|
+
const stringTo = to;
|
|
324
|
+
const baseSegments = parseBasePathSegments(
|
|
363
325
|
from.startsWith("/") ? from : `/${from}`,
|
|
364
326
|
parseCache
|
|
365
327
|
);
|
|
366
|
-
const routeSegments =
|
|
367
|
-
|
|
328
|
+
const routeSegments = parseRoutePathSegments(
|
|
329
|
+
stringTo.startsWith("/") ? stringTo : `/${stringTo}`,
|
|
368
330
|
parseCache
|
|
369
331
|
);
|
|
370
332
|
const params = {};
|
|
@@ -569,8 +531,9 @@ export {
|
|
|
569
531
|
joinPaths,
|
|
570
532
|
matchByPath,
|
|
571
533
|
matchPathname,
|
|
534
|
+
parseBasePathSegments,
|
|
572
535
|
parsePathname,
|
|
573
|
-
|
|
536
|
+
parseRoutePathSegments,
|
|
574
537
|
removeTrailingSlash,
|
|
575
538
|
resolvePath,
|
|
576
539
|
trimPath,
|
package/dist/esm/path.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.js","sources":["../../src/path.ts"],"sourcesContent":["import { last } from './utils'\nimport type { LRUCache } from './lru-cache'\nimport type { MatchLocation } from './RouterProvider'\nimport type { AnyPathParams } from './route'\n\nexport const SEGMENT_TYPE_PATHNAME = 0\nexport const SEGMENT_TYPE_PARAM = 1\nexport const SEGMENT_TYPE_WILDCARD = 2\nexport const SEGMENT_TYPE_OPTIONAL_PARAM = 3\n\nexport interface Segment {\n readonly type:\n | typeof SEGMENT_TYPE_PATHNAME\n | typeof SEGMENT_TYPE_PARAM\n | typeof SEGMENT_TYPE_WILDCARD\n | typeof SEGMENT_TYPE_OPTIONAL_PARAM\n readonly value: string\n readonly prefixSegment?: string\n readonly suffixSegment?: string\n // Indicates if there is a static segment after this required/optional param\n readonly hasStaticAfter?: boolean\n}\n\nexport function joinPaths(paths: Array<string | undefined>) {\n return cleanPath(\n paths\n .filter((val) => {\n return val !== undefined\n })\n .join('/'),\n )\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function trimPathRight(path: string) {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '')\n}\n\nexport function trimPath(path: string) {\n return trimPathRight(trimPathLeft(path))\n}\n\nexport function removeTrailingSlash(value: string, basepath: string): string {\n if (value?.endsWith('/') && value !== '/' && value !== `${basepath}/`) {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(\n pathName1: string,\n pathName2: string,\n basepath: string,\n): boolean {\n return (\n removeTrailingSlash(pathName1, basepath) ===\n removeTrailingSlash(pathName2, basepath)\n )\n}\n\n// When resolving relative paths, we treat all paths as if they are trailing slash\n// documents. All trailing slashes are removed after the path is resolved.\n// Here are a few examples:\n//\n// /a/b/c + ./d = /a/b/c/d\n// /a/b/c + ../d = /a/b/d\n// /a/b/c + ./d/ = /a/b/c/d\n// /a/b/c + ../d/ = /a/b/d\n// /a/b/c + ./ = /a/b/c\n//\n// Absolute paths that start with `/` short circuit the resolution process to the root\n// path.\n//\n// Here are some examples:\n//\n// /a/b/c + /d = /d\n// /a/b/c + /d/ = /d\n// /a/b/c + / = /\n//\n// Non-.-prefixed paths are still treated as relative paths, resolved like `./`\n//\n// Here are some examples:\n//\n// /a/b/c + d = /a/b/c/d\n// /a/b/c + d/ = /a/b/c/d\n// /a/b/c + d/e = /a/b/c/d/e\ninterface ResolvePathOptions {\n basepath: string\n base: string\n to: string\n trailingSlash?: 'always' | 'never' | 'preserve'\n caseSensitive?: boolean\n parseCache?: ParsePathnameCache\n}\n\nfunction segmentToString(segment: Segment): string {\n const { type, value } = segment\n if (type === SEGMENT_TYPE_PATHNAME) {\n return value\n }\n\n const { prefixSegment, suffixSegment } = segment\n\n if (type === SEGMENT_TYPE_PARAM) {\n const param = value.substring(1)\n if (prefixSegment && suffixSegment) {\n return `${prefixSegment}{$${param}}${suffixSegment}`\n } else if (prefixSegment) {\n return `${prefixSegment}{$${param}}`\n } else if (suffixSegment) {\n return `{$${param}}${suffixSegment}`\n }\n }\n\n if (type === SEGMENT_TYPE_OPTIONAL_PARAM) {\n const param = value.substring(1)\n if (prefixSegment && suffixSegment) {\n return `${prefixSegment}{-$${param}}${suffixSegment}`\n } else if (prefixSegment) {\n return `${prefixSegment}{-$${param}}`\n } else if (suffixSegment) {\n return `{-$${param}}${suffixSegment}`\n }\n return `{-$${param}}`\n }\n\n if (type === SEGMENT_TYPE_WILDCARD) {\n if (prefixSegment && suffixSegment) {\n return `${prefixSegment}{$}${suffixSegment}`\n } else if (prefixSegment) {\n return `${prefixSegment}{$}`\n } else if (suffixSegment) {\n return `{$}${suffixSegment}`\n }\n }\n\n // This case should never happen, should we throw instead?\n return value\n}\n\nexport function resolvePath({\n basepath,\n base,\n to,\n trailingSlash = 'never',\n caseSensitive,\n parseCache,\n}: ResolvePathOptions) {\n base = removeBasepath(basepath, base, caseSensitive)\n to = removeBasepath(basepath, to, caseSensitive)\n\n let baseSegments = parsePathname(base, parseCache).slice()\n const toSegments = parsePathname(to, parseCache)\n\n if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {\n baseSegments.pop()\n }\n\n for (let index = 0, length = toSegments.length; index < length; index++) {\n const toSegment = toSegments[index]!\n const value = toSegment.value\n if (value === '/') {\n if (!index) {\n // Leading slash\n baseSegments = [toSegment]\n } else if (index === length - 1) {\n // Trailing Slash\n baseSegments.push(toSegment)\n } else {\n // ignore inter-slashes\n }\n } else if (value === '..') {\n baseSegments.pop()\n } else if (value === '.') {\n // ignore\n } else {\n baseSegments.push(toSegment)\n }\n }\n\n if (baseSegments.length > 1) {\n if (last(baseSegments)!.value === '/') {\n if (trailingSlash === 'never') {\n baseSegments.pop()\n }\n } else if (trailingSlash === 'always') {\n baseSegments.push({ type: SEGMENT_TYPE_PATHNAME, value: '/' })\n }\n }\n\n const segmentValues = baseSegments.map(segmentToString)\n const joined = joinPaths([basepath, ...segmentValues])\n return joined\n}\n\nexport type ParsePathnameCache = LRUCache<string, ReadonlyArray<Segment>>\nexport const parsePathname = (\n pathname?: string,\n cache?: ParsePathnameCache,\n): ReadonlyArray<Segment> => {\n if (!pathname) return []\n const cached = cache?.get(pathname)\n if (cached) return cached\n const parsed = baseParsePathname(pathname)\n cache?.set(pathname, parsed)\n return parsed\n}\n\nconst PARAM_RE = /^\\$.{1,}$/ // $paramName\nconst PARAM_W_CURLY_BRACES_RE = /^(.*?)\\{(\\$[a-zA-Z_$][a-zA-Z0-9_$]*)\\}(.*)$/ // prefix{$paramName}suffix\nconst OPTIONAL_PARAM_W_CURLY_BRACES_RE =\n /^(.*?)\\{-(\\$[a-zA-Z_$][a-zA-Z0-9_$]*)\\}(.*)$/ // prefix{-$paramName}suffix\n\nconst WILDCARD_RE = /^\\$$/ // $\nconst WILDCARD_W_CURLY_BRACES_RE = /^(.*?)\\{\\$\\}(.*)$/ // prefix{$}suffix\n\n/**\n * Required: `/foo/$bar` ✅\n * Prefix and Suffix: `/foo/prefix${bar}suffix` ✅\n * Wildcard: `/foo/$` ✅\n * Wildcard with Prefix and Suffix: `/foo/prefix{$}suffix` ✅\n *\n * Optional param: `/foo/{-$bar}`\n * Optional param with Prefix and Suffix: `/foo/prefix{-$bar}suffix`\n\n * Future:\n * Optional named segment: `/foo/{bar}`\n * Optional named segment with Prefix and Suffix: `/foo/prefix{-bar}suffix`\n * Escape special characters:\n * - `/foo/[$]` - Static route\n * - `/foo/[$]{$foo} - Dynamic route with a static prefix of `$`\n * - `/foo/{$foo}[$]` - Dynamic route with a static suffix of `$`\n */\nfunction baseParsePathname(pathname: string): ReadonlyArray<Segment> {\n pathname = cleanPath(pathname)\n\n const segments: Array<Segment> = []\n\n if (pathname.slice(0, 1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: SEGMENT_TYPE_PATHNAME,\n value: '/',\n })\n }\n\n if (!pathname) {\n return segments\n }\n\n // Remove empty segments and '.' segments\n const split = pathname.split('/').filter(Boolean)\n\n segments.push(\n ...split.map((part): Segment => {\n // Check for wildcard with curly braces: prefix{$}suffix\n const wildcardBracesMatch = part.match(WILDCARD_W_CURLY_BRACES_RE)\n if (wildcardBracesMatch) {\n const prefix = wildcardBracesMatch[1]\n const suffix = wildcardBracesMatch[2]\n return {\n type: SEGMENT_TYPE_WILDCARD,\n value: '$',\n prefixSegment: prefix || undefined,\n suffixSegment: suffix || undefined,\n }\n }\n\n // Check for optional parameter format: prefix{-$paramName}suffix\n const optionalParamBracesMatch = part.match(\n OPTIONAL_PARAM_W_CURLY_BRACES_RE,\n )\n if (optionalParamBracesMatch) {\n const prefix = optionalParamBracesMatch[1]\n const paramName = optionalParamBracesMatch[2]!\n const suffix = optionalParamBracesMatch[3]\n return {\n type: SEGMENT_TYPE_OPTIONAL_PARAM,\n value: paramName, // Now just $paramName (no prefix)\n prefixSegment: prefix || undefined,\n suffixSegment: suffix || undefined,\n }\n }\n\n // Check for the new parameter format: prefix{$paramName}suffix\n const paramBracesMatch = part.match(PARAM_W_CURLY_BRACES_RE)\n if (paramBracesMatch) {\n const prefix = paramBracesMatch[1]\n const paramName = paramBracesMatch[2]\n const suffix = paramBracesMatch[3]\n return {\n type: SEGMENT_TYPE_PARAM,\n value: '' + paramName,\n prefixSegment: prefix || undefined,\n suffixSegment: suffix || undefined,\n }\n }\n\n // Check for bare parameter format: $paramName (without curly braces)\n if (PARAM_RE.test(part)) {\n const paramName = part.substring(1)\n return {\n type: SEGMENT_TYPE_PARAM,\n value: '$' + paramName,\n prefixSegment: undefined,\n suffixSegment: undefined,\n }\n }\n\n // Check for bare wildcard: $ (without curly braces)\n if (WILDCARD_RE.test(part)) {\n return {\n type: SEGMENT_TYPE_WILDCARD,\n value: '$',\n prefixSegment: undefined,\n suffixSegment: undefined,\n }\n }\n\n // Handle regular pathname segment\n return {\n type: SEGMENT_TYPE_PATHNAME,\n value: part.includes('%25')\n ? part\n .split('%25')\n .map((segment) => decodeURI(segment))\n .join('%25')\n : decodeURI(part),\n }\n }),\n )\n\n if (pathname.slice(-1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: SEGMENT_TYPE_PATHNAME,\n value: '/',\n })\n }\n\n return segments\n}\n\ninterface InterpolatePathOptions {\n path?: string\n params: Record<string, unknown>\n leaveWildcards?: boolean\n leaveParams?: boolean\n // Map of encoded chars to decoded chars (e.g. '%40' -> '@') that should remain decoded in path params\n decodeCharMap?: Map<string, string>\n parseCache?: ParsePathnameCache\n}\n\ntype InterPolatePathResult = {\n interpolatedPath: string\n usedParams: Record<string, unknown>\n isMissingParams: boolean // true if any params were not available when being looked up in the params object\n}\nexport function interpolatePath({\n path,\n params,\n leaveWildcards,\n leaveParams,\n decodeCharMap,\n parseCache,\n}: InterpolatePathOptions): InterPolatePathResult {\n const interpolatedPathSegments = parsePathname(path, parseCache)\n\n function encodeParam(key: string): any {\n const value = params[key]\n const isValueString = typeof value === 'string'\n\n if (key === '*' || key === '_splat') {\n // the splat/catch-all routes shouldn't have the '/' encoded out\n return isValueString ? encodeURI(value) : value\n } else {\n return isValueString ? encodePathParam(value, decodeCharMap) : value\n }\n }\n\n // Tracking if any params are missing in the `params` object\n // when interpolating the path\n let isMissingParams = false\n\n const usedParams: Record<string, unknown> = {}\n const interpolatedPath = joinPaths(\n interpolatedPathSegments.map((segment) => {\n if (segment.type === SEGMENT_TYPE_PATHNAME) {\n return segment.value\n }\n\n if (segment.type === SEGMENT_TYPE_WILDCARD) {\n usedParams._splat = params._splat\n const segmentPrefix = segment.prefixSegment || ''\n const segmentSuffix = segment.suffixSegment || ''\n\n // Check if _splat parameter is missing\n if (!('_splat' in params)) {\n isMissingParams = true\n // For missing splat parameters, just return the prefix and suffix without the wildcard\n if (leaveWildcards) {\n return `${segmentPrefix}${segment.value}${segmentSuffix}`\n }\n // If there is a prefix or suffix, return them joined, otherwise omit the segment\n if (segmentPrefix || segmentSuffix) {\n return `${segmentPrefix}${segmentSuffix}`\n }\n return undefined\n }\n\n const value = encodeParam('_splat')\n if (leaveWildcards) {\n return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`\n }\n return `${segmentPrefix}${value}${segmentSuffix}`\n }\n\n if (segment.type === SEGMENT_TYPE_PARAM) {\n const key = segment.value.substring(1)\n if (!isMissingParams && !(key in params)) {\n isMissingParams = true\n }\n usedParams[key] = params[key]\n\n const segmentPrefix = segment.prefixSegment || ''\n const segmentSuffix = segment.suffixSegment || ''\n if (leaveParams) {\n const value = encodeParam(segment.value)\n return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`\n }\n return `${segmentPrefix}${encodeParam(key) ?? 'undefined'}${segmentSuffix}`\n }\n\n if (segment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {\n const key = segment.value.substring(1)\n\n const segmentPrefix = segment.prefixSegment || ''\n const segmentSuffix = segment.suffixSegment || ''\n\n // Check if optional parameter is missing or undefined\n if (!(key in params) || params[key] == null) {\n if (leaveWildcards) {\n return `${segmentPrefix}${key}${segmentSuffix}`\n }\n // For optional params with prefix/suffix, keep the prefix/suffix but omit the param\n if (segmentPrefix || segmentSuffix) {\n return `${segmentPrefix}${segmentSuffix}`\n }\n // If no prefix/suffix, omit the entire segment\n return undefined\n }\n\n usedParams[key] = params[key]\n\n if (leaveParams) {\n const value = encodeParam(segment.value)\n return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`\n }\n if (leaveWildcards) {\n return `${segmentPrefix}${key}${encodeParam(key) ?? ''}${segmentSuffix}`\n }\n return `${segmentPrefix}${encodeParam(key) ?? ''}${segmentSuffix}`\n }\n\n return segment.value\n }),\n )\n return { usedParams, interpolatedPath, isMissingParams }\n}\n\nfunction encodePathParam(value: string, decodeCharMap?: Map<string, string>) {\n let encoded = encodeURIComponent(value)\n if (decodeCharMap) {\n for (const [encodedChar, char] of decodeCharMap) {\n encoded = encoded.replaceAll(encodedChar, char)\n }\n }\n return encoded\n}\n\nexport function matchPathname(\n basepath: string,\n currentPathname: string,\n matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,\n parseCache?: ParsePathnameCache,\n): AnyPathParams | undefined {\n const pathParams = matchByPath(\n basepath,\n currentPathname,\n matchLocation,\n parseCache,\n )\n // const searchMatched = matchBySearch(location.search, matchLocation)\n\n if (matchLocation.to && !pathParams) {\n return\n }\n\n return pathParams ?? {}\n}\n\nexport function removeBasepath(\n basepath: string,\n pathname: string,\n caseSensitive: boolean = false,\n) {\n // normalize basepath and pathname for case-insensitive comparison if needed\n const normalizedBasepath = caseSensitive ? basepath : basepath.toLowerCase()\n const normalizedPathname = caseSensitive ? pathname : pathname.toLowerCase()\n\n switch (true) {\n // default behaviour is to serve app from the root - pathname\n // left untouched\n case normalizedBasepath === '/':\n return pathname\n\n // shortcut for removing the basepath if it matches the pathname\n case normalizedPathname === normalizedBasepath:\n return ''\n\n // in case pathname is shorter than basepath - there is\n // nothing to remove\n case pathname.length < basepath.length:\n return pathname\n\n // avoid matching partial segments - strict equality handled\n // earlier, otherwise, basepath separated from pathname with\n // separator, therefore lack of separator means partial\n // segment match (`/app` should not match `/application`)\n case normalizedPathname[normalizedBasepath.length] !== '/':\n return pathname\n\n // remove the basepath from the pathname if it starts with it\n case normalizedPathname.startsWith(normalizedBasepath):\n return pathname.slice(basepath.length)\n\n // otherwise, return the pathname as is\n default:\n return pathname\n }\n}\n\nexport function matchByPath(\n basepath: string,\n from: string,\n {\n to,\n fuzzy,\n caseSensitive,\n }: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,\n parseCache?: ParsePathnameCache,\n): Record<string, string> | undefined {\n // check basepath first\n if (basepath !== '/' && !from.startsWith(basepath)) {\n return undefined\n }\n // Remove the base path from the pathname\n from = removeBasepath(basepath, from, caseSensitive)\n // Default to to $ (wildcard)\n to = removeBasepath(basepath, `${to ?? '$'}`, caseSensitive)\n\n // Parse the from and to\n const baseSegments = parsePathname(\n from.startsWith('/') ? from : `/${from}`,\n parseCache,\n )\n const routeSegments = parsePathname(\n to.startsWith('/') ? to : `/${to}`,\n parseCache,\n )\n\n const params: Record<string, string> = {}\n\n const result = isMatch(\n baseSegments,\n routeSegments,\n params,\n fuzzy,\n caseSensitive,\n )\n\n return result ? params : undefined\n}\n\nfunction isMatch(\n baseSegments: ReadonlyArray<Segment>,\n routeSegments: ReadonlyArray<Segment>,\n params: Record<string, string>,\n fuzzy?: boolean,\n caseSensitive?: boolean,\n): boolean {\n let baseIndex = 0\n let routeIndex = 0\n\n while (baseIndex < baseSegments.length || routeIndex < routeSegments.length) {\n const baseSegment = baseSegments[baseIndex]\n const routeSegment = routeSegments[routeIndex]\n\n if (routeSegment) {\n if (routeSegment.type === SEGMENT_TYPE_WILDCARD) {\n // Capture all remaining segments for a wildcard\n const remainingBaseSegments = baseSegments.slice(baseIndex)\n\n let _splat: string\n\n // If this is a wildcard with prefix/suffix, we need to handle the first segment specially\n if (routeSegment.prefixSegment || routeSegment.suffixSegment) {\n if (!baseSegment) return false\n\n const prefix = routeSegment.prefixSegment || ''\n const suffix = routeSegment.suffixSegment || ''\n\n // Check if the base segment starts with prefix and ends with suffix\n const baseValue = baseSegment.value\n if ('prefixSegment' in routeSegment) {\n if (!baseValue.startsWith(prefix)) {\n return false\n }\n }\n if ('suffixSegment' in routeSegment) {\n if (\n !baseSegments[baseSegments.length - 1]?.value.endsWith(suffix)\n ) {\n return false\n }\n }\n\n let rejoinedSplat = decodeURI(\n joinPaths(remainingBaseSegments.map((d) => d.value)),\n )\n\n // Remove the prefix and suffix from the rejoined splat\n if (prefix && rejoinedSplat.startsWith(prefix)) {\n rejoinedSplat = rejoinedSplat.slice(prefix.length)\n }\n\n if (suffix && rejoinedSplat.endsWith(suffix)) {\n rejoinedSplat = rejoinedSplat.slice(\n 0,\n rejoinedSplat.length - suffix.length,\n )\n }\n\n _splat = rejoinedSplat\n } else {\n // If no prefix/suffix, just rejoin the remaining segments\n _splat = decodeURI(\n joinPaths(remainingBaseSegments.map((d) => d.value)),\n )\n }\n\n // TODO: Deprecate *\n params['*'] = _splat\n params['_splat'] = _splat\n return true\n }\n\n if (routeSegment.type === SEGMENT_TYPE_PATHNAME) {\n if (routeSegment.value === '/' && !baseSegment?.value) {\n routeIndex++\n continue\n }\n\n if (baseSegment) {\n if (caseSensitive) {\n if (routeSegment.value !== baseSegment.value) {\n return false\n }\n } else if (\n routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()\n ) {\n return false\n }\n baseIndex++\n routeIndex++\n continue\n } else {\n return false\n }\n }\n\n if (routeSegment.type === SEGMENT_TYPE_PARAM) {\n if (!baseSegment) {\n return false\n }\n\n if (baseSegment.value === '/') {\n return false\n }\n\n let _paramValue = ''\n let matched = false\n\n // If this param has prefix/suffix, we need to extract the actual parameter value\n if (routeSegment.prefixSegment || routeSegment.suffixSegment) {\n const prefix = routeSegment.prefixSegment || ''\n const suffix = routeSegment.suffixSegment || ''\n\n // Check if the base segment starts with prefix and ends with suffix\n const baseValue = baseSegment.value\n if (prefix && !baseValue.startsWith(prefix)) {\n return false\n }\n if (suffix && !baseValue.endsWith(suffix)) {\n return false\n }\n\n let paramValue = baseValue\n if (prefix && paramValue.startsWith(prefix)) {\n paramValue = paramValue.slice(prefix.length)\n }\n if (suffix && paramValue.endsWith(suffix)) {\n paramValue = paramValue.slice(0, paramValue.length - suffix.length)\n }\n\n _paramValue = decodeURIComponent(paramValue)\n matched = true\n } else {\n // If no prefix/suffix, just decode the base segment value\n _paramValue = decodeURIComponent(baseSegment.value)\n matched = true\n }\n\n if (matched) {\n params[routeSegment.value.substring(1)] = _paramValue\n baseIndex++\n }\n\n routeIndex++\n continue\n }\n\n if (routeSegment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {\n // Optional parameters can be missing - don't fail the match\n if (!baseSegment) {\n // No base segment for optional param - skip this route segment\n routeIndex++\n continue\n }\n\n if (baseSegment.value === '/') {\n // Skip slash segments for optional params\n routeIndex++\n continue\n }\n\n let _paramValue = ''\n let matched = false\n\n // If this optional param has prefix/suffix, we need to extract the actual parameter value\n if (routeSegment.prefixSegment || routeSegment.suffixSegment) {\n const prefix = routeSegment.prefixSegment || ''\n const suffix = routeSegment.suffixSegment || ''\n\n // Check if the base segment starts with prefix and ends with suffix\n const baseValue = baseSegment.value\n if (\n (!prefix || baseValue.startsWith(prefix)) &&\n (!suffix || baseValue.endsWith(suffix))\n ) {\n let paramValue = baseValue\n if (prefix && paramValue.startsWith(prefix)) {\n paramValue = paramValue.slice(prefix.length)\n }\n if (suffix && paramValue.endsWith(suffix)) {\n paramValue = paramValue.slice(\n 0,\n paramValue.length - suffix.length,\n )\n }\n\n _paramValue = decodeURIComponent(paramValue)\n matched = true\n }\n } else {\n // For optional params without prefix/suffix, we need to check if the current\n // base segment should match this optional param or a later route segment\n\n // Look ahead to see if there's a later route segment that matches the current base segment\n let shouldMatchOptional = true\n for (\n let lookAhead = routeIndex + 1;\n lookAhead < routeSegments.length;\n lookAhead++\n ) {\n const futureRouteSegment = routeSegments[lookAhead]\n if (\n futureRouteSegment?.type === SEGMENT_TYPE_PATHNAME &&\n futureRouteSegment.value === baseSegment.value\n ) {\n // The current base segment matches a future pathname segment,\n // so we should skip this optional parameter\n shouldMatchOptional = false\n break\n }\n\n // If we encounter a required param or wildcard, stop looking ahead\n if (\n futureRouteSegment?.type === SEGMENT_TYPE_PARAM ||\n futureRouteSegment?.type === SEGMENT_TYPE_WILDCARD\n ) {\n if (baseSegments.length < routeSegments.length) {\n shouldMatchOptional = false\n }\n break\n }\n }\n\n if (shouldMatchOptional) {\n // If no prefix/suffix, just decode the base segment value\n _paramValue = decodeURIComponent(baseSegment.value)\n matched = true\n }\n }\n\n if (matched) {\n params[routeSegment.value.substring(1)] = _paramValue\n baseIndex++\n }\n\n routeIndex++\n continue\n }\n }\n\n // If we have base segments left but no route segments, it's a fuzzy match\n if (baseIndex < baseSegments.length && routeIndex >= routeSegments.length) {\n params['**'] = joinPaths(\n baseSegments.slice(baseIndex).map((d) => d.value),\n )\n return !!fuzzy && routeSegments[routeSegments.length - 1]?.value !== '/'\n }\n\n // If we have route segments left but no base segments, check if remaining are optional\n if (routeIndex < routeSegments.length && baseIndex >= baseSegments.length) {\n // Check if all remaining route segments are optional\n for (let i = routeIndex; i < routeSegments.length; i++) {\n if (routeSegments[i]?.type !== SEGMENT_TYPE_OPTIONAL_PARAM) {\n return false\n }\n }\n // All remaining are optional, so we can finish\n break\n }\n\n break\n }\n\n return true\n}\n"],"names":[],"mappings":";AAKO,MAAM,wBAAwB;AAC9B,MAAM,qBAAqB;AAC3B,MAAM,wBAAwB;AAC9B,MAAM,8BAA8B;AAepC,SAAS,UAAU,OAAkC;AAC1D,SAAO;AAAA,IACL,MACG,OAAO,CAAC,QAAQ;AACf,aAAO,QAAQ;AAAA,IACjB,CAAC,EACA,KAAK,GAAG;AAAA,EAAA;AAEf;AAEO,SAAS,UAAU,MAAc;AAEtC,SAAO,KAAK,QAAQ,WAAW,GAAG;AACpC;AAEO,SAAS,aAAa,MAAc;AACzC,SAAO,SAAS,MAAM,OAAO,KAAK,QAAQ,WAAW,EAAE;AACzD;AAEO,SAAS,cAAc,MAAc;AAC1C,SAAO,SAAS,MAAM,OAAO,KAAK,QAAQ,WAAW,EAAE;AACzD;AAEO,SAAS,SAAS,MAAc;AACrC,SAAO,cAAc,aAAa,IAAI,CAAC;AACzC;AAEO,SAAS,oBAAoB,OAAe,UAA0B;AAC3E,MAAI,OAAO,SAAS,GAAG,KAAK,UAAU,OAAO,UAAU,GAAG,QAAQ,KAAK;AACrE,WAAO,MAAM,MAAM,GAAG,EAAE;AAAA,EAC1B;AACA,SAAO;AACT;AAMO,SAAS,cACd,WACA,WACA,UACS;AACT,SACE,oBAAoB,WAAW,QAAQ,MACvC,oBAAoB,WAAW,QAAQ;AAE3C;AAqCA,SAAS,gBAAgB,SAA0B;AACjD,QAAM,EAAE,MAAM,MAAA,IAAU;AACxB,MAAI,SAAS,uBAAuB;AAClC,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,eAAe,cAAA,IAAkB;AAEzC,MAAI,SAAS,oBAAoB;AAC/B,UAAM,QAAQ,MAAM,UAAU,CAAC;AAC/B,QAAI,iBAAiB,eAAe;AAClC,aAAO,GAAG,aAAa,KAAK,KAAK,IAAI,aAAa;AAAA,IACpD,WAAW,eAAe;AACxB,aAAO,GAAG,aAAa,KAAK,KAAK;AAAA,IACnC,WAAW,eAAe;AACxB,aAAO,KAAK,KAAK,IAAI,aAAa;AAAA,IACpC;AAAA,EACF;AAEA,MAAI,SAAS,6BAA6B;AACxC,UAAM,QAAQ,MAAM,UAAU,CAAC;AAC/B,QAAI,iBAAiB,eAAe;AAClC,aAAO,GAAG,aAAa,MAAM,KAAK,IAAI,aAAa;AAAA,IACrD,WAAW,eAAe;AACxB,aAAO,GAAG,aAAa,MAAM,KAAK;AAAA,IACpC,WAAW,eAAe;AACxB,aAAO,MAAM,KAAK,IAAI,aAAa;AAAA,IACrC;AACA,WAAO,MAAM,KAAK;AAAA,EACpB;AAEA,MAAI,SAAS,uBAAuB;AAClC,QAAI,iBAAiB,eAAe;AAClC,aAAO,GAAG,aAAa,MAAM,aAAa;AAAA,IAC5C,WAAW,eAAe;AACxB,aAAO,GAAG,aAAa;AAAA,IACzB,WAAW,eAAe;AACxB,aAAO,MAAM,aAAa;AAAA,IAC5B;AAAA,EACF;AAGA,SAAO;AACT;AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AACF,GAAuB;AACrB,SAAO,eAAe,UAAU,MAAM,aAAa;AACnD,OAAK,eAAe,UAAU,IAAI,aAAa;AAE/C,MAAI,eAAe,cAAc,MAAM,UAAU,EAAE,MAAA;AACnD,QAAM,aAAa,cAAc,IAAI,UAAU;AAE/C,MAAI,aAAa,SAAS,KAAK,KAAK,YAAY,GAAG,UAAU,KAAK;AAChE,iBAAa,IAAA;AAAA,EACf;AAEA,WAAS,QAAQ,GAAG,SAAS,WAAW,QAAQ,QAAQ,QAAQ,SAAS;AACvE,UAAM,YAAY,WAAW,KAAK;AAClC,UAAM,QAAQ,UAAU;AACxB,QAAI,UAAU,KAAK;AACjB,UAAI,CAAC,OAAO;AAEV,uBAAe,CAAC,SAAS;AAAA,MAC3B,WAAW,UAAU,SAAS,GAAG;AAE/B,qBAAa,KAAK,SAAS;AAAA,MAC7B,MAAO;AAAA,IAGT,WAAW,UAAU,MAAM;AACzB,mBAAa,IAAA;AAAA,IACf,WAAW,UAAU,IAAK;AAAA,SAEnB;AACL,mBAAa,KAAK,SAAS;AAAA,IAC7B;AAAA,EACF;AAEA,MAAI,aAAa,SAAS,GAAG;AAC3B,QAAI,KAAK,YAAY,EAAG,UAAU,KAAK;AACrC,UAAI,kBAAkB,SAAS;AAC7B,qBAAa,IAAA;AAAA,MACf;AAAA,IACF,WAAW,kBAAkB,UAAU;AACrC,mBAAa,KAAK,EAAE,MAAM,uBAAuB,OAAO,KAAK;AAAA,IAC/D;AAAA,EACF;AAEA,QAAM,gBAAgB,aAAa,IAAI,eAAe;AACtD,QAAM,SAAS,UAAU,CAAC,UAAU,GAAG,aAAa,CAAC;AACrD,SAAO;AACT;AAGO,MAAM,gBAAgB,CAC3B,UACA,UAC2B;AAC3B,MAAI,CAAC,SAAU,QAAO,CAAA;AACtB,QAAM,SAAS,OAAO,IAAI,QAAQ;AAClC,MAAI,OAAQ,QAAO;AACnB,QAAM,SAAS,kBAAkB,QAAQ;AACzC,SAAO,IAAI,UAAU,MAAM;AAC3B,SAAO;AACT;AAEA,MAAM,WAAW;AACjB,MAAM,0BAA0B;AAChC,MAAM,mCACJ;AAEF,MAAM,cAAc;AACpB,MAAM,6BAA6B;AAmBnC,SAAS,kBAAkB,UAA0C;AACnE,aAAW,UAAU,QAAQ;AAE7B,QAAM,WAA2B,CAAA;AAEjC,MAAI,SAAS,MAAM,GAAG,CAAC,MAAM,KAAK;AAChC,eAAW,SAAS,UAAU,CAAC;AAC/B,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,IAAA,CACR;AAAA,EACH;AAEA,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAGA,QAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AAEhD,WAAS;AAAA,IACP,GAAG,MAAM,IAAI,CAAC,SAAkB;AAE9B,YAAM,sBAAsB,KAAK,MAAM,0BAA0B;AACjE,UAAI,qBAAqB;AACvB,cAAM,SAAS,oBAAoB,CAAC;AACpC,cAAM,SAAS,oBAAoB,CAAC;AACpC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO;AAAA,UACP,eAAe,UAAU;AAAA,UACzB,eAAe,UAAU;AAAA,QAAA;AAAA,MAE7B;AAGA,YAAM,2BAA2B,KAAK;AAAA,QACpC;AAAA,MAAA;AAEF,UAAI,0BAA0B;AAC5B,cAAM,SAAS,yBAAyB,CAAC;AACzC,cAAM,YAAY,yBAAyB,CAAC;AAC5C,cAAM,SAAS,yBAAyB,CAAC;AACzC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO;AAAA;AAAA,UACP,eAAe,UAAU;AAAA,UACzB,eAAe,UAAU;AAAA,QAAA;AAAA,MAE7B;AAGA,YAAM,mBAAmB,KAAK,MAAM,uBAAuB;AAC3D,UAAI,kBAAkB;AACpB,cAAM,SAAS,iBAAiB,CAAC;AACjC,cAAM,YAAY,iBAAiB,CAAC;AACpC,cAAM,SAAS,iBAAiB,CAAC;AACjC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO,KAAK;AAAA,UACZ,eAAe,UAAU;AAAA,UACzB,eAAe,UAAU;AAAA,QAAA;AAAA,MAE7B;AAGA,UAAI,SAAS,KAAK,IAAI,GAAG;AACvB,cAAM,YAAY,KAAK,UAAU,CAAC;AAClC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO,MAAM;AAAA,UACb,eAAe;AAAA,UACf,eAAe;AAAA,QAAA;AAAA,MAEnB;AAGA,UAAI,YAAY,KAAK,IAAI,GAAG;AAC1B,eAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO;AAAA,UACP,eAAe;AAAA,UACf,eAAe;AAAA,QAAA;AAAA,MAEnB;AAGA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO,KAAK,SAAS,KAAK,IACtB,KACG,MAAM,KAAK,EACX,IAAI,CAAC,YAAY,UAAU,OAAO,CAAC,EACnC,KAAK,KAAK,IACb,UAAU,IAAI;AAAA,MAAA;AAAA,IAEtB,CAAC;AAAA,EAAA;AAGH,MAAI,SAAS,MAAM,EAAE,MAAM,KAAK;AAC9B,eAAW,SAAS,UAAU,CAAC;AAC/B,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,IAAA,CACR;AAAA,EACH;AAEA,SAAO;AACT;AAiBO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkD;AAChD,QAAM,2BAA2B,cAAc,MAAM,UAAU;AAE/D,WAAS,YAAY,KAAkB;AACrC,UAAM,QAAQ,OAAO,GAAG;AACxB,UAAM,gBAAgB,OAAO,UAAU;AAEvC,QAAI,QAAQ,OAAO,QAAQ,UAAU;AAEnC,aAAO,gBAAgB,UAAU,KAAK,IAAI;AAAA,IAC5C,OAAO;AACL,aAAO,gBAAgB,gBAAgB,OAAO,aAAa,IAAI;AAAA,IACjE;AAAA,EACF;AAIA,MAAI,kBAAkB;AAEtB,QAAM,aAAsC,CAAA;AAC5C,QAAM,mBAAmB;AAAA,IACvB,yBAAyB,IAAI,CAAC,YAAY;AACxC,UAAI,QAAQ,SAAS,uBAAuB;AAC1C,eAAO,QAAQ;AAAA,MACjB;AAEA,UAAI,QAAQ,SAAS,uBAAuB;AAC1C,mBAAW,SAAS,OAAO;AAC3B,cAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,cAAM,gBAAgB,QAAQ,iBAAiB;AAG/C,YAAI,EAAE,YAAY,SAAS;AACzB,4BAAkB;AAElB,cAAI,gBAAgB;AAClB,mBAAO,GAAG,aAAa,GAAG,QAAQ,KAAK,GAAG,aAAa;AAAA,UACzD;AAEA,cAAI,iBAAiB,eAAe;AAClC,mBAAO,GAAG,aAAa,GAAG,aAAa;AAAA,UACzC;AACA,iBAAO;AAAA,QACT;AAEA,cAAM,QAAQ,YAAY,QAAQ;AAClC,YAAI,gBAAgB;AAClB,iBAAO,GAAG,aAAa,GAAG,QAAQ,KAAK,GAAG,SAAS,EAAE,GAAG,aAAa;AAAA,QACvE;AACA,eAAO,GAAG,aAAa,GAAG,KAAK,GAAG,aAAa;AAAA,MACjD;AAEA,UAAI,QAAQ,SAAS,oBAAoB;AACvC,cAAM,MAAM,QAAQ,MAAM,UAAU,CAAC;AACrC,YAAI,CAAC,mBAAmB,EAAE,OAAO,SAAS;AACxC,4BAAkB;AAAA,QACpB;AACA,mBAAW,GAAG,IAAI,OAAO,GAAG;AAE5B,cAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,cAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,YAAI,aAAa;AACf,gBAAM,QAAQ,YAAY,QAAQ,KAAK;AACvC,iBAAO,GAAG,aAAa,GAAG,QAAQ,KAAK,GAAG,SAAS,EAAE,GAAG,aAAa;AAAA,QACvE;AACA,eAAO,GAAG,aAAa,GAAG,YAAY,GAAG,KAAK,WAAW,GAAG,aAAa;AAAA,MAC3E;AAEA,UAAI,QAAQ,SAAS,6BAA6B;AAChD,cAAM,MAAM,QAAQ,MAAM,UAAU,CAAC;AAErC,cAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,cAAM,gBAAgB,QAAQ,iBAAiB;AAG/C,YAAI,EAAE,OAAO,WAAW,OAAO,GAAG,KAAK,MAAM;AAC3C,cAAI,gBAAgB;AAClB,mBAAO,GAAG,aAAa,GAAG,GAAG,GAAG,aAAa;AAAA,UAC/C;AAEA,cAAI,iBAAiB,eAAe;AAClC,mBAAO,GAAG,aAAa,GAAG,aAAa;AAAA,UACzC;AAEA,iBAAO;AAAA,QACT;AAEA,mBAAW,GAAG,IAAI,OAAO,GAAG;AAE5B,YAAI,aAAa;AACf,gBAAM,QAAQ,YAAY,QAAQ,KAAK;AACvC,iBAAO,GAAG,aAAa,GAAG,QAAQ,KAAK,GAAG,SAAS,EAAE,GAAG,aAAa;AAAA,QACvE;AACA,YAAI,gBAAgB;AAClB,iBAAO,GAAG,aAAa,GAAG,GAAG,GAAG,YAAY,GAAG,KAAK,EAAE,GAAG,aAAa;AAAA,QACxE;AACA,eAAO,GAAG,aAAa,GAAG,YAAY,GAAG,KAAK,EAAE,GAAG,aAAa;AAAA,MAClE;AAEA,aAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EAAA;AAEH,SAAO,EAAE,YAAY,kBAAkB,gBAAA;AACzC;AAEA,SAAS,gBAAgB,OAAe,eAAqC;AAC3E,MAAI,UAAU,mBAAmB,KAAK;AACtC,MAAI,eAAe;AACjB,eAAW,CAAC,aAAa,IAAI,KAAK,eAAe;AAC/C,gBAAU,QAAQ,WAAW,aAAa,IAAI;AAAA,IAChD;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,cACd,UACA,iBACA,eACA,YAC2B;AAC3B,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAIF,MAAI,cAAc,MAAM,CAAC,YAAY;AACnC;AAAA,EACF;AAEA,SAAO,cAAc,CAAA;AACvB;AAEO,SAAS,eACd,UACA,UACA,gBAAyB,OACzB;AAEA,QAAM,qBAAqB,gBAAgB,WAAW,SAAS,YAAA;AAC/D,QAAM,qBAAqB,gBAAgB,WAAW,SAAS,YAAA;AAE/D,UAAQ,MAAA;AAAA;AAAA;AAAA,IAGN,KAAK,uBAAuB;AAC1B,aAAO;AAAA;AAAA,IAGT,KAAK,uBAAuB;AAC1B,aAAO;AAAA;AAAA;AAAA,IAIT,KAAK,SAAS,SAAS,SAAS;AAC9B,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAMT,KAAK,mBAAmB,mBAAmB,MAAM,MAAM;AACrD,aAAO;AAAA;AAAA,IAGT,KAAK,mBAAmB,WAAW,kBAAkB;AACnD,aAAO,SAAS,MAAM,SAAS,MAAM;AAAA;AAAA,IAGvC;AACE,aAAO;AAAA,EAAA;AAEb;AAEO,SAAS,YACd,UACA,MACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF,GACA,YACoC;AAEpC,MAAI,aAAa,OAAO,CAAC,KAAK,WAAW,QAAQ,GAAG;AAClD,WAAO;AAAA,EACT;AAEA,SAAO,eAAe,UAAU,MAAM,aAAa;AAEnD,OAAK,eAAe,UAAU,GAAG,MAAM,GAAG,IAAI,aAAa;AAG3D,QAAM,eAAe;AAAA,IACnB,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAAA,IACtC;AAAA,EAAA;AAEF,QAAM,gBAAgB;AAAA,IACpB,GAAG,WAAW,GAAG,IAAI,KAAK,IAAI,EAAE;AAAA,IAChC;AAAA,EAAA;AAGF,QAAM,SAAiC,CAAA;AAEvC,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,SAAO,SAAS,SAAS;AAC3B;AAEA,SAAS,QACP,cACA,eACA,QACA,OACA,eACS;AACT,MAAI,YAAY;AAChB,MAAI,aAAa;AAEjB,SAAO,YAAY,aAAa,UAAU,aAAa,cAAc,QAAQ;AAC3E,UAAM,cAAc,aAAa,SAAS;AAC1C,UAAM,eAAe,cAAc,UAAU;AAE7C,QAAI,cAAc;AAChB,UAAI,aAAa,SAAS,uBAAuB;AAE/C,cAAM,wBAAwB,aAAa,MAAM,SAAS;AAE1D,YAAI;AAGJ,YAAI,aAAa,iBAAiB,aAAa,eAAe;AAC5D,cAAI,CAAC,YAAa,QAAO;AAEzB,gBAAM,SAAS,aAAa,iBAAiB;AAC7C,gBAAM,SAAS,aAAa,iBAAiB;AAG7C,gBAAM,YAAY,YAAY;AAC9B,cAAI,mBAAmB,cAAc;AACnC,gBAAI,CAAC,UAAU,WAAW,MAAM,GAAG;AACjC,qBAAO;AAAA,YACT;AAAA,UACF;AACA,cAAI,mBAAmB,cAAc;AACnC,gBACE,CAAC,aAAa,aAAa,SAAS,CAAC,GAAG,MAAM,SAAS,MAAM,GAC7D;AACA,qBAAO;AAAA,YACT;AAAA,UACF;AAEA,cAAI,gBAAgB;AAAA,YAClB,UAAU,sBAAsB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,UAAA;AAIrD,cAAI,UAAU,cAAc,WAAW,MAAM,GAAG;AAC9C,4BAAgB,cAAc,MAAM,OAAO,MAAM;AAAA,UACnD;AAEA,cAAI,UAAU,cAAc,SAAS,MAAM,GAAG;AAC5C,4BAAgB,cAAc;AAAA,cAC5B;AAAA,cACA,cAAc,SAAS,OAAO;AAAA,YAAA;AAAA,UAElC;AAEA,mBAAS;AAAA,QACX,OAAO;AAEL,mBAAS;AAAA,YACP,UAAU,sBAAsB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,UAAA;AAAA,QAEvD;AAGA,eAAO,GAAG,IAAI;AACd,eAAO,QAAQ,IAAI;AACnB,eAAO;AAAA,MACT;AAEA,UAAI,aAAa,SAAS,uBAAuB;AAC/C,YAAI,aAAa,UAAU,OAAO,CAAC,aAAa,OAAO;AACrD;AACA;AAAA,QACF;AAEA,YAAI,aAAa;AACf,cAAI,eAAe;AACjB,gBAAI,aAAa,UAAU,YAAY,OAAO;AAC5C,qBAAO;AAAA,YACT;AAAA,UACF,WACE,aAAa,MAAM,YAAA,MAAkB,YAAY,MAAM,eACvD;AACA,mBAAO;AAAA,UACT;AACA;AACA;AACA;AAAA,QACF,OAAO;AACL,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,UAAI,aAAa,SAAS,oBAAoB;AAC5C,YAAI,CAAC,aAAa;AAChB,iBAAO;AAAA,QACT;AAEA,YAAI,YAAY,UAAU,KAAK;AAC7B,iBAAO;AAAA,QACT;AAEA,YAAI,cAAc;AAClB,YAAI,UAAU;AAGd,YAAI,aAAa,iBAAiB,aAAa,eAAe;AAC5D,gBAAM,SAAS,aAAa,iBAAiB;AAC7C,gBAAM,SAAS,aAAa,iBAAiB;AAG7C,gBAAM,YAAY,YAAY;AAC9B,cAAI,UAAU,CAAC,UAAU,WAAW,MAAM,GAAG;AAC3C,mBAAO;AAAA,UACT;AACA,cAAI,UAAU,CAAC,UAAU,SAAS,MAAM,GAAG;AACzC,mBAAO;AAAA,UACT;AAEA,cAAI,aAAa;AACjB,cAAI,UAAU,WAAW,WAAW,MAAM,GAAG;AAC3C,yBAAa,WAAW,MAAM,OAAO,MAAM;AAAA,UAC7C;AACA,cAAI,UAAU,WAAW,SAAS,MAAM,GAAG;AACzC,yBAAa,WAAW,MAAM,GAAG,WAAW,SAAS,OAAO,MAAM;AAAA,UACpE;AAEA,wBAAc,mBAAmB,UAAU;AAC3C,oBAAU;AAAA,QACZ,OAAO;AAEL,wBAAc,mBAAmB,YAAY,KAAK;AAClD,oBAAU;AAAA,QACZ;AAEA,YAAI,SAAS;AACX,iBAAO,aAAa,MAAM,UAAU,CAAC,CAAC,IAAI;AAC1C;AAAA,QACF;AAEA;AACA;AAAA,MACF;AAEA,UAAI,aAAa,SAAS,6BAA6B;AAErD,YAAI,CAAC,aAAa;AAEhB;AACA;AAAA,QACF;AAEA,YAAI,YAAY,UAAU,KAAK;AAE7B;AACA;AAAA,QACF;AAEA,YAAI,cAAc;AAClB,YAAI,UAAU;AAGd,YAAI,aAAa,iBAAiB,aAAa,eAAe;AAC5D,gBAAM,SAAS,aAAa,iBAAiB;AAC7C,gBAAM,SAAS,aAAa,iBAAiB;AAG7C,gBAAM,YAAY,YAAY;AAC9B,eACG,CAAC,UAAU,UAAU,WAAW,MAAM,OACtC,CAAC,UAAU,UAAU,SAAS,MAAM,IACrC;AACA,gBAAI,aAAa;AACjB,gBAAI,UAAU,WAAW,WAAW,MAAM,GAAG;AAC3C,2BAAa,WAAW,MAAM,OAAO,MAAM;AAAA,YAC7C;AACA,gBAAI,UAAU,WAAW,SAAS,MAAM,GAAG;AACzC,2BAAa,WAAW;AAAA,gBACtB;AAAA,gBACA,WAAW,SAAS,OAAO;AAAA,cAAA;AAAA,YAE/B;AAEA,0BAAc,mBAAmB,UAAU;AAC3C,sBAAU;AAAA,UACZ;AAAA,QACF,OAAO;AAKL,cAAI,sBAAsB;AAC1B,mBACM,YAAY,aAAa,GAC7B,YAAY,cAAc,QAC1B,aACA;AACA,kBAAM,qBAAqB,cAAc,SAAS;AAClD,gBACE,oBAAoB,SAAS,yBAC7B,mBAAmB,UAAU,YAAY,OACzC;AAGA,oCAAsB;AACtB;AAAA,YACF;AAGA,gBACE,oBAAoB,SAAS,sBAC7B,oBAAoB,SAAS,uBAC7B;AACA,kBAAI,aAAa,SAAS,cAAc,QAAQ;AAC9C,sCAAsB;AAAA,cACxB;AACA;AAAA,YACF;AAAA,UACF;AAEA,cAAI,qBAAqB;AAEvB,0BAAc,mBAAmB,YAAY,KAAK;AAClD,sBAAU;AAAA,UACZ;AAAA,QACF;AAEA,YAAI,SAAS;AACX,iBAAO,aAAa,MAAM,UAAU,CAAC,CAAC,IAAI;AAC1C;AAAA,QACF;AAEA;AACA;AAAA,MACF;AAAA,IACF;AAGA,QAAI,YAAY,aAAa,UAAU,cAAc,cAAc,QAAQ;AACzE,aAAO,IAAI,IAAI;AAAA,QACb,aAAa,MAAM,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK;AAAA,MAAA;AAElD,aAAO,CAAC,CAAC,SAAS,cAAc,cAAc,SAAS,CAAC,GAAG,UAAU;AAAA,IACvE;AAGA,QAAI,aAAa,cAAc,UAAU,aAAa,aAAa,QAAQ;AAEzE,eAAS,IAAI,YAAY,IAAI,cAAc,QAAQ,KAAK;AACtD,YAAI,cAAc,CAAC,GAAG,SAAS,6BAA6B;AAC1D,iBAAO;AAAA,QACT;AAAA,MACF;AAEA;AAAA,IACF;AAEA;AAAA,EACF;AAEA,SAAO;AACT;"}
|
|
1
|
+
{"version":3,"file":"path.js","sources":["../../src/path.ts"],"sourcesContent":["import { last } from './utils'\nimport type { LRUCache } from './lru-cache'\nimport type { MatchLocation } from './RouterProvider'\nimport type { AnyPathParams } from './route'\n\nexport const SEGMENT_TYPE_PATHNAME = 0\nexport const SEGMENT_TYPE_PARAM = 1\nexport const SEGMENT_TYPE_WILDCARD = 2\nexport const SEGMENT_TYPE_OPTIONAL_PARAM = 3\n\nexport interface Segment {\n readonly type:\n | typeof SEGMENT_TYPE_PATHNAME\n | typeof SEGMENT_TYPE_PARAM\n | typeof SEGMENT_TYPE_WILDCARD\n | typeof SEGMENT_TYPE_OPTIONAL_PARAM\n readonly value: string\n readonly prefixSegment?: string\n readonly suffixSegment?: string\n // Indicates if there is a static segment after this required/optional param\n readonly hasStaticAfter?: boolean\n}\n\nexport function joinPaths(paths: Array<string | undefined>) {\n return cleanPath(\n paths\n .filter((val) => {\n return val !== undefined\n })\n .join('/'),\n )\n}\n\nexport function cleanPath(path: string) {\n // remove double slashes\n return path.replace(/\\/{2,}/g, '/')\n}\n\nexport function trimPathLeft(path: string) {\n return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\nexport function trimPathRight(path: string) {\n return path === '/' ? path : path.replace(/\\/{1,}$/, '')\n}\n\nexport function trimPath(path: string) {\n return trimPathRight(trimPathLeft(path))\n}\n\nexport function removeTrailingSlash(value: string, basepath: string): string {\n if (value?.endsWith('/') && value !== '/' && value !== `${basepath}/`) {\n return value.slice(0, -1)\n }\n return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\nexport function exactPathTest(\n pathName1: string,\n pathName2: string,\n basepath: string,\n): boolean {\n return (\n removeTrailingSlash(pathName1, basepath) ===\n removeTrailingSlash(pathName2, basepath)\n )\n}\n\n// When resolving relative paths, we treat all paths as if they are trailing slash\n// documents. All trailing slashes are removed after the path is resolved.\n// Here are a few examples:\n//\n// /a/b/c + ./d = /a/b/c/d\n// /a/b/c + ../d = /a/b/d\n// /a/b/c + ./d/ = /a/b/c/d\n// /a/b/c + ../d/ = /a/b/d\n// /a/b/c + ./ = /a/b/c\n//\n// Absolute paths that start with `/` short circuit the resolution process to the root\n// path.\n//\n// Here are some examples:\n//\n// /a/b/c + /d = /d\n// /a/b/c + /d/ = /d\n// /a/b/c + / = /\n//\n// Non-.-prefixed paths are still treated as relative paths, resolved like `./`\n//\n// Here are some examples:\n//\n// /a/b/c + d = /a/b/c/d\n// /a/b/c + d/ = /a/b/c/d\n// /a/b/c + d/e = /a/b/c/d/e\ninterface ResolvePathOptions {\n base: string\n to: string\n trailingSlash?: 'always' | 'never' | 'preserve'\n parseCache?: ParsePathnameCache\n}\n\nfunction segmentToString(segment: Segment): string {\n const { type, value } = segment\n if (type === SEGMENT_TYPE_PATHNAME) {\n return value\n }\n\n const { prefixSegment, suffixSegment } = segment\n\n if (type === SEGMENT_TYPE_PARAM) {\n const param = value.substring(1)\n if (prefixSegment && suffixSegment) {\n return `${prefixSegment}{$${param}}${suffixSegment}`\n } else if (prefixSegment) {\n return `${prefixSegment}{$${param}}`\n } else if (suffixSegment) {\n return `{$${param}}${suffixSegment}`\n }\n }\n\n if (type === SEGMENT_TYPE_OPTIONAL_PARAM) {\n const param = value.substring(1)\n if (prefixSegment && suffixSegment) {\n return `${prefixSegment}{-$${param}}${suffixSegment}`\n } else if (prefixSegment) {\n return `${prefixSegment}{-$${param}}`\n } else if (suffixSegment) {\n return `{-$${param}}${suffixSegment}`\n }\n return `{-$${param}}`\n }\n\n if (type === SEGMENT_TYPE_WILDCARD) {\n if (prefixSegment && suffixSegment) {\n return `${prefixSegment}{$}${suffixSegment}`\n } else if (prefixSegment) {\n return `${prefixSegment}{$}`\n } else if (suffixSegment) {\n return `{$}${suffixSegment}`\n }\n }\n\n // This case should never happen, should we throw instead?\n return value\n}\n\nexport function resolvePath({\n base,\n to,\n trailingSlash = 'never',\n parseCache,\n}: ResolvePathOptions) {\n let baseSegments = parseBasePathSegments(base, parseCache).slice()\n const toSegments = parseRoutePathSegments(to, parseCache)\n\n if (baseSegments.length > 1 && last(baseSegments)?.value === '/') {\n baseSegments.pop()\n }\n\n for (let index = 0, length = toSegments.length; index < length; index++) {\n const toSegment = toSegments[index]!\n const value = toSegment.value\n if (value === '/') {\n if (!index) {\n // Leading slash\n baseSegments = [toSegment]\n } else if (index === length - 1) {\n // Trailing Slash\n baseSegments.push(toSegment)\n } else {\n // ignore inter-slashes\n }\n } else if (value === '..') {\n baseSegments.pop()\n } else if (value === '.') {\n // ignore\n } else {\n baseSegments.push(toSegment)\n }\n }\n\n if (baseSegments.length > 1) {\n if (last(baseSegments)!.value === '/') {\n if (trailingSlash === 'never') {\n baseSegments.pop()\n }\n } else if (trailingSlash === 'always') {\n baseSegments.push({ type: SEGMENT_TYPE_PATHNAME, value: '/' })\n }\n }\n\n const segmentValues = baseSegments.map(segmentToString)\n // const joined = joinPaths([basepath, ...segmentValues])\n const joined = joinPaths(segmentValues)\n return joined\n}\n\nexport type ParsePathnameCache = LRUCache<string, ReadonlyArray<Segment>>\n\nexport const parseBasePathSegments = (\n pathname?: string,\n cache?: ParsePathnameCache,\n): ReadonlyArray<Segment> => parsePathname(pathname, cache, true)\n\nexport const parseRoutePathSegments = (\n pathname?: string,\n cache?: ParsePathnameCache,\n): ReadonlyArray<Segment> => parsePathname(pathname, cache, false)\n\nexport const parsePathname = (\n pathname?: string,\n cache?: ParsePathnameCache,\n basePathValues?: boolean,\n): ReadonlyArray<Segment> => {\n if (!pathname) return []\n const cached = cache?.get(pathname)\n if (cached) return cached\n const parsed = baseParsePathname(pathname, basePathValues)\n cache?.set(pathname, parsed)\n return parsed\n}\n\nconst PARAM_RE = /^\\$.{1,}$/ // $paramName\nconst PARAM_W_CURLY_BRACES_RE = /^(.*?)\\{(\\$[a-zA-Z_$][a-zA-Z0-9_$]*)\\}(.*)$/ // prefix{$paramName}suffix\nconst OPTIONAL_PARAM_W_CURLY_BRACES_RE =\n /^(.*?)\\{-(\\$[a-zA-Z_$][a-zA-Z0-9_$]*)\\}(.*)$/ // prefix{-$paramName}suffix\n\nconst WILDCARD_RE = /^\\$$/ // $\nconst WILDCARD_W_CURLY_BRACES_RE = /^(.*?)\\{\\$\\}(.*)$/ // prefix{$}suffix\n\n/**\n * Required: `/foo/$bar` ✅\n * Prefix and Suffix: `/foo/prefix${bar}suffix` ✅\n * Wildcard: `/foo/$` ✅\n * Wildcard with Prefix and Suffix: `/foo/prefix{$}suffix` ✅\n *\n * Optional param: `/foo/{-$bar}`\n * Optional param with Prefix and Suffix: `/foo/prefix{-$bar}suffix`\n\n * Future:\n * Optional named segment: `/foo/{bar}`\n * Optional named segment with Prefix and Suffix: `/foo/prefix{-bar}suffix`\n * Escape special characters:\n * - `/foo/[$]` - Static route\n * - `/foo/[$]{$foo} - Dynamic route with a static prefix of `$`\n * - `/foo/{$foo}[$]` - Dynamic route with a static suffix of `$`\n */\nfunction baseParsePathname(\n pathname: string,\n basePathValues?: boolean,\n): ReadonlyArray<Segment> {\n pathname = cleanPath(pathname)\n\n const segments: Array<Segment> = []\n\n if (pathname.slice(0, 1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: SEGMENT_TYPE_PATHNAME,\n value: '/',\n })\n }\n\n if (!pathname) {\n return segments\n }\n\n // Remove empty segments and '.' segments\n const split = pathname.split('/').filter(Boolean)\n\n segments.push(\n ...split.map((part): Segment => {\n // strip tailing underscore for non-nested paths\n const partToMatch =\n !basePathValues && part.slice(-1) === '_' ? part.slice(0, -1) : part\n\n // Check for wildcard with curly braces: prefix{$}suffix\n const wildcardBracesMatch = partToMatch.match(WILDCARD_W_CURLY_BRACES_RE)\n if (wildcardBracesMatch) {\n const prefix = wildcardBracesMatch[1]\n const suffix = wildcardBracesMatch[2]\n return {\n type: SEGMENT_TYPE_WILDCARD,\n value: '$',\n prefixSegment: prefix || undefined,\n suffixSegment: suffix || undefined,\n }\n }\n\n // Check for optional parameter format: prefix{-$paramName}suffix\n const optionalParamBracesMatch = partToMatch.match(\n OPTIONAL_PARAM_W_CURLY_BRACES_RE,\n )\n if (optionalParamBracesMatch) {\n const prefix = optionalParamBracesMatch[1]\n const paramName = optionalParamBracesMatch[2]!\n const suffix = optionalParamBracesMatch[3]\n return {\n type: SEGMENT_TYPE_OPTIONAL_PARAM,\n value: paramName, // Now just $paramName (no prefix)\n prefixSegment: prefix || undefined,\n suffixSegment: suffix || undefined,\n }\n }\n\n // Check for the new parameter format: prefix{$paramName}suffix\n const paramBracesMatch = partToMatch.match(PARAM_W_CURLY_BRACES_RE)\n if (paramBracesMatch) {\n const prefix = paramBracesMatch[1]\n const paramName = paramBracesMatch[2]\n const suffix = paramBracesMatch[3]\n return {\n type: SEGMENT_TYPE_PARAM,\n value: '' + paramName,\n prefixSegment: prefix || undefined,\n suffixSegment: suffix || undefined,\n }\n }\n\n // Check for bare parameter format: $paramName (without curly braces)\n if (PARAM_RE.test(partToMatch)) {\n const paramName = partToMatch.substring(1)\n return {\n type: SEGMENT_TYPE_PARAM,\n value: '$' + paramName,\n prefixSegment: undefined,\n suffixSegment: undefined,\n }\n }\n\n // Check for bare wildcard: $ (without curly braces)\n if (WILDCARD_RE.test(partToMatch)) {\n return {\n type: SEGMENT_TYPE_WILDCARD,\n value: '$',\n prefixSegment: undefined,\n suffixSegment: undefined,\n }\n }\n\n // Handle regular pathname segment\n return {\n type: SEGMENT_TYPE_PATHNAME,\n value: partToMatch.includes('%25')\n ? partToMatch\n .split('%25')\n .map((segment) => decodeURI(segment))\n .join('%25')\n : decodeURI(partToMatch),\n }\n }),\n )\n\n if (pathname.slice(-1) === '/') {\n pathname = pathname.substring(1)\n segments.push({\n type: SEGMENT_TYPE_PATHNAME,\n value: '/',\n })\n }\n\n return segments\n}\n\ninterface InterpolatePathOptions {\n path?: string\n params: Record<string, unknown>\n leaveWildcards?: boolean\n leaveParams?: boolean\n // Map of encoded chars to decoded chars (e.g. '%40' -> '@') that should remain decoded in path params\n decodeCharMap?: Map<string, string>\n parseCache?: ParsePathnameCache\n}\n\ntype InterPolatePathResult = {\n interpolatedPath: string\n usedParams: Record<string, unknown>\n isMissingParams: boolean // true if any params were not available when being looked up in the params object\n}\nexport function interpolatePath({\n path,\n params,\n leaveWildcards,\n leaveParams,\n decodeCharMap,\n parseCache,\n}: InterpolatePathOptions): InterPolatePathResult {\n const interpolatedPathSegments = parseRoutePathSegments(path, parseCache)\n\n function encodeParam(key: string): any {\n const value = params[key]\n const isValueString = typeof value === 'string'\n\n if (key === '*' || key === '_splat') {\n // the splat/catch-all routes shouldn't have the '/' encoded out\n return isValueString ? encodeURI(value) : value\n } else {\n return isValueString ? encodePathParam(value, decodeCharMap) : value\n }\n }\n\n // Tracking if any params are missing in the `params` object\n // when interpolating the path\n let isMissingParams = false\n\n const usedParams: Record<string, unknown> = {}\n const interpolatedPath = joinPaths(\n interpolatedPathSegments.map((segment) => {\n if (segment.type === SEGMENT_TYPE_PATHNAME) {\n return segment.value\n }\n\n if (segment.type === SEGMENT_TYPE_WILDCARD) {\n usedParams._splat = params._splat\n\n // TODO: Deprecate *\n usedParams['*'] = params._splat\n\n const segmentPrefix = segment.prefixSegment || ''\n const segmentSuffix = segment.suffixSegment || ''\n\n // Check if _splat parameter is missing\n if (!('_splat' in params)) {\n isMissingParams = true\n // For missing splat parameters, just return the prefix and suffix without the wildcard\n if (leaveWildcards) {\n return `${segmentPrefix}${segment.value}${segmentSuffix}`\n }\n // If there is a prefix or suffix, return them joined, otherwise omit the segment\n if (segmentPrefix || segmentSuffix) {\n return `${segmentPrefix}${segmentSuffix}`\n }\n return undefined\n }\n\n const value = encodeParam('_splat')\n if (leaveWildcards) {\n return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`\n }\n return `${segmentPrefix}${value}${segmentSuffix}`\n }\n\n if (segment.type === SEGMENT_TYPE_PARAM) {\n const key = segment.value.substring(1)\n if (!isMissingParams && !(key in params)) {\n isMissingParams = true\n }\n usedParams[key] = params[key]\n\n const segmentPrefix = segment.prefixSegment || ''\n const segmentSuffix = segment.suffixSegment || ''\n if (leaveParams) {\n const value = encodeParam(segment.value)\n return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`\n }\n return `${segmentPrefix}${encodeParam(key) ?? 'undefined'}${segmentSuffix}`\n }\n\n if (segment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {\n const key = segment.value.substring(1)\n\n const segmentPrefix = segment.prefixSegment || ''\n const segmentSuffix = segment.suffixSegment || ''\n\n // Check if optional parameter is missing or undefined\n if (!(key in params) || params[key] == null) {\n if (leaveWildcards) {\n return `${segmentPrefix}${key}${segmentSuffix}`\n }\n // For optional params with prefix/suffix, keep the prefix/suffix but omit the param\n if (segmentPrefix || segmentSuffix) {\n return `${segmentPrefix}${segmentSuffix}`\n }\n // If no prefix/suffix, omit the entire segment\n return undefined\n }\n\n usedParams[key] = params[key]\n\n if (leaveParams) {\n const value = encodeParam(segment.value)\n return `${segmentPrefix}${segment.value}${value ?? ''}${segmentSuffix}`\n }\n if (leaveWildcards) {\n return `${segmentPrefix}${key}${encodeParam(key) ?? ''}${segmentSuffix}`\n }\n return `${segmentPrefix}${encodeParam(key) ?? ''}${segmentSuffix}`\n }\n\n return segment.value\n }),\n )\n return { usedParams, interpolatedPath, isMissingParams }\n}\n\nfunction encodePathParam(value: string, decodeCharMap?: Map<string, string>) {\n let encoded = encodeURIComponent(value)\n if (decodeCharMap) {\n for (const [encodedChar, char] of decodeCharMap) {\n encoded = encoded.replaceAll(encodedChar, char)\n }\n }\n return encoded\n}\n\nexport function matchPathname(\n currentPathname: string,\n matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>,\n parseCache?: ParsePathnameCache,\n): AnyPathParams | undefined {\n const pathParams = matchByPath(currentPathname, matchLocation, parseCache)\n // const searchMatched = matchBySearch(location.search, matchLocation)\n\n if (matchLocation.to && !pathParams) {\n return\n }\n\n return pathParams ?? {}\n}\n\nexport function matchByPath(\n from: string,\n {\n to,\n fuzzy,\n caseSensitive,\n }: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,\n parseCache?: ParsePathnameCache,\n): Record<string, string> | undefined {\n const stringTo = to as string\n\n // Parse the from and to\n const baseSegments = parseBasePathSegments(\n from.startsWith('/') ? from : `/${from}`,\n parseCache,\n )\n const routeSegments = parseRoutePathSegments(\n stringTo.startsWith('/') ? stringTo : `/${stringTo}`,\n parseCache,\n )\n\n const params: Record<string, string> = {}\n\n const result = isMatch(\n baseSegments,\n routeSegments,\n params,\n fuzzy,\n caseSensitive,\n )\n\n return result ? params : undefined\n}\n\nfunction isMatch(\n baseSegments: ReadonlyArray<Segment>,\n routeSegments: ReadonlyArray<Segment>,\n params: Record<string, string>,\n fuzzy?: boolean,\n caseSensitive?: boolean,\n): boolean {\n let baseIndex = 0\n let routeIndex = 0\n\n while (baseIndex < baseSegments.length || routeIndex < routeSegments.length) {\n const baseSegment = baseSegments[baseIndex]\n const routeSegment = routeSegments[routeIndex]\n\n if (routeSegment) {\n if (routeSegment.type === SEGMENT_TYPE_WILDCARD) {\n // Capture all remaining segments for a wildcard\n const remainingBaseSegments = baseSegments.slice(baseIndex)\n\n let _splat: string\n\n // If this is a wildcard with prefix/suffix, we need to handle the first segment specially\n if (routeSegment.prefixSegment || routeSegment.suffixSegment) {\n if (!baseSegment) return false\n\n const prefix = routeSegment.prefixSegment || ''\n const suffix = routeSegment.suffixSegment || ''\n\n // Check if the base segment starts with prefix and ends with suffix\n const baseValue = baseSegment.value\n if ('prefixSegment' in routeSegment) {\n if (!baseValue.startsWith(prefix)) {\n return false\n }\n }\n if ('suffixSegment' in routeSegment) {\n if (\n !baseSegments[baseSegments.length - 1]?.value.endsWith(suffix)\n ) {\n return false\n }\n }\n\n let rejoinedSplat = decodeURI(\n joinPaths(remainingBaseSegments.map((d) => d.value)),\n )\n\n // Remove the prefix and suffix from the rejoined splat\n if (prefix && rejoinedSplat.startsWith(prefix)) {\n rejoinedSplat = rejoinedSplat.slice(prefix.length)\n }\n\n if (suffix && rejoinedSplat.endsWith(suffix)) {\n rejoinedSplat = rejoinedSplat.slice(\n 0,\n rejoinedSplat.length - suffix.length,\n )\n }\n\n _splat = rejoinedSplat\n } else {\n // If no prefix/suffix, just rejoin the remaining segments\n _splat = decodeURI(\n joinPaths(remainingBaseSegments.map((d) => d.value)),\n )\n }\n\n // TODO: Deprecate *\n params['*'] = _splat\n params['_splat'] = _splat\n return true\n }\n\n if (routeSegment.type === SEGMENT_TYPE_PATHNAME) {\n if (routeSegment.value === '/' && !baseSegment?.value) {\n routeIndex++\n continue\n }\n\n if (baseSegment) {\n if (caseSensitive) {\n if (routeSegment.value !== baseSegment.value) {\n return false\n }\n } else if (\n routeSegment.value.toLowerCase() !== baseSegment.value.toLowerCase()\n ) {\n return false\n }\n baseIndex++\n routeIndex++\n continue\n } else {\n return false\n }\n }\n\n if (routeSegment.type === SEGMENT_TYPE_PARAM) {\n if (!baseSegment) {\n return false\n }\n\n if (baseSegment.value === '/') {\n return false\n }\n\n let _paramValue = ''\n let matched = false\n\n // If this param has prefix/suffix, we need to extract the actual parameter value\n if (routeSegment.prefixSegment || routeSegment.suffixSegment) {\n const prefix = routeSegment.prefixSegment || ''\n const suffix = routeSegment.suffixSegment || ''\n\n // Check if the base segment starts with prefix and ends with suffix\n const baseValue = baseSegment.value\n if (prefix && !baseValue.startsWith(prefix)) {\n return false\n }\n if (suffix && !baseValue.endsWith(suffix)) {\n return false\n }\n\n let paramValue = baseValue\n if (prefix && paramValue.startsWith(prefix)) {\n paramValue = paramValue.slice(prefix.length)\n }\n if (suffix && paramValue.endsWith(suffix)) {\n paramValue = paramValue.slice(0, paramValue.length - suffix.length)\n }\n\n _paramValue = decodeURIComponent(paramValue)\n matched = true\n } else {\n // If no prefix/suffix, just decode the base segment value\n _paramValue = decodeURIComponent(baseSegment.value)\n matched = true\n }\n\n if (matched) {\n params[routeSegment.value.substring(1)] = _paramValue\n baseIndex++\n }\n\n routeIndex++\n continue\n }\n\n if (routeSegment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {\n // Optional parameters can be missing - don't fail the match\n if (!baseSegment) {\n // No base segment for optional param - skip this route segment\n routeIndex++\n continue\n }\n\n if (baseSegment.value === '/') {\n // Skip slash segments for optional params\n routeIndex++\n continue\n }\n\n let _paramValue = ''\n let matched = false\n\n // If this optional param has prefix/suffix, we need to extract the actual parameter value\n if (routeSegment.prefixSegment || routeSegment.suffixSegment) {\n const prefix = routeSegment.prefixSegment || ''\n const suffix = routeSegment.suffixSegment || ''\n\n // Check if the base segment starts with prefix and ends with suffix\n const baseValue = baseSegment.value\n if (\n (!prefix || baseValue.startsWith(prefix)) &&\n (!suffix || baseValue.endsWith(suffix))\n ) {\n let paramValue = baseValue\n if (prefix && paramValue.startsWith(prefix)) {\n paramValue = paramValue.slice(prefix.length)\n }\n if (suffix && paramValue.endsWith(suffix)) {\n paramValue = paramValue.slice(\n 0,\n paramValue.length - suffix.length,\n )\n }\n\n _paramValue = decodeURIComponent(paramValue)\n matched = true\n }\n } else {\n // For optional params without prefix/suffix, we need to check if the current\n // base segment should match this optional param or a later route segment\n\n // Look ahead to see if there's a later route segment that matches the current base segment\n let shouldMatchOptional = true\n for (\n let lookAhead = routeIndex + 1;\n lookAhead < routeSegments.length;\n lookAhead++\n ) {\n const futureRouteSegment = routeSegments[lookAhead]\n if (\n futureRouteSegment?.type === SEGMENT_TYPE_PATHNAME &&\n futureRouteSegment.value === baseSegment.value\n ) {\n // The current base segment matches a future pathname segment,\n // so we should skip this optional parameter\n shouldMatchOptional = false\n break\n }\n\n // If we encounter a required param or wildcard, stop looking ahead\n if (\n futureRouteSegment?.type === SEGMENT_TYPE_PARAM ||\n futureRouteSegment?.type === SEGMENT_TYPE_WILDCARD\n ) {\n if (baseSegments.length < routeSegments.length) {\n shouldMatchOptional = false\n }\n break\n }\n }\n\n if (shouldMatchOptional) {\n // If no prefix/suffix, just decode the base segment value\n _paramValue = decodeURIComponent(baseSegment.value)\n matched = true\n }\n }\n\n if (matched) {\n params[routeSegment.value.substring(1)] = _paramValue\n baseIndex++\n }\n\n routeIndex++\n continue\n }\n }\n\n // If we have base segments left but no route segments, it's a fuzzy match\n if (baseIndex < baseSegments.length && routeIndex >= routeSegments.length) {\n params['**'] = joinPaths(\n baseSegments.slice(baseIndex).map((d) => d.value),\n )\n return !!fuzzy && routeSegments[routeSegments.length - 1]?.value !== '/'\n }\n\n // If we have route segments left but no base segments, check if remaining are optional\n if (routeIndex < routeSegments.length && baseIndex >= baseSegments.length) {\n // Check if all remaining route segments are optional\n for (let i = routeIndex; i < routeSegments.length; i++) {\n if (routeSegments[i]?.type !== SEGMENT_TYPE_OPTIONAL_PARAM) {\n return false\n }\n }\n // All remaining are optional, so we can finish\n break\n }\n\n break\n }\n\n return true\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RouteLike } from './route.js';
|
|
2
|
+
export type ProcessRouteTreeResult<TRouteLike extends RouteLike> = {
|
|
3
|
+
routesById: Record<string, TRouteLike>;
|
|
4
|
+
routesByPath: Record<string, TRouteLike>;
|
|
5
|
+
flatRoutes: Array<TRouteLike>;
|
|
6
|
+
};
|
|
7
|
+
export declare function processRouteTree<TRouteLike extends RouteLike>({ routeTree, initRoute, }: {
|
|
8
|
+
routeTree: TRouteLike;
|
|
9
|
+
initRoute?: (route: TRouteLike, index: number) => void;
|
|
10
|
+
}): ProcessRouteTreeResult<TRouteLike>;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import invariant from "tiny-invariant";
|
|
2
|
+
import { trimPathRight, trimPathLeft, parseRoutePathSegments, SEGMENT_TYPE_PATHNAME, SEGMENT_TYPE_PARAM, SEGMENT_TYPE_OPTIONAL_PARAM } from "./path.js";
|
|
3
|
+
const SLASH_SCORE = 0.75;
|
|
4
|
+
const STATIC_SEGMENT_SCORE = 1;
|
|
5
|
+
const REQUIRED_PARAM_BASE_SCORE = 0.5;
|
|
6
|
+
const OPTIONAL_PARAM_BASE_SCORE = 0.4;
|
|
7
|
+
const WILDCARD_PARAM_BASE_SCORE = 0.25;
|
|
8
|
+
const STATIC_AFTER_DYNAMIC_BONUS_SCORE = 0.2;
|
|
9
|
+
const BOTH_PRESENCE_BASE_SCORE = 0.05;
|
|
10
|
+
const PREFIX_PRESENCE_BASE_SCORE = 0.02;
|
|
11
|
+
const SUFFIX_PRESENCE_BASE_SCORE = 0.01;
|
|
12
|
+
const PREFIX_LENGTH_SCORE_MULTIPLIER = 2e-4;
|
|
13
|
+
const SUFFIX_LENGTH_SCORE_MULTIPLIER = 1e-4;
|
|
14
|
+
function handleParam(segment, baseScore) {
|
|
15
|
+
if (segment.prefixSegment && segment.suffixSegment) {
|
|
16
|
+
return baseScore + BOTH_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
|
|
17
|
+
}
|
|
18
|
+
if (segment.prefixSegment) {
|
|
19
|
+
return baseScore + PREFIX_PRESENCE_BASE_SCORE + PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length;
|
|
20
|
+
}
|
|
21
|
+
if (segment.suffixSegment) {
|
|
22
|
+
return baseScore + SUFFIX_PRESENCE_BASE_SCORE + SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length;
|
|
23
|
+
}
|
|
24
|
+
return baseScore;
|
|
25
|
+
}
|
|
26
|
+
function sortRoutes(routes) {
|
|
27
|
+
const scoredRoutes = [];
|
|
28
|
+
routes.forEach((d, i) => {
|
|
29
|
+
if (d.isRoot || !d.path) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const trimmed = trimPathLeft(d.fullPath);
|
|
33
|
+
let parsed = parseRoutePathSegments(trimmed);
|
|
34
|
+
let skip = 0;
|
|
35
|
+
while (parsed.length > skip + 1 && parsed[skip]?.value === "/") {
|
|
36
|
+
skip++;
|
|
37
|
+
}
|
|
38
|
+
if (skip > 0) parsed = parsed.slice(skip);
|
|
39
|
+
let optionalParamCount = 0;
|
|
40
|
+
let hasStaticAfter = false;
|
|
41
|
+
const scores = parsed.map((segment, index) => {
|
|
42
|
+
if (segment.value === "/") {
|
|
43
|
+
return SLASH_SCORE;
|
|
44
|
+
}
|
|
45
|
+
if (segment.type === SEGMENT_TYPE_PATHNAME) {
|
|
46
|
+
return STATIC_SEGMENT_SCORE;
|
|
47
|
+
}
|
|
48
|
+
let baseScore = void 0;
|
|
49
|
+
if (segment.type === SEGMENT_TYPE_PARAM) {
|
|
50
|
+
baseScore = REQUIRED_PARAM_BASE_SCORE;
|
|
51
|
+
} else if (segment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {
|
|
52
|
+
baseScore = OPTIONAL_PARAM_BASE_SCORE;
|
|
53
|
+
optionalParamCount++;
|
|
54
|
+
} else {
|
|
55
|
+
baseScore = WILDCARD_PARAM_BASE_SCORE;
|
|
56
|
+
}
|
|
57
|
+
for (let i2 = index + 1; i2 < parsed.length; i2++) {
|
|
58
|
+
const nextSegment = parsed[i2];
|
|
59
|
+
if (nextSegment.type === SEGMENT_TYPE_PATHNAME && nextSegment.value !== "/") {
|
|
60
|
+
hasStaticAfter = true;
|
|
61
|
+
return handleParam(
|
|
62
|
+
segment,
|
|
63
|
+
baseScore + STATIC_AFTER_DYNAMIC_BONUS_SCORE
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return handleParam(segment, baseScore);
|
|
68
|
+
});
|
|
69
|
+
scoredRoutes.push({
|
|
70
|
+
child: d,
|
|
71
|
+
trimmed,
|
|
72
|
+
parsed,
|
|
73
|
+
index: i,
|
|
74
|
+
scores,
|
|
75
|
+
optionalParamCount,
|
|
76
|
+
hasStaticAfter
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
const flatRoutes = scoredRoutes.sort((a, b) => {
|
|
80
|
+
const minLength = Math.min(a.scores.length, b.scores.length);
|
|
81
|
+
for (let i = 0; i < minLength; i++) {
|
|
82
|
+
if (a.scores[i] !== b.scores[i]) {
|
|
83
|
+
return b.scores[i] - a.scores[i];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (a.scores.length !== b.scores.length) {
|
|
87
|
+
if (a.optionalParamCount !== b.optionalParamCount) {
|
|
88
|
+
if (a.hasStaticAfter === b.hasStaticAfter) {
|
|
89
|
+
return a.optionalParamCount - b.optionalParamCount;
|
|
90
|
+
} else if (a.hasStaticAfter && !b.hasStaticAfter) {
|
|
91
|
+
return -1;
|
|
92
|
+
} else if (!a.hasStaticAfter && b.hasStaticAfter) {
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return b.scores.length - a.scores.length;
|
|
97
|
+
}
|
|
98
|
+
for (let i = 0; i < minLength; i++) {
|
|
99
|
+
if (a.parsed[i].value !== b.parsed[i].value) {
|
|
100
|
+
return a.parsed[i].value > b.parsed[i].value ? 1 : -1;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return a.index - b.index;
|
|
104
|
+
}).map((d, i) => {
|
|
105
|
+
d.child.rank = i;
|
|
106
|
+
return d.child;
|
|
107
|
+
});
|
|
108
|
+
return flatRoutes;
|
|
109
|
+
}
|
|
110
|
+
function processRouteTree({
|
|
111
|
+
routeTree,
|
|
112
|
+
initRoute
|
|
113
|
+
}) {
|
|
114
|
+
const routesById = {};
|
|
115
|
+
const routesByPath = {};
|
|
116
|
+
const recurseRoutes = (childRoutes) => {
|
|
117
|
+
childRoutes.forEach((childRoute, i) => {
|
|
118
|
+
initRoute?.(childRoute, i);
|
|
119
|
+
const existingRoute = routesById[childRoute.id];
|
|
120
|
+
invariant(
|
|
121
|
+
!existingRoute,
|
|
122
|
+
`Duplicate routes found with id: ${String(childRoute.id)}`
|
|
123
|
+
);
|
|
124
|
+
routesById[childRoute.id] = childRoute;
|
|
125
|
+
if (!childRoute.isRoot && childRoute.path) {
|
|
126
|
+
const trimmedFullPath = trimPathRight(childRoute.fullPath);
|
|
127
|
+
if (!routesByPath[trimmedFullPath] || childRoute.fullPath.endsWith("/")) {
|
|
128
|
+
routesByPath[trimmedFullPath] = childRoute;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const children = childRoute.children;
|
|
132
|
+
if (children?.length) {
|
|
133
|
+
recurseRoutes(children);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
recurseRoutes([routeTree]);
|
|
138
|
+
const flatRoutes = sortRoutes(Object.values(routesById));
|
|
139
|
+
return { routesById, routesByPath, flatRoutes };
|
|
140
|
+
}
|
|
141
|
+
export {
|
|
142
|
+
processRouteTree
|
|
143
|
+
};
|
|
144
|
+
//# sourceMappingURL=process-route-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-route-tree.js","sources":["../../src/process-route-tree.ts"],"sourcesContent":["import invariant from 'tiny-invariant'\nimport {\n SEGMENT_TYPE_OPTIONAL_PARAM,\n SEGMENT_TYPE_PARAM,\n SEGMENT_TYPE_PATHNAME,\n parseRoutePathSegments,\n trimPathLeft,\n trimPathRight,\n} from './path'\nimport type { Segment } from './path'\nimport type { RouteLike } from './route'\n\nconst SLASH_SCORE = 0.75\nconst STATIC_SEGMENT_SCORE = 1\nconst REQUIRED_PARAM_BASE_SCORE = 0.5\nconst OPTIONAL_PARAM_BASE_SCORE = 0.4\nconst WILDCARD_PARAM_BASE_SCORE = 0.25\nconst STATIC_AFTER_DYNAMIC_BONUS_SCORE = 0.2\nconst BOTH_PRESENCE_BASE_SCORE = 0.05\nconst PREFIX_PRESENCE_BASE_SCORE = 0.02\nconst SUFFIX_PRESENCE_BASE_SCORE = 0.01\nconst PREFIX_LENGTH_SCORE_MULTIPLIER = 0.0002\nconst SUFFIX_LENGTH_SCORE_MULTIPLIER = 0.0001\n\nfunction handleParam(segment: Segment, baseScore: number) {\n if (segment.prefixSegment && segment.suffixSegment) {\n return (\n baseScore +\n BOTH_PRESENCE_BASE_SCORE +\n PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length +\n SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length\n )\n }\n\n if (segment.prefixSegment) {\n return (\n baseScore +\n PREFIX_PRESENCE_BASE_SCORE +\n PREFIX_LENGTH_SCORE_MULTIPLIER * segment.prefixSegment.length\n )\n }\n\n if (segment.suffixSegment) {\n return (\n baseScore +\n SUFFIX_PRESENCE_BASE_SCORE +\n SUFFIX_LENGTH_SCORE_MULTIPLIER * segment.suffixSegment.length\n )\n }\n\n return baseScore\n}\n\nfunction sortRoutes<TRouteLike extends RouteLike>(\n routes: ReadonlyArray<TRouteLike>,\n): Array<TRouteLike> {\n const scoredRoutes: Array<{\n child: TRouteLike\n trimmed: string\n parsed: ReadonlyArray<Segment>\n index: number\n scores: Array<number>\n hasStaticAfter: boolean\n optionalParamCount: number\n }> = []\n\n routes.forEach((d, i) => {\n if (d.isRoot || !d.path) {\n return\n }\n\n const trimmed = trimPathLeft(d.fullPath)\n let parsed = parseRoutePathSegments(trimmed)\n\n // Removes the leading slash if it is not the only remaining segment\n let skip = 0\n while (parsed.length > skip + 1 && parsed[skip]?.value === '/') {\n skip++\n }\n if (skip > 0) parsed = parsed.slice(skip)\n\n let optionalParamCount = 0\n let hasStaticAfter = false\n const scores = parsed.map((segment, index) => {\n if (segment.value === '/') {\n return SLASH_SCORE\n }\n\n if (segment.type === SEGMENT_TYPE_PATHNAME) {\n return STATIC_SEGMENT_SCORE\n }\n\n let baseScore: number | undefined = undefined\n if (segment.type === SEGMENT_TYPE_PARAM) {\n baseScore = REQUIRED_PARAM_BASE_SCORE\n } else if (segment.type === SEGMENT_TYPE_OPTIONAL_PARAM) {\n baseScore = OPTIONAL_PARAM_BASE_SCORE\n optionalParamCount++\n } else {\n baseScore = WILDCARD_PARAM_BASE_SCORE\n }\n\n // if there is any static segment (that is not an index) after a required / optional param,\n // we will boost this param so it ranks higher than a required/optional param without a static segment after it\n // JUST FOR SORTING, NOT FOR MATCHING\n for (let i = index + 1; i < parsed.length; i++) {\n const nextSegment = parsed[i]!\n if (\n nextSegment.type === SEGMENT_TYPE_PATHNAME &&\n nextSegment.value !== '/'\n ) {\n hasStaticAfter = true\n return handleParam(\n segment,\n baseScore + STATIC_AFTER_DYNAMIC_BONUS_SCORE,\n )\n }\n }\n\n return handleParam(segment, baseScore)\n })\n\n scoredRoutes.push({\n child: d,\n trimmed,\n parsed,\n index: i,\n scores,\n optionalParamCount,\n hasStaticAfter,\n })\n })\n\n const flatRoutes = scoredRoutes\n .sort((a, b) => {\n const minLength = Math.min(a.scores.length, b.scores.length)\n\n // Sort by segment-by-segment score comparison ONLY for the common prefix\n for (let i = 0; i < minLength; i++) {\n if (a.scores[i] !== b.scores[i]) {\n return b.scores[i]! - a.scores[i]!\n }\n }\n\n // If all common segments have equal scores, then consider length and specificity\n if (a.scores.length !== b.scores.length) {\n // If different number of optional parameters, fewer optional parameters wins (more specific)\n // only if both or none of the routes has static segments after the params\n if (a.optionalParamCount !== b.optionalParamCount) {\n if (a.hasStaticAfter === b.hasStaticAfter) {\n return a.optionalParamCount - b.optionalParamCount\n } else if (a.hasStaticAfter && !b.hasStaticAfter) {\n return -1\n } else if (!a.hasStaticAfter && b.hasStaticAfter) {\n return 1\n }\n }\n\n // If same number of optional parameters, longer path wins (for static segments)\n return b.scores.length - a.scores.length\n }\n\n // Sort by min available parsed value for alphabetical ordering\n for (let i = 0; i < minLength; i++) {\n if (a.parsed[i]!.value !== b.parsed[i]!.value) {\n return a.parsed[i]!.value > b.parsed[i]!.value ? 1 : -1\n }\n }\n\n // Sort by original index\n return a.index - b.index\n })\n .map((d, i) => {\n d.child.rank = i\n return d.child\n })\n\n return flatRoutes\n}\n\nexport type ProcessRouteTreeResult<TRouteLike extends RouteLike> = {\n routesById: Record<string, TRouteLike>\n routesByPath: Record<string, TRouteLike>\n flatRoutes: Array<TRouteLike>\n}\n\nexport function processRouteTree<TRouteLike extends RouteLike>({\n routeTree,\n initRoute,\n}: {\n routeTree: TRouteLike\n initRoute?: (route: TRouteLike, index: number) => void\n}): ProcessRouteTreeResult<TRouteLike> {\n const routesById = {} as Record<string, TRouteLike>\n const routesByPath = {} as Record<string, TRouteLike>\n\n const recurseRoutes = (childRoutes: Array<TRouteLike>) => {\n childRoutes.forEach((childRoute, i) => {\n initRoute?.(childRoute, i)\n\n const existingRoute = routesById[childRoute.id]\n\n invariant(\n !existingRoute,\n `Duplicate routes found with id: ${String(childRoute.id)}`,\n )\n\n routesById[childRoute.id] = childRoute\n\n if (!childRoute.isRoot && childRoute.path) {\n const trimmedFullPath = trimPathRight(childRoute.fullPath)\n if (\n !routesByPath[trimmedFullPath] ||\n childRoute.fullPath.endsWith('/')\n ) {\n routesByPath[trimmedFullPath] = childRoute\n }\n }\n\n const children = childRoute.children as Array<TRouteLike>\n\n if (children?.length) {\n recurseRoutes(children)\n }\n })\n }\n\n recurseRoutes([routeTree])\n\n const flatRoutes = sortRoutes(Object.values(routesById))\n\n return { routesById, routesByPath, flatRoutes }\n}\n"],"names":["i"],"mappings":"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"}
|
package/dist/esm/redirect.js
CHANGED
package/dist/esm/redirect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirect.js","sources":["../../src/redirect.ts"],"sourcesContent":["import type { NavigateOptions } from './link'\nimport type { AnyRouter, RegisteredRouter } from './router'\n\nexport type AnyRedirect = Redirect<any, any, any, any, any>\n\n/**\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)\n */\nexport type Redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = Response & {\n options: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n redirectHandled?: boolean\n}\n\nexport type RedirectOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = {\n href?: string\n /**\n * @deprecated Use `statusCode` instead\n **/\n code?: number\n /**\n * The HTTP status code to use when redirecting.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#statuscode-property)\n */\n statusCode?: number\n /**\n * If provided, will throw the redirect object instead of returning it. This can be useful in places where `throwing` in a function might cause it to have a return type of `never`. In that case, you can use `redirect({ throw: true })` to throw the redirect object instead of returning it.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#throw-property)\n */\n throw?: any\n /**\n * The HTTP headers to use when redirecting.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#headers-property)\n */\n headers?: HeadersInit\n} & NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport type ResolvedRedirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport function redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n const TTo extends string | undefined = '.',\n const TFrom extends string = string,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n opts: RedirectOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n): Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> {\n opts.statusCode = opts.statusCode || opts.code || 307\n\n if (!opts.reloadDocument && typeof opts.href === 'string') {\n try {\n new URL(opts.href)\n opts.reloadDocument = true\n } catch {}\n }\n\n const headers = new Headers(opts.headers
|
|
1
|
+
{"version":3,"file":"redirect.js","sources":["../../src/redirect.ts"],"sourcesContent":["import type { NavigateOptions } from './link'\nimport type { AnyRouter, RegisteredRouter } from './router'\n\nexport type AnyRedirect = Redirect<any, any, any, any, any>\n\n/**\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType)\n */\nexport type Redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = Response & {\n options: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n redirectHandled?: boolean\n}\n\nexport type RedirectOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '.',\n> = {\n href?: string\n /**\n * @deprecated Use `statusCode` instead\n **/\n code?: number\n /**\n * The HTTP status code to use when redirecting.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#statuscode-property)\n */\n statusCode?: number\n /**\n * If provided, will throw the redirect object instead of returning it. This can be useful in places where `throwing` in a function might cause it to have a return type of `never`. In that case, you can use `redirect({ throw: true })` to throw the redirect object instead of returning it.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#throw-property)\n */\n throw?: any\n /**\n * The HTTP headers to use when redirecting.\n * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RedirectType#headers-property)\n */\n headers?: HeadersInit\n} & NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport type ResolvedRedirect<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string = '',\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n\nexport function redirect<\n TRouter extends AnyRouter = RegisteredRouter,\n const TTo extends string | undefined = '.',\n const TFrom extends string = string,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n opts: RedirectOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n): Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> {\n opts.statusCode = opts.statusCode || opts.code || 307\n\n if (!opts.reloadDocument && typeof opts.href === 'string') {\n try {\n new URL(opts.href)\n opts.reloadDocument = true\n } catch {}\n }\n\n const headers = new Headers(opts.headers)\n if (opts.href && headers.get('Location') === null) {\n headers.set('Location', opts.href)\n }\n\n const response = new Response(null, {\n status: opts.statusCode,\n headers,\n })\n\n ;(response as Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>).options =\n opts\n\n if (opts.throw) {\n throw response\n }\n\n return response as Redirect<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>\n}\n\nexport function isRedirect(obj: any): obj is AnyRedirect {\n return obj instanceof Response && !!(obj as any).options\n}\n\nexport function isResolvedRedirect(\n obj: any,\n): obj is AnyRedirect & { options: { href: string } } {\n return isRedirect(obj) && !!obj.options.href\n}\n\nexport function parseRedirect(obj: any) {\n if (obj !== null && typeof obj === 'object' && obj.isSerializedRedirect) {\n return redirect(obj)\n }\n\n return undefined\n}\n"],"names":[],"mappings":"AAwDO,SAAS,SAOd,MACmD;AACnD,OAAK,aAAa,KAAK,cAAc,KAAK,QAAQ;AAElD,MAAI,CAAC,KAAK,kBAAkB,OAAO,KAAK,SAAS,UAAU;AACzD,QAAI;AACF,UAAI,IAAI,KAAK,IAAI;AACjB,WAAK,iBAAiB;AAAA,IACxB,QAAQ;AAAA,IAAC;AAAA,EACX;AAEA,QAAM,UAAU,IAAI,QAAQ,KAAK,OAAO;AACxC,MAAI,KAAK,QAAQ,QAAQ,IAAI,UAAU,MAAM,MAAM;AACjD,YAAQ,IAAI,YAAY,KAAK,IAAI;AAAA,EACnC;AAEA,QAAM,WAAW,IAAI,SAAS,MAAM;AAAA,IAClC,QAAQ,KAAK;AAAA,IACb;AAAA,EAAA,CACD;AAEC,WAA+D,UAC/D;AAEF,MAAI,KAAK,OAAO;AACd,UAAM;AAAA,EACR;AAEA,SAAO;AACT;AAEO,SAAS,WAAW,KAA8B;AACvD,SAAO,eAAe,YAAY,CAAC,CAAE,IAAY;AACnD;AAEO,SAAS,mBACd,KACoD;AACpD,SAAO,WAAW,GAAG,KAAK,CAAC,CAAC,IAAI,QAAQ;AAC1C;AAEO,SAAS,cAAc,KAAU;AACtC,MAAI,QAAQ,QAAQ,OAAO,QAAQ,YAAY,IAAI,sBAAsB;AACvE,WAAO,SAAS,GAAG;AAAA,EACrB;AAEA,SAAO;AACT;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { LocationRewrite } from './router.js';
|
|
2
|
+
export declare function composeRewrites(rewrites: Array<LocationRewrite>): {
|
|
3
|
+
input: ({ url }: {
|
|
4
|
+
url: URL;
|
|
5
|
+
}) => URL;
|
|
6
|
+
output: ({ url }: {
|
|
7
|
+
url: URL;
|
|
8
|
+
}) => URL;
|
|
9
|
+
};
|
|
10
|
+
export declare function rewriteBasepath(opts: {
|
|
11
|
+
basepath: string;
|
|
12
|
+
caseSensitive?: boolean;
|
|
13
|
+
}): {
|
|
14
|
+
input: ({ url }: {
|
|
15
|
+
url: URL;
|
|
16
|
+
}) => URL;
|
|
17
|
+
output: ({ url }: {
|
|
18
|
+
url: URL;
|
|
19
|
+
}) => URL;
|
|
20
|
+
};
|
|
21
|
+
export declare function executeRewriteInput(rewrite: LocationRewrite | undefined, url: URL): URL;
|
|
22
|
+
export declare function executeRewriteOutput(rewrite: LocationRewrite | undefined, url: URL): URL;
|