@tanstack/router-core 1.129.6 → 1.129.8

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.
@@ -1,4 +1,5 @@
1
1
  import { Store } from '@tanstack/store';
2
+ import { ParsePathnameCache } from './path.cjs';
2
3
  import { SearchParser, SearchSerializer } from './searchParams.cjs';
3
4
  import { AnyRedirect, ResolvedRedirect } from './redirect.cjs';
4
5
  import { HistoryLocation, HistoryState, ParsedHistoryState, RouterHistory } from '@tanstack/history';
@@ -496,6 +497,8 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
496
497
  get looseRoutesById(): Record<string, AnyRoute>;
497
498
  matchRoutes: MatchRoutesFn;
498
499
  private matchRoutesInternal;
500
+ /** a cache for `parsePathname` */
501
+ private parsePathnameCache;
499
502
  getMatchedRoutes: GetMatchRoutesFn;
500
503
  cancelMatch: (id: string) => void;
501
504
  cancelMatches: () => void;
@@ -563,7 +566,7 @@ export declare function processRouteTree<TRouteLike extends RouteLike>({ routeTr
563
566
  routeTree: TRouteLike;
564
567
  initRoute?: (route: TRouteLike, index: number) => void;
565
568
  }): ProcessRouteTreeResult<TRouteLike>;
