diff --git a/packages/router/src/location.ts b/packages/router/src/location.ts index 0ca40799c..163bf6f8d 100644 --- a/packages/router/src/location.ts +++ b/packages/router/src/location.ts @@ -3,7 +3,7 @@ import { RouteParamValue, RouteParamsGeneric } from './types' import { RouteRecord } from './matcher/types' import { warn } from './warning' import { isArray } from './utils' -import { decode } from './encoding' +import { decode, encodeHash } from './encoding' import { RouteLocation, RouteLocationNormalizedLoaded } from './typed-routes' /** @@ -94,6 +94,25 @@ export function parseURL( } } +/** + * Creates a `fullPath` property from the `path`, `query` and `hash` properties + * + * @param stringifyQuery - custom function to stringify the query object. It should handle encoding values + * @param path - An encdoded path + * @param query - A decoded query object + * @param hash - A decoded hash + * @returns a valid `fullPath` + */ +export function NEW_stringifyURL( + stringifyQuery: (query?: LocationQueryRaw) => string, + path: LocationPartial['path'], + query?: LocationPartial['query'], + hash: LocationPartial['hash'] = '' +): string { + const searchText = stringifyQuery(query) + return path + (searchText && '?') + searchText + encodeHash(hash) +} + /** * Stringifies a URL object * diff --git a/packages/router/src/new-route-resolver/matcher.spec.ts b/packages/router/src/new-route-resolver/matcher.spec.ts index 07695b598..a0c59e6d9 100644 --- a/packages/router/src/new-route-resolver/matcher.spec.ts +++ b/packages/router/src/new-route-resolver/matcher.spec.ts @@ -314,33 +314,50 @@ describe('RouterMatcher', () => { }) describe('encoding', () => { - it('handles encoded string path', () => { - const matcher = createCompiledMatcher([ANY_PATH_ROUTE]) - console.log(matcher.resolve('/%23%2F%3F')) - expect(matcher.resolve('/%23%2F%3F')).toMatchObject({ - fullPath: '/%23%2F%3F', - path: '/%23%2F%3F', - query: {}, - params: {}, - hash: '', + const matcher = createCompiledMatcher([ANY_PATH_ROUTE]) + describe('decodes', () => { + it('handles encoded string path', () => { + expect(matcher.resolve('/%23%2F%3F')).toMatchObject({ + fullPath: '/%23%2F%3F', + path: '/%23%2F%3F', + query: {}, + params: {}, + hash: '', + }) }) - }) - it('decodes query from a string', () => { - const matcher = createCompiledMatcher([ANY_PATH_ROUTE]) - expect(matcher.resolve('/foo?foo=%23%2F%3F')).toMatchObject({ - path: '/foo', - fullPath: '/foo?foo=%23%2F%3F', - query: { foo: '#/?' }, + it('decodes query from a string', () => { + expect(matcher.resolve('/foo?foo=%23%2F%3F')).toMatchObject({ + path: '/foo', + fullPath: '/foo?foo=%23%2F%3F', + query: { foo: '#/?' }, + }) + }) + + it('decodes hash from a string', () => { + expect(matcher.resolve('/foo#%22')).toMatchObject({ + path: '/foo', + fullPath: '/foo#%22', + hash: '#"', + }) }) }) - it('decodes hash from a string', () => { - const matcher = createCompiledMatcher([ANY_PATH_ROUTE]) - expect(matcher.resolve('/foo#h-%23%2F%3F')).toMatchObject({ - path: '/foo', - fullPath: '/foo#h-%23%2F%3F', - hash: '#h-#/?', + describe('encodes', () => { + it('encodes the query', () => { + expect( + matcher.resolve({ path: '/foo', query: { foo: '"' } }) + ).toMatchObject({ + fullPath: '/foo?foo=%22', + query: { foo: '"' }, + }) + }) + + it('encodes the hash', () => { + expect(matcher.resolve({ path: '/foo', hash: '#"' })).toMatchObject({ + fullPath: '/foo#%22', + hash: '#"', + }) }) }) }) diff --git a/packages/router/src/new-route-resolver/matcher.ts b/packages/router/src/new-route-resolver/matcher.ts index 69ddc5540..c0ba504ce 100644 --- a/packages/router/src/new-route-resolver/matcher.ts +++ b/packages/router/src/new-route-resolver/matcher.ts @@ -11,7 +11,7 @@ import type { } from './matcher-pattern' import { warn } from '../warning' import { encodeQueryValue as _encodeQueryValue, encodeParam } from '../encoding' -import { parseURL, stringifyURL } from '../location' +import { parseURL, NEW_stringifyURL } from '../location' import type { MatcherLocationAsNamed, MatcherLocationAsPathAbsolute, @@ -432,7 +432,7 @@ export function createCompiledMatcher( const path = location.path ?? '/' return { ...NO_MATCH_LOCATION, - fullPath: stringifyURL(stringifyQuery, { path, query, hash }), + fullPath: NEW_stringifyURL(stringifyQuery, path, query, hash), path, query, hash, @@ -465,7 +465,7 @@ export function createCompiledMatcher( return { name, - fullPath: stringifyURL(stringifyQuery, { path, query, hash }), + fullPath: NEW_stringifyURL(stringifyQuery, path, query, hash), path, query, hash,