3
3
MatcherLocationRaw ,
4
4
MatcherLocation ,
5
5
isRouteName ,
6
+ RouteParamsGeneric ,
6
7
} from '../types'
7
8
import { createRouterError , ErrorTypes , MatcherError } from '../errors'
8
9
import { createRouteRecordMatcher , RouteRecordMatcher } from './pathMatcher'
@@ -17,8 +18,9 @@ import type {
17
18
import { comparePathParserScore } from './pathParserRanker'
18
19
19
20
import { warn } from '../warning'
20
- import { assign , noop } from '../utils'
21
+ import { applyToParam , assign , noop } from '../utils'
21
22
import type { RouteRecordNameGeneric , _RouteRecordProps } from '../typed-routes'
23
+ import { encodeParam , encodePathParam } from '../encoding'
22
24
23
25
/**
24
26
* Internal RouterMatcher
@@ -40,10 +42,12 @@ export interface RouterMatcher {
40
42
*
41
43
* @param location - MatcherLocationRaw to resolve to a url
42
44
* @param currentLocation - MatcherLocation of the current location
45
+ * @param encodeParams - Whether to encode parameters or not. Defaults to `false`
43
46
*/
44
47
resolve : (
45
48
location : MatcherLocationRaw ,
46
- currentLocation : MatcherLocation
49
+ currentLocation : MatcherLocation ,
50
+ encodeParams ?: boolean
47
51
) => MatcherLocation
48
52
}
49
53
@@ -230,15 +234,48 @@ export function createRouterMatcher(
230
234
matcherMap . set ( matcher . record . name , matcher )
231
235
}
232
236
237
+ function encodeParams (
238
+ matcher : RouteRecordMatcher ,
239
+ params : RouteParamsGeneric | undefined
240
+ ) : MatcherLocation [ 'params' ] {
241
+ const newParams = { } as MatcherLocation [ 'params' ]
242
+ if ( params ) {
243
+ for ( let paramKey of Object . keys ( params ) ) {
244
+ let matcherKey = matcher . keys . find ( k => k . name == paramKey )
245
+
246
+ let keepSlash = matcherKey ?. keepSlash ?? false
247
+ newParams [ paramKey ] = keepSlash
248
+ ? applyToParam ( encodePathParam , params [ paramKey ] )
249
+ : applyToParam ( encodeParam , params [ paramKey ] )
250
+ }
251
+ }
252
+ return newParams
253
+ }
254
+
233
255
function resolve (
234
256
location : Readonly < MatcherLocationRaw > ,
235
- currentLocation : Readonly < MatcherLocation >
257
+ currentLocation : Readonly < MatcherLocation > ,
258
+ doEncodeParams : boolean = false
236
259
) : MatcherLocation {
237
260
let matcher : RouteRecordMatcher | undefined
238
261
let params : PathParams = { }
239
262
let path : MatcherLocation [ 'path' ]
240
263
let name : MatcherLocation [ 'name' ]
241
264
265
+ // Encode params
266
+ let encodeLocationsParams = ( matcher : RouteRecordMatcher ) => {
267
+ if ( doEncodeParams ) {
268
+ if ( 'params' in location ) {
269
+ location = assign ( location , {
270
+ params : encodeParams ( matcher , location . params ) ,
271
+ } )
272
+ }
273
+ currentLocation = assign ( currentLocation , {
274
+ params : encodeParams ( matcher , currentLocation . params ) ,
275
+ } )
276
+ }
277
+ }
278
+
242
279
if ( 'name' in location && location . name ) {
243
280
matcher = matcherMap . get ( location . name )
244
281
@@ -247,6 +284,8 @@ export function createRouterMatcher(
247
284
location,
248
285
} )
249
286
287
+ encodeLocationsParams ( matcher )
288
+
250
289
// warn if the user is passing invalid params so they can debug it better when they get removed
251
290
if ( __DEV__ ) {
252
291
const invalidParams : string [ ] = Object . keys (
@@ -301,6 +340,7 @@ export function createRouterMatcher(
301
340
// matcher should have a value after the loop
302
341
303
342
if ( matcher ) {
343
+ encodeLocationsParams ( matcher )
304
344
// we know the matcher works because we tested the regexp
305
345
params = matcher . parse ( path ) !
306
346
name = matcher . record . name
@@ -316,6 +356,7 @@ export function createRouterMatcher(
316
356
location,
317
357
currentLocation,
318
358
} )
359
+ encodeLocationsParams ( matcher )
319
360
name = matcher . record . name
320
361
// since we are navigating to the same location, we don't need to pick the
321
362
// params like when `name` is provided
0 commit comments