@tanstack/react-router 1.78.3 → 1.79.0
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/path.cjs +12 -2
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +2 -1
- package/dist/cjs/router.cjs +14 -4
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +8 -0
- package/dist/esm/path.d.ts +2 -1
- package/dist/esm/path.js +12 -2
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/router.d.ts +8 -0
- package/dist/esm/router.js +14 -4
- package/dist/esm/router.js.map +1 -1
- package/package.json +3 -3
- package/src/path.ts +16 -1
- package/src/router.ts +23 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-router",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.79.0",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@tanstack/history": "1.61.1"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@testing-library/jest-dom": "^6.6.
|
|
58
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
59
59
|
"@testing-library/react": "^16.0.1",
|
|
60
60
|
"@vitejs/plugin-react": "^4.3.3",
|
|
61
61
|
"combinate": "^1.1.11",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"react": ">=18",
|
|
68
68
|
"react-dom": ">=18",
|
|
69
|
-
"@tanstack/router-generator": "1.
|
|
69
|
+
"@tanstack/router-generator": "1.79.0"
|
|
70
70
|
},
|
|
71
71
|
"peerDependenciesMeta": {
|
|
72
72
|
"@tanstack/router-generator": {
|
package/src/path.ts
CHANGED
|
@@ -204,6 +204,8 @@ interface InterpolatePathOptions {
|
|
|
204
204
|
params: Record<string, unknown>
|
|
205
205
|
leaveWildcards?: boolean
|
|
206
206
|
leaveParams?: boolean
|
|
207
|
+
// Map of encoded chars to decoded chars (e.g. '%40' -> '@') that should remain decoded in path params
|
|
208
|
+
decodeCharMap?: Map<string, string>
|
|
207
209
|
}
|
|
208
210
|
|
|
209
211
|
export function interpolatePath({
|
|
@@ -211,6 +213,7 @@ export function interpolatePath({
|
|
|
211
213
|
params,
|
|
212
214
|
leaveWildcards,
|
|
213
215
|
leaveParams,
|
|
216
|
+
decodeCharMap,
|
|
214
217
|
}: InterpolatePathOptions) {
|
|
215
218
|
const interpolatedPathSegments = parsePathname(path)
|
|
216
219
|
const encodedParams: any = {}
|
|
@@ -222,7 +225,9 @@ export function interpolatePath({
|
|
|
222
225
|
// the splat/catch-all routes shouldn't have the '/' encoded out
|
|
223
226
|
encodedParams[key] = isValueString ? encodeURI(value) : value
|
|
224
227
|
} else {
|
|
225
|
-
encodedParams[key] = isValueString
|
|
228
|
+
encodedParams[key] = isValueString
|
|
229
|
+
? encodePathParam(value, decodeCharMap)
|
|
230
|
+
: value
|
|
226
231
|
}
|
|
227
232
|
}
|
|
228
233
|
|
|
@@ -247,6 +252,16 @@ export function interpolatePath({
|
|
|
247
252
|
)
|
|
248
253
|
}
|
|
249
254
|
|
|
255
|
+
function encodePathParam(value: string, decodeCharMap?: Map<string, string>) {
|
|
256
|
+
let encoded = encodeURIComponent(value)
|
|
257
|
+
if (decodeCharMap) {
|
|
258
|
+
for (const [encodedChar, char] of decodeCharMap) {
|
|
259
|
+
encoded = encoded.replaceAll(encodedChar, char)
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return encoded
|
|
263
|
+
}
|
|
264
|
+
|
|
250
265
|
export function matchPathname(
|
|
251
266
|
basepath: string,
|
|
252
267
|
currentPathname: string,
|
package/src/router.ts
CHANGED
|
@@ -464,6 +464,15 @@ export interface RouterOptions<
|
|
|
464
464
|
*/
|
|
465
465
|
strict?: boolean
|
|
466
466
|
}
|
|
467
|
+
/**
|
|
468
|
+
* Configures which URI characters are allowed in path params that would ordinarily be escaped by encodeURIComponent.
|
|
469
|
+
*
|
|
470
|
+
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#pathparamsallowedcharacters-property)
|
|
471
|
+
* @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/path-params#allowed-characters)
|
|
472
|
+
*/
|
|
473
|
+
pathParamsAllowedCharacters?: Array<
|
|
474
|
+
';' | ':' | '@' | '&' | '=' | '+' | '$' | ','
|
|
475
|
+
>
|
|
467
476
|
}
|
|
468
477
|
|
|
469
478
|
export interface RouterErrorSerializer<TSerializedError> {
|
|
@@ -711,6 +720,7 @@ export class Router<
|
|
|
711
720
|
routesByPath!: RoutesByPath<TRouteTree>
|
|
712
721
|
flatRoutes!: Array<AnyRoute>
|
|
713
722
|
isServer!: boolean
|
|
723
|
+
pathParamsDecodeCharMap?: Map<string, string>
|
|
714
724
|
|
|
715
725
|
/**
|
|
716
726
|
* @deprecated Use the `createRouter` function instead
|
|
@@ -768,6 +778,15 @@ export class Router<
|
|
|
768
778
|
|
|
769
779
|
this.isServer = this.options.isServer ?? typeof document === 'undefined'
|
|
770
780
|
|
|
781
|
+
this.pathParamsDecodeCharMap = this.options.pathParamsAllowedCharacters
|
|
782
|
+
? new Map(
|
|
783
|
+
this.options.pathParamsAllowedCharacters.map((char) => [
|
|
784
|
+
encodeURIComponent(char),
|
|
785
|
+
char,
|
|
786
|
+
]),
|
|
787
|
+
)
|
|
788
|
+
: undefined
|
|
789
|
+
|
|
771
790
|
if (
|
|
772
791
|
!this.basepath ||
|
|
773
792
|
(newOptions.basepath && newOptions.basepath !== previousOptions.basepath)
|
|
@@ -1187,6 +1206,7 @@ export class Router<
|
|
|
1187
1206
|
const interpolatedPath = interpolatePath({
|
|
1188
1207
|
path: route.fullPath,
|
|
1189
1208
|
params: routeParams,
|
|
1209
|
+
decodeCharMap: this.pathParamsDecodeCharMap,
|
|
1190
1210
|
})
|
|
1191
1211
|
|
|
1192
1212
|
const matchId =
|
|
@@ -1194,6 +1214,7 @@ export class Router<
|
|
|
1194
1214
|
path: route.id,
|
|
1195
1215
|
params: routeParams,
|
|
1196
1216
|
leaveWildcards: true,
|
|
1217
|
+
decodeCharMap: this.pathParamsDecodeCharMap,
|
|
1197
1218
|
}) + loaderDepsHash
|
|
1198
1219
|
|
|
1199
1220
|
// Waste not, want not. If we already have a match for this route,
|
|
@@ -1431,6 +1452,7 @@ export class Router<
|
|
|
1431
1452
|
const interpolatedPath = interpolatePath({
|
|
1432
1453
|
path: route.fullPath,
|
|
1433
1454
|
params: matchedRoutesResult?.routeParams ?? {},
|
|
1455
|
+
decodeCharMap: this.pathParamsDecodeCharMap,
|
|
1434
1456
|
})
|
|
1435
1457
|
const pathname = joinPaths([this.basepath, interpolatedPath])
|
|
1436
1458
|
return pathname === fromPath
|
|
@@ -1467,6 +1489,7 @@ export class Router<
|
|
|
1467
1489
|
params: nextParams ?? {},
|
|
1468
1490
|
leaveWildcards: false,
|
|
1469
1491
|
leaveParams: opts.leaveParams,
|
|
1492
|
+
decodeCharMap: this.pathParamsDecodeCharMap,
|
|
1470
1493
|
})
|
|
1471
1494
|
|
|
1472
1495
|
let search = fromSearch
|