566
- export declare function getMatchedRoutes<TRouteLike extends RouteLike>({ pathname, routePathname, basepath, caseSensitive, routesByPath, routesById, flatRoutes, }: {
569
+ export declare function getMatchedRoutes<TRouteLike extends RouteLike>({ pathname, routePathname, basepath, caseSensitive, routesByPath, routesById, flatRoutes, parseCache, }: {
567
570
  pathname: string;
568
571
  routePathname?: string;
569
572
  basepath: string;
@@ -571,6 +574,7 @@ export declare function getMatchedRoutes<TRouteLike extends RouteLike>({ pathnam
571
574
  routesByPath: Record<string, TRouteLike>;
572
575
  routesById: Record<string, TRouteLike>;
573
576
  flatRoutes: Array<TRouteLike>;
577
+ parseCache?: ParsePathnameCache;
574
578
  }): {
575
579
  matchedRoutes: TRouteLike[];
576
580
  routeParams: Record<string, string>;
@@ -0,0 +1,5 @@
1
+ export type LRUCache<TKey, TValue> = {
2
+ get: (key: TKey) => TValue | undefined;
3
+ set: (key: TKey, value: TValue) => void;
4
+ };
5
+ export declare function createLRUCache<TKey, TValue>(max: number): LRUCache<TKey, TValue>;
@@ -0,0 +1,62 @@
1
+ function createLRUCache(max) {
2
+ const cache = /* @__PURE__ */ new Map();
3
+ let oldest;
4
+ let newest;
5
+ const touch = (entry) => {
6
+ if (!entry.next) return;
7
+ if (!entry.prev) {
8
+ entry.next.prev = void 0;
9
+ oldest = entry.next;
10
+ entry.next = void 0;
11
+ if (newest) {
12
+ entry.prev = newest;
13
+ newest.next = entry;
14
+ }
15
+ } else {
16
+ entry.prev.next = entry.next;
17
+ entry.next.prev = entry.prev;
18
+ entry.next = void 0;
19
+ if (newest) {
20
+ newest.next = entry;
21
+ entry.prev = newest;
22
+ }
23
+ }
24
+ newest = entry;
25
+ };
26
+ return {
27
+ get(key) {
28
+ const entry = cache.get(key);
29
+ if (!entry) return void 0;
30
+ touch(entry);
31
+ return entry.value;
32
+ },
33
+ set(key, value) {
34
+ if (cache.size >= max && oldest) {
35
+ const toDelete = oldest;
36
+ cache.delete(toDelete.key);
37
+ if (toDelete.next) {
38
+ oldest = toDelete.next;
39
+ toDelete.next.prev = void 0;
40
+ }
41
+ if (toDelete === newest) {
42
+ newest = void 0;
43
+ }
44
+ }
45
+ const existing = cache.get(key);
46
+ if (existing) {
47
+ existing.value = value;
48
+ touch(existing);
49
+ } else {
50
+ const entry = { key, value, prev: newest };
51
+ if (newest) newest.next = entry;
52
+ newest = entry;
53
+ if (!oldest) oldest = entry;
54
+ cache.set(key, entry);
55
+ }
56
+ }
57
+ };
58
+ }
59
+ export {
60
+ createLRUCache
61
+ };
62
+ //# sourceMappingURL=lru-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lru-cache.js","sources":["../../src/lru-cache.ts"],"sourcesContent":["export type LRUCache<TKey, TValue> = {\n get: (key: TKey) => TValue | undefined\n set: (key: TKey, value: TValue) => void\n}\n\nexport function createLRUCache<TKey, TValue>(\n max: number,\n): LRUCache<TKey, TValue> {\n type Node = { prev?: Node; next?: Node; key: TKey; value: TValue }\n const cache = new Map<TKey, Node>()\n let oldest: Node | undefined\n let newest: Node | undefined\n\n const touch = (entry: Node) => {\n if (!entry.next) return\n if (!entry.prev) {\n entry.next.prev = undefined\n oldest = entry.next\n entry.next = undefined\n if (newest) {\n entry.prev = newest\n newest.next = entry\n }\n } else {\n entry.prev.next = entry.next\n entry.next.prev = entry.prev\n entry.next = undefined\n if (newest) {\n newest.next = entry\n entry.prev = newest\n }\n }\n newest = entry\n }\n\n return {\n get(key) {\n const entry = cache.get(key)\n if (!entry) return undefined\n touch(entry)\n return entry.value\n },\n set(key, value) {\n if (cache.size >= max && oldest) {\n const toDelete = oldest\n cache.delete(toDelete.key)\n if (toDelete.next) {\n oldest = toDelete.next\n toDelete.next.prev = undefined\n }\n if (toDelete === newest) {\n newest = undefined\n }\n }\n const existing = cache.get(key)\n if (existing) {\n existing.value = value\n touch(existing)\n } else {\n const entry: Node = { key, value, prev: newest }\n if (newest) newest.next = entry\n newest = entry\n if (!oldest) oldest = entry\n cache.set(key, entry)\n }\n },\n }\n}\n"],"names":[],"mappings":"AAKO,SAAS,eACd,KACwB;AAElB,QAAA,4BAAY,IAAgB;AAC9B,MAAA;AACA,MAAA;AAEE,QAAA,QAAQ,CAAC,UAAgB;AACzB,QAAA,CAAC,MAAM,KAAM;AACb,QAAA,CAAC,MAAM,MAAM;AACf,YAAM,KAAK,OAAO;AAClB,eAAS,MAAM;AACf,YAAM,OAAO;AACb,UAAI,QAAQ;AACV,cAAM,OAAO;AACb,eAAO,OAAO;AAAA,MAAA;AAAA,IAChB,OACK;AACC,YAAA,KAAK,OAAO,MAAM;AAClB,YAAA,KAAK,OAAO,MAAM;AACxB,YAAM,OAAO;AACb,UAAI,QAAQ;AACV,eAAO,OAAO;AACd,cAAM,OAAO;AAAA,MAAA;AAAA,IACf;AAEO,aAAA;AAAA,EACX;AAEO,SAAA;AAAA,IACL,IAAI,KAAK;AACD,YAAA,QAAQ,MAAM,IAAI,GAAG;AACvB,UAAA,CAAC,MAAc,QAAA;AACnB,YAAM,KAAK;AACX,aAAO,MAAM;AAAA,IACf;AAAA,IACA,IAAI,KAAK,OAAO;AACV,UAAA,MAAM,QAAQ,OAAO,QAAQ;AAC/B,cAAM,WAAW;AACX,cAAA,OAAO,SAAS,GAAG;AACzB,YAAI,SAAS,MAAM;AACjB,mBAAS,SAAS;AAClB,mBAAS,KAAK,OAAO;AAAA,QAAA;AAEvB,YAAI,aAAa,QAAQ;AACd,mBAAA;AAAA,QAAA;AAAA,MACX;AAEI,YAAA,WAAW,MAAM,IAAI,GAAG;AAC9B,UAAI,UAAU;AACZ,iBAAS,QAAQ;AACjB,cAAM,QAAQ;AAAA,MAAA,OACT;AACL,cAAM,QAAc,EAAE,KAAK,OAAO,MAAM,OAAO;AAC3C,YAAA,eAAe,OAAO;AACjB,iBAAA;AACL,YAAA,CAAC,OAAiB,UAAA;AAChB,cAAA,IAAI,KAAK,KAAK;AAAA,MAAA;AAAA,IACtB;AAAA,EAEJ;AACF;"}
@@ -1,3 +1,4 @@
1
+ import { LRUCache } from './lru-cache.js';
1
2
  import { MatchLocation } from './RouterProvider.js';
2
3
  import { AnyPathParams } from './route.js';
3
4
  export declare const SEGMENT_TYPE_PATHNAME = 0;
@@ -24,40 +25,26 @@ interface ResolvePathOptions {
24
25
  to: string;
25
26
  trailingSlash?: 'always' | 'never' | 'preserve';
26
27
  caseSensitive?: boolean;
28
+ parseCache?: ParsePathnameCache;
27
29
  }
28
- export declare function resolvePath({ basepath, base, to, trailingSlash, caseSensitive, }: ResolvePathOptions): string;
29
- /**
30
- * Required: `/foo/$bar`
31
- * Prefix and Suffix: `/foo/prefix${bar}suffix` ✅
32
- * Wildcard: `/foo/$` ✅
33
- * Wildcard with Prefix and Suffix: `/foo/prefix{$}suffix` ✅
34
- *
35
- * Optional param: `/foo/{-$bar}`
36
- * Optional param with Prefix and Suffix: `/foo/prefix{-$bar}suffix`
37
-
38
- * Future:
39
- * Optional named segment: `/foo/{bar}`
40
- * Optional named segment with Prefix and Suffix: `/foo/prefix{-bar}suffix`
41
- * Escape special characters:
42
- * - `/foo/[$]` - Static route
43
- * - `/foo/[$]{$foo} - Dynamic route with a static prefix of `$`
44
- * - `/foo/{$foo}[$]` - Dynamic route with a static suffix of `$`
45
- */
46
- export declare function parsePathname(pathname?: string): ReadonlyArray<Segment>;
30
+ export declare function resolvePath({ basepath, base, to, trailingSlash, caseSensitive, parseCache, }: ResolvePathOptions): string;
31
+ export type ParsePathnameCache = LRUCache<string, ReadonlyArray<Segment>>;
32
+ export declare const parsePathname: (pathname?: string, cache?: ParsePathnameCache) => ReadonlyArray<Segment>;
47
33
  interface InterpolatePathOptions {
48
34
  path?: string;
49
35
  params: Record<string, unknown>;
50
36
  leaveWildcards?: boolean;
51
37
  leaveParams?: boolean;
52
38
  decodeCharMap?: Map<string, string>;
39
+ parseCache?: ParsePathnameCache;
53
40
  }
54
41
  type InterPolatePathResult = {
55
42
  interpolatedPath: string;
56
43
  usedParams: Record<string, unknown>;
57
44
  isMissingParams: boolean;
58
45
  };
59
- export declare function interpolatePath({ path, params, leaveWildcards, leaveParams, decodeCharMap, }: InterpolatePathOptions): InterPolatePathResult;
60
- export declare function matchPathname(basepath: string, currentPathname: string, matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>): AnyPathParams | undefined;
46
+ export declare function interpolatePath({ path, params, leaveWildcards, leaveParams, decodeCharMap, parseCache, }: InterpolatePathOptions): InterPolatePathResult;
47
+ export declare function matchPathname(basepath: string, currentPathname: string, matchLocation: Pick<MatchLocation, 'to' | 'fuzzy' | 'caseSensitive'>, parseCache?: ParsePathnameCache): AnyPathParams | undefined;
61
48
  export declare function removeBasepath(basepath: string, pathname: string, caseSensitive?: boolean): string;
62
- export declare function matchByPath(basepath: string, from: string, { to, fuzzy, caseSensitive, }: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>): Record<string, string> | undefined;
49
+ export declare function matchByPath(basepath: string, from: string, { to, fuzzy, caseSensitive, }: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>, parseCache?: ParsePathnameCache): Record<string, string> | undefined;
63
50
  export {};
package/dist/esm/path.js CHANGED
@@ -74,13 +74,14 @@ function resolvePath({
74
74
  base,
75
75
  to,
76
76
  trailingSlash = "never",
77
- caseSensitive
77
+ caseSensitive,
78
+ parseCache
78
79
  }) {
79
80
  var _a;
80
81
  base = removeBasepath(basepath, base, caseSensitive);
81
82
  to = removeBasepath(basepath, to, caseSensitive);
82
- let baseSegments = parsePathname(base).slice();
83
- const toSegments = parsePathname(to);
83
+ let baseSegments = parsePathname(base, parseCache).slice();
84
+ const toSegments = parsePathname(to, parseCache);
84
85
  if (baseSegments.length > 1 && ((_a = last(baseSegments)) == null ? void 0 : _a.value) === "/") {
85
86
  baseSegments.pop();
86
87
  }
@@ -113,15 +114,20 @@ function resolvePath({
113
114
  const joined = joinPaths([basepath, ...segmentValues]);
114
115
  return joined;
115
116
  }
117
+ const parsePathname = (pathname, cache) => {
118
+ if (!pathname) return [];
119
+ const cached = cache == null ? void 0 : cache.get(pathname);
120
+ if (cached) return cached;
121
+ const parsed = baseParsePathname(pathname);
122
+ cache == null ? void 0 : cache.set(pathname, parsed);
123
+ return parsed;
124
+ };
116
125
  const PARAM_RE = /^\$.{1,}$/;
117
126
  const PARAM_W_CURLY_BRACES_RE = /^(.*?)\{(\$[a-zA-Z_$][a-zA-Z0-9_$]*)\}(.*)$/;
118
127
  const OPTIONAL_PARAM_W_CURLY_BRACES_RE = /^(.*?)\{-(\$[a-zA-Z_$][a-zA-Z0-9_$]*)\}(.*)$/;
119
128
  const WILDCARD_RE = /^\$$/;
120
129
  const WILDCARD_W_CURLY_BRACES_RE = /^(.*?)\{\$\}(.*)$/;
121
- function parsePathname(pathname) {
122
- if (!pathname) {
123
- return [];
124
- }
130
+ function baseParsePathname(pathname) {
125
131
  pathname = cleanPath(pathname);
126
132
  const segments = [];
127
133
  if (pathname.slice(0, 1) === "/") {
@@ -212,9 +218,10 @@ function interpolatePath({
212
218
  params,
213
219
  leaveWildcards,
214
220
  leaveParams,
215
- decodeCharMap
221
+ decodeCharMap,
222
+ parseCache
216
223
  }) {
217
- const interpolatedPathSegments = parsePathname(path);
224
+ const interpolatedPathSegments = parsePathname(path, parseCache);
218
225
  function encodeParam(key) {
219
226
  const value = params[key];
220
227
  const isValueString = typeof value === "string";
@@ -302,8 +309,13 @@ function encodePathParam(value, decodeCharMap) {
302
309
  }
303
310
  return encoded;
304
311
  }
305
- function matchPathname(basepath, currentPathname, matchLocation) {
306
- const pathParams = matchByPath(basepath, currentPathname, matchLocation);
312
+ function matchPathname(basepath, currentPathname, matchLocation, parseCache) {
313
+ const pathParams = matchByPath(
314
+ basepath,
315
+ currentPathname,
316
+ matchLocation,
317
+ parseCache
318
+ );
307
319
  if (matchLocation.to && !pathParams) {
308
320
  return;
309
321
  }
@@ -342,14 +354,20 @@ function matchByPath(basepath, from, {
342
354
  to,
343
355
  fuzzy,
344
356
  caseSensitive
345
- }) {
357
+ }, parseCache) {
346
358
  if (basepath !== "/" && !from.startsWith(basepath)) {
347
359
  return void 0;
348
360
  }
349
361
  from = removeBasepath(basepath, from, caseSensitive);
350
362
  to = removeBasepath(basepath, `${to ?? "$"}`, caseSensitive);
351
- const baseSegments = parsePathname(from.startsWith("/") ? from : `/${from}`);
352
- const routeSegments = parsePathname(to.startsWith("/") ? to : `/${to}`);
363
+ const baseSegments = parsePathname(
364
+ from.startsWith("/") ? from : `/${from}`,
365
+ parseCache
366
+ );
367
+ const routeSegments = parsePathname(
368
+ to.startsWith("/") ? to : `/${to}`,
369
+ parseCache
370
+ );
353
371
  const params = {};
354
372
  const result = isMatch(
355
373
  baseSegments,
@@ -1 +1 @@
1
- {"version":3,"file":"path.js","sources":["../../src/path.ts"],"sourcesContent":["import { last } from './utils'\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}\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}: ResolvePathOptions) {\n base = removeBasepath(basepath, base, caseSensitive)\n to = removeBasepath(basepath, to, caseSensitive)\n\n let baseSegments = parsePathname(base).slice()\n const toSegments = parsePathname(to)\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\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 */\nexport function parsePathname(pathname?: string): ReadonlyArray<Segment> {\n if (!pathname) {\n return []\n }\n\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}\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}: InterpolatePathOptions): InterPolatePathResult {\n const interpolatedPathSegments = parsePathname(path)\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): AnyPathParams | undefined {\n const pathParams = matchByPath(basepath, currentPathname, matchLocation)\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): 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(from.startsWith('/') ? from : `/${from}`)\n const routeSegments = parsePathname(to.startsWith('/') ? to : `/${to}`)\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 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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"}
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 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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"}
@@ -1,4 +1,5 @@
1
1
  import { Store } from '@tanstack/store';
2
+ import { ParsePathnameCache } from './path.js';
2
3
  import { SearchParser, SearchSerializer } from './searchParams.js';
3
4
  import { AnyRedirect, ResolvedRedirect } from './redirect.js';
4
5
  import { HistoryLocation, HistoryState, ParsedHistoryState, RouterHistory } from '@tanstack/history';
@@ -496,6 +497,8 @@ export declare class RouterCore<in out TRouteTree extends AnyRoute, in out TTrai
496
497
  get looseRoutesById(): Record<string, AnyRoute>;
497
498
  matchRoutes: MatchRoutesFn;
498
499
  private matchRoutesInternal;
500
+ /** a cache for `parsePathname` */
501
+ private parsePathnameCache;
499
502
  getMatchedRoutes: GetMatchRoutesFn;
500
503
  cancelMatch: (id: string) => void;
501
504
  cancelMatches: () => void;
@@ -563,7 +566,7 @@ export declare function processRouteTree<TRouteLike extends RouteLike>({ routeTr
563
566
  routeTree: TRouteLike;
564
567
  initRoute?: (route: TRouteLike, index: number) => void;
565
568
  }): ProcessRouteTreeResult<TRouteLike>;
566
- export declare function getMatchedRoutes<TRouteLike extends RouteLike>({ pathname, routePathname, basepath, caseSensitive, routesByPath, routesById, flatRoutes, }: {
569
+ export declare function getMatchedRoutes<TRouteLike extends RouteLike>({ pathname, routePathname, basepath, caseSensitive, routesByPath, routesById, flatRoutes, parseCache, }: {
567
570
  pathname: string;
568
571
  routePathname?: string;
569
572
  basepath: string;
@@ -571,6 +574,7 @@ export declare function getMatchedRoutes<TRouteLike extends RouteLike>({ pathnam
571
574
  routesByPath: Record<string, TRouteLike>;
572
575
  routesById: Record<string, TRouteLike>;
573
576
  flatRoutes: Array<TRouteLike>;
577
+ parseCache?: ParsePathnameCache;
574
578
  }): {
575
579
  matchedRoutes: TRouteLike[];
576
580
  routeParams: Record<string, string>;
@@ -8,6 +8,7 @@ import { setupScrollRestoration } from "./scroll-restoration.js";
8
8
  import { defaultParseSearch, defaultStringifySearch } from "./searchParams.js";
9
9
  import { rootRouteId } from "./root.js";
10
10
  import { redirect, isRedirect } from "./redirect.js";
11
+ import { createLRUCache } from "./lru-cache.js";
11
12
  function defaultSerializeError(err) {
12
13
  if (err instanceof Error) {
13
14
  const obj = {
@@ -176,7 +177,8 @@ class RouterCore {
176
177
  base: from,
177
178
  to: cleanPath(path),
178
179
  trailingSlash: this.options.trailingSlash,
179
- caseSensitive: this.options.caseSensitive
180
+ caseSensitive: this.options.caseSensitive,
181
+ parseCache: this.parsePathnameCache
180
182
  });
181
183
  return resolvedPath;
182
184
  };
@@ -192,6 +194,7 @@ class RouterCore {
192
194
  }
193
195
  return this.matchRoutesInternal(pathnameOrNext, locationSearchOrOpts);
194
196
  };
197
+ this.parsePathnameCache = createLRUCache(1e3);
195
198
  this.getMatchedRoutes = (pathname, routePathname) => {
196
199
  return getMatchedRoutes({
197
200
  pathname,
@@ -200,7 +203,8 @@ class RouterCore {
200
203
  caseSensitive: this.options.caseSensitive,
201
204
  routesByPath: this.routesByPath,
202
205
  routesById: this.routesById,
203
- flatRoutes: this.flatRoutes
206
+ flatRoutes: this.flatRoutes,
207
+ parseCache: this.parsePathnameCache
204
208
  });
205
209
  };
206
210
  this.cancelMatch = (id) => {
@@ -261,7 +265,8 @@ class RouterCore {
261
265
  };
262
266
  const interpolatedNextTo = interpolatePath({
263
267
  path: nextTo,
264
- params: nextParams ?? {}
268
+ params: nextParams ?? {},
269
+ parseCache: this.parsePathnameCache
265
270
  }).interpolatedPath;
266
271
  const destRoutes = this.matchRoutes(
267
272
  interpolatedNextTo,
@@ -285,7 +290,8 @@ class RouterCore {
285
290
  params: nextParams ?? {},
286
291
  leaveWildcards: false,
287
292
  leaveParams: opts.leaveParams,
288
- decodeCharMap: this.pathParamsDecodeCharMap
293
+ decodeCharMap: this.pathParamsDecodeCharMap,
294
+ parseCache: this.parsePathnameCache
289
295
  }).interpolatedPath;
290
296
  let nextSearch = fromSearch;
291
297
  if (opts._includeValidateSearch && ((_a = this.options.search) == null ? void 0 : _a.strict)) {
@@ -335,11 +341,16 @@ class RouterCore {
335
341
  if (!maskedNext) {
336
342
  let params = {};
337
343
  const foundMask = (_a = this.options.routeMasks) == null ? void 0 : _a.find((d) => {
338
- const match = matchPathname(this.basepath, next.pathname, {
339
- to: d.from,
340
- caseSensitive: false,
341
- fuzzy: false
342
- });
344
+ const match = matchPathname(
345
+ this.basepath,
346
+ next.pathname,
347
+ {
348
+ to: d.from,
349
+ caseSensitive: false,
350
+ fuzzy: false
351
+ },
352
+ this.parsePathnameCache
353
+ );
343
354
  if (match) {
344
355
  params = match;
345
356
  return true;
@@ -1369,10 +1380,15 @@ class RouterCore {
1369
1380
  }
1370
1381
  const pending = (opts == null ? void 0 : opts.pending) === void 0 ? !this.state.isLoading : opts.pending;
1371
1382
  const baseLocation = pending ? this.latestLocation : this.state.resolvedLocation || this.state.location;
1372
- const match = matchPathname(this.basepath, baseLocation.pathname, {
1373
- ...opts,
1374
- to: next.pathname
1375
- });
1383
+ const match = matchPathname(
1384
+ this.basepath,
1385
+ baseLocation.pathname,
1386
+ {
1387
+ ...opts,
1388
+ to: next.pathname
1389
+ },
1390
+ this.parsePathnameCache
1391
+ );
1376
1392
  if (!match) {
1377
1393
  return false;
1378
1394
  }
@@ -1551,7 +1567,8 @@ class RouterCore {
1551
1567
  path: route.id,
1552
1568
  params: routeParams,
1553
1569
  leaveWildcards: true,
1554
- decodeCharMap: this.pathParamsDecodeCharMap
1570
+ decodeCharMap: this.pathParamsDecodeCharMap,
1571
+ parseCache: this.parsePathnameCache
1555
1572
  }).interpolatedPath + loaderDepsHash;
1556
1573
  const existingMatch = this.getMatch(matchId);
1557
1574
  const previousMatch = this.state.matches.find(
@@ -1840,18 +1857,24 @@ function getMatchedRoutes({
1840
1857
  caseSensitive,
1841
1858
  routesByPath,
1842
1859
  routesById,
1843
- flatRoutes
1860
+ flatRoutes,
1861
+ parseCache
1844
1862
  }) {
1845
1863
  let routeParams = {};
1846
1864
  const trimmedPath = trimPathRight(pathname);
1847
1865
  const getMatchedParams = (route) => {
1848
1866
  var _a;
1849
- const result = matchPathname(basepath, trimmedPath, {
1850
- to: route.fullPath,
1851
- caseSensitive: ((_a = route.options) == null ? void 0 : _a.caseSensitive) ?? caseSensitive,
1852
- // we need fuzzy matching for `notFoundMode: 'fuzzy'`
1853
- fuzzy: true
1854
- });
1867
+ const result = matchPathname(
1868
+ basepath,
1869
+ trimmedPath,
1870
+ {
1871
+ to: route.fullPath,
1872
+ caseSensitive: ((_a = route.options) == null ? void 0 : _a.caseSensitive) ?? caseSensitive,
1873
+ // we need fuzzy matching for `notFoundMode: 'fuzzy'`
1874
+ fuzzy: true
1875
+ },
1876
+ parseCache
1877
+ );
1855
1878
  return result;
1856
1879
  };
1857
1880
  let foundRoute = routePathname !== void 0 ? routesByPath[routePathname] : void 0;