From 7fb8ee679614d3aae7cd7765729555816f0936f0 Mon Sep 17 00:00:00 2001 From: Evan Sutherland Date: Sun, 22 Sep 2024 08:23:45 -0500 Subject: [PATCH 1/4] push/replace accepts option for hash, assembles on url --- src/services/createRouterResolve.spec.ts | 6 ++++++ src/services/createRouterResolve.ts | 2 ++ src/services/createRouterRoute.ts | 1 + src/services/urlAssembly.spec.ts | 11 +++++++++++ src/services/urlAssembly.ts | 6 +++++- src/types/routerPush.ts | 1 + src/types/routerReplace.ts | 1 + 7 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/services/createRouterResolve.spec.ts b/src/services/createRouterResolve.spec.ts index 3002a69c..a2b81294 100644 --- a/src/services/createRouterResolve.spec.ts +++ b/src/services/createRouterResolve.spec.ts @@ -83,4 +83,10 @@ test('when given an external route with params in host, interpolates param value const url = resolve('external', { 'subdomain': 'router' }) expect(url).toBe('https://router.kitbag.dev/') +}) + +test('given a route with hash, interpolates hash value', () => { + const resolve = createRouterResolve(routes) + + expect(resolve('parentA', { paramA: 'bar' }, { hash: 'foo' })).toBe('/parentA/bar#foo') }) \ No newline at end of file diff --git a/src/services/createRouterResolve.ts b/src/services/createRouterResolve.ts index 474387b4..5ce7b6f1 100644 --- a/src/services/createRouterResolve.ts +++ b/src/services/createRouterResolve.ts @@ -10,6 +10,7 @@ import { AllPropertiesAreOptional } from '@/types/utilities' export type RouterResolveOptions = { query?: Record, + hash?: string, } type RouterResolveArgs< @@ -51,6 +52,7 @@ export function createRouterResolve(routes: TRoute const url = assembleUrl(match, { params, query: options.query, + hash: options.hash, }) return url diff --git a/src/services/createRouterRoute.ts b/src/services/createRouterRoute.ts index 9961c945..4e70b15e 100644 --- a/src/services/createRouterRoute.ts +++ b/src/services/createRouterRoute.ts @@ -13,6 +13,7 @@ export type RouterRoute = Readonly matches: TRoute['matches'], state: TRoute['state'], query: ResolvedRouteQuery, + hash: TRoute['hash'], params: Writable, update: RouteUpdate, }> diff --git a/src/services/urlAssembly.spec.ts b/src/services/urlAssembly.spec.ts index ff0dda35..24eb7a8f 100644 --- a/src/services/urlAssembly.spec.ts +++ b/src/services/urlAssembly.spec.ts @@ -358,4 +358,15 @@ describe('host params', () => { expect(url).toBe('ABC.kitbag.dev/') }) +}) + +test('given route with hash, returns url with hash value interpolated', () => { + const route = createRoute({ + name: 'simple', + path: '/', + }) + + const url = assembleUrl(route, { hash: 'foo' }) + + expect(url).toBe('/#foo') }) \ No newline at end of file diff --git a/src/services/urlAssembly.ts b/src/services/urlAssembly.ts index 2c2f0148..b1a41779 100644 --- a/src/services/urlAssembly.ts +++ b/src/services/urlAssembly.ts @@ -11,6 +11,7 @@ import { Route } from '@/types/route' type AssembleUrlOptions = { params?: Record, query?: Record, + hash?: string, } export function assembleUrl(route: Route, options: AssembleUrlOptions = {}): string { @@ -20,7 +21,10 @@ export function assembleUrl(route: Route, options: AssembleUrlOptions = {}): str const pathWithParamsSet = assemblePathParamValues(route.path, paramValues) const queryWithParamsSet = assembleQueryParamValues(route.query, paramValues) - return withQuery(`${hostWithParamsSet}${pathWithParamsSet}`, queryWithParamsSet, queryValues) + const url = withQuery(`${hostWithParamsSet}${pathWithParamsSet}`, queryWithParamsSet, queryValues) + const hash = options.hash ? `#${options.hash.replace(/^#/, '')}` : '' + + return `${url}${hash}` } function assembleHostParamValues(host: Host, paramValues: Record): string { diff --git a/src/types/routerPush.ts b/src/types/routerPush.ts index 2bfe469f..74990865 100644 --- a/src/types/routerPush.ts +++ b/src/types/routerPush.ts @@ -9,6 +9,7 @@ export type RouterPushOptions< TState = unknown > = { query?: Record, + hash?: string, replace?: boolean, state?: Partial, } diff --git a/src/types/routerReplace.ts b/src/types/routerReplace.ts index 018fe665..ee3648e3 100644 --- a/src/types/routerReplace.ts +++ b/src/types/routerReplace.ts @@ -9,6 +9,7 @@ export type RouterReplaceOptions< TState = unknown > = { query?: Record, + hash?: string, state?: Partial, } From 57c50038ba39b0e1fe97900b2716e0544ac7ba53 Mon Sep 17 00:00:00 2001 From: Evan Sutherland Date: Sun, 22 Sep 2024 08:28:03 -0500 Subject: [PATCH 2/4] revert file --- src/services/createRouterRoute.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/createRouterRoute.ts b/src/services/createRouterRoute.ts index 4e70b15e..9961c945 100644 --- a/src/services/createRouterRoute.ts +++ b/src/services/createRouterRoute.ts @@ -13,7 +13,6 @@ export type RouterRoute = Readonly matches: TRoute['matches'], state: TRoute['state'], query: ResolvedRouteQuery, - hash: TRoute['hash'], params: Writable, update: RouteUpdate, }> From b0c5013d6e9549e5993df7f6f0ce38e8fab693b4 Mon Sep 17 00:00:00 2001 From: Evan Sutherland Date: Sun, 22 Sep 2024 21:20:32 -0500 Subject: [PATCH 3/4] support for reading hash from resolved route --- src/services/createRouterRoute.ts | 4 +++- src/services/getResolvedRouteForUrl.browser.spec.ts | 11 +++++++++++ src/services/getResolvedRouteForUrl.ts | 3 ++- src/types/resolved.ts | 4 ++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/services/createRouterRoute.ts b/src/services/createRouterRoute.ts index 9961c945..fbcaf4cc 100644 --- a/src/services/createRouterRoute.ts +++ b/src/services/createRouterRoute.ts @@ -13,6 +13,7 @@ export type RouterRoute = Readonly matches: TRoute['matches'], state: TRoute['state'], query: ResolvedRouteQuery, + hash: TRoute['hash'], params: Writable, update: RouteUpdate, }> @@ -40,13 +41,14 @@ export function createRouterRoute(route: TRoute, p return push(route.name, params, maybeOptions) } - const { matched, matches, name, query, params, state } = toRefs(route) + const { matched, matches, name, query, params, state, hash } = toRefs(route) const routerRoute: RouterRoute = reactive({ matched, matches, state, query, + hash, params, name, update, diff --git a/src/services/getResolvedRouteForUrl.browser.spec.ts b/src/services/getResolvedRouteForUrl.browser.spec.ts index ee8755d1..ae860077 100644 --- a/src/services/getResolvedRouteForUrl.browser.spec.ts +++ b/src/services/getResolvedRouteForUrl.browser.spec.ts @@ -214,4 +214,15 @@ test('given state that matches state params, returns state', () => { const response = getResolvedRouteForUrl(routes, '/foo', { foo: 'true', bar: 'abc' }) expect(response?.state).toMatchObject({ foo: true, bar: 'abc' }) +}) + +test('given a route with hash returns hash property', () => { + const route = createRoute({ + name: 'route', + path: '/foo', + component, + }) + const response = getResolvedRouteForUrl([route], '/foo#bar') + + expect(response?.hash).toBe('#bar') }) \ No newline at end of file diff --git a/src/services/getResolvedRouteForUrl.ts b/src/services/getResolvedRouteForUrl.ts index 8708d68c..1028f1bd 100644 --- a/src/services/getResolvedRouteForUrl.ts +++ b/src/services/getResolvedRouteForUrl.ts @@ -27,7 +27,7 @@ export function getResolvedRouteForUrl(routes: Routes, url: string, state?: unkn } const [route] = matches - const { search } = createMaybeRelativeUrl(url) + const { search, hash } = createMaybeRelativeUrl(url) return { matched: route.matched, @@ -36,5 +36,6 @@ export function getResolvedRouteForUrl(routes: Routes, url: string, state?: unkn query: createResolvedRouteQuery(search), params: getRouteParamValues(route, url), state: getStateValues(route.state, state), + hash, } } \ No newline at end of file diff --git a/src/types/resolved.ts b/src/types/resolved.ts index 4c6a22e2..288367d4 100644 --- a/src/types/resolved.ts +++ b/src/types/resolved.ts @@ -25,6 +25,10 @@ export type ResolvedRoute = Readonly<{ * Accessor for query string values from user in the current browser location. */ query: ResolvedRouteQuery, + /** + * Hash value of the route. + */ + hash?: string, /** * Key value pair for route params, values will be the user provided value from current browser location. */ From f1079cbadd05453b220760cf521fbcf7d2fe1b93 Mon Sep 17 00:00:00 2001 From: Evan Sutherland Date: Sun, 22 Sep 2024 21:43:33 -0500 Subject: [PATCH 4/4] basic doc updates --- docs/api/types/ResolvedRoute.md | 8 ++++++++ docs/api/types/RouterPush.md | 1 + docs/api/types/RouterReplace.md | 1 + docs/api/types/RouterResolve.md | 1 + 4 files changed, 11 insertions(+) diff --git a/docs/api/types/ResolvedRoute.md b/docs/api/types/ResolvedRoute.md index eb618d6b..9dffe327 100644 --- a/docs/api/types/ResolvedRoute.md +++ b/docs/api/types/ResolvedRoute.md @@ -43,6 +43,14 @@ query: ResolvedRouteQuery; Accessor for query string values from user in the current browser location. [ResolvedRouteQuery](/api/types/ResolvedRouteQuery) +### hash + +```ts +hash?: string; +``` + +Accessor for hash string value (or undefined) from user in the current browser location. + ### params ```ts diff --git a/docs/api/types/RouterPush.md b/docs/api/types/RouterPush.md index 4352bb2b..4d6317ac 100644 --- a/docs/api/types/RouterPush.md +++ b/docs/api/types/RouterPush.md @@ -21,6 +21,7 @@ Push will update the URL for the browser and also add the URL into the history s { query?: Record, replace?: boolean, + hash?: string, } ``` diff --git a/docs/api/types/RouterReplace.md b/docs/api/types/RouterReplace.md index 674b9a43..8d2558b0 100644 --- a/docs/api/types/RouterReplace.md +++ b/docs/api/types/RouterReplace.md @@ -20,6 +20,7 @@ Replace has the same effect as [`RouterPush`](/api/types/RouterPush) but without ```ts { query?: Record, + hash?: string, } ``` diff --git a/docs/api/types/RouterResolve.md b/docs/api/types/RouterResolve.md index df1e68a1..1f427814 100644 --- a/docs/api/types/RouterResolve.md +++ b/docs/api/types/RouterResolve.md @@ -34,6 +34,7 @@ If source is `Url`, expected type for params is `never`. Else when source is `TS ```ts { query?: Record, + hash?: string, } ```