33 MatcherLocationRaw ,
44 MatcherLocation ,
55 isRouteName ,
6+ RouteParamsGeneric ,
67} from '../types'
78import { createRouterError , ErrorTypes , MatcherError } from '../errors'
89import { createRouteRecordMatcher , RouteRecordMatcher } from './pathMatcher'
@@ -17,8 +18,9 @@ import type {
1718import { comparePathParserScore } from './pathParserRanker'
1819
1920import { warn } from '../warning'
20- import { assign , noop } from '../utils'
21+ import { applyToParam , assign , noop } from '../utils'
2122import type { RouteRecordNameGeneric , _RouteRecordProps } from '../typed-routes'
23+ import { encodeParam , encodePathParam } from '../encoding'
2224
2325/**
2426 * Internal RouterMatcher
@@ -40,10 +42,12 @@ export interface RouterMatcher {
4042 *
4143 * @param location - MatcherLocationRaw to resolve to a url
4244 * @param currentLocation - MatcherLocation of the current location
45+ * @param encodeParams - Whether to encode parameters or not. Defaults to `false`
4346 */
4447 resolve : (
4548 location : MatcherLocationRaw ,
46- currentLocation : MatcherLocation
49+ currentLocation : MatcherLocation ,
50+ encodeParams ?: boolean
4751 ) => MatcherLocation
4852}
4953
@@ -230,15 +234,48 @@ export function createRouterMatcher(
230234 matcherMap . set ( matcher . record . name , matcher )
231235 }
232236
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+
233255 function resolve (
234256 location : Readonly < MatcherLocationRaw > ,
235- currentLocation : Readonly < MatcherLocation >
257+ currentLocation : Readonly < MatcherLocation > ,
258+ doEncodeParams : boolean = false
236259 ) : MatcherLocation {
237260 let matcher : RouteRecordMatcher | undefined
238261 let params : PathParams = { }
239262 let path : MatcherLocation [ 'path' ]
240263 let name : MatcherLocation [ 'name' ]
241264
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+
242279 if ( 'name' in location && location . name ) {
243280 matcher = matcherMap . get ( location . name )
244281
@@ -247,6 +284,8 @@ export function createRouterMatcher(
247284 location,
248285 } )
249286
287+ encodeLocationsParams ( matcher )
288+
250289 // warn if the user is passing invalid params so they can debug it better when they get removed
251290 if ( __DEV__ ) {
252291 const invalidParams : string [ ] = Object . keys (
@@ -301,6 +340,7 @@ export function createRouterMatcher(
301340 // matcher should have a value after the loop
302341
303342 if ( matcher ) {
343+ encodeLocationsParams ( matcher )
304344 // we know the matcher works because we tested the regexp
305345 params = matcher . parse ( path ) !
306346 name = matcher . record . name
@@ -316,6 +356,7 @@ export function createRouterMatcher(
316356 location,
317357 currentLocation,
318358 } )
359+ encodeLocationsParams ( matcher )
319360 name = matcher . record . name
320361 // since we are navigating to the same location, we don't need to pick the
321362 // params like when `name` is provided
0 commit comments