Skip to content

Commit

Permalink
Merge pull request #265 from kitbagjs/push-hash
Browse files Browse the repository at this point in the history
  • Loading branch information
stackoverfloweth authored Sep 23, 2024
2 parents 9814f1f + f1079cb commit a1c5bd6
Show file tree
Hide file tree
Showing 14 changed files with 57 additions and 3 deletions.
8 changes: 8 additions & 0 deletions docs/api/types/ResolvedRoute.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions docs/api/types/RouterPush.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Push will update the URL for the browser and also add the URL into the history s
{
query?: Record<string, string>,
replace?: boolean,
hash?: string,
}
```

Expand Down
1 change: 1 addition & 0 deletions docs/api/types/RouterReplace.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Replace has the same effect as [`RouterPush`](/api/types/RouterPush) but without
```ts
{
query?: Record<string, string>,
hash?: string,
}
```

Expand Down
1 change: 1 addition & 0 deletions docs/api/types/RouterResolve.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ If source is `Url`, expected type for params is `never`. Else when source is `TS
```ts
{
query?: Record<string, string>,
hash?: string,
}
```

Expand Down
6 changes: 6 additions & 0 deletions src/services/createRouterResolve.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
2 changes: 2 additions & 0 deletions src/services/createRouterResolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { AllPropertiesAreOptional } from '@/types/utilities'

export type RouterResolveOptions = {
query?: Record<string, string>,
hash?: string,
}

type RouterResolveArgs<
Expand Down Expand Up @@ -51,6 +52,7 @@ export function createRouterResolve<const TRoutes extends Routes>(routes: TRoute
const url = assembleUrl(match, {
params,
query: options.query,
hash: options.hash,
})

return url
Expand Down
4 changes: 3 additions & 1 deletion src/services/createRouterRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type RouterRoute<TRoute extends ResolvedRoute = ResolvedRoute> = Readonly
matches: TRoute['matches'],
state: TRoute['state'],
query: ResolvedRouteQuery,
hash: TRoute['hash'],
params: Writable<TRoute['params']>,
update: RouteUpdate<TRoute>,
}>
Expand Down Expand Up @@ -40,13 +41,14 @@ export function createRouterRoute<TRoute extends ResolvedRoute>(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<TRoute> = reactive({
matched,
matches,
state,
query,
hash,
params,
name,
update,
Expand Down
11 changes: 11 additions & 0 deletions src/services/getResolvedRouteForUrl.browser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
3 changes: 2 additions & 1 deletion src/services/getResolvedRouteForUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
}
}
11 changes: 11 additions & 0 deletions src/services/urlAssembly.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
6 changes: 5 additions & 1 deletion src/services/urlAssembly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Route } from '@/types/route'
type AssembleUrlOptions = {
params?: Record<string, unknown>,
query?: Record<string, string>,
hash?: string,
}

export function assembleUrl(route: Route, options: AssembleUrlOptions = {}): string {
Expand All @@ -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, unknown>): string {
Expand Down
4 changes: 4 additions & 0 deletions src/types/resolved.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export type ResolvedRoute<TRoute extends Route = Route> = 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.
*/
Expand Down
1 change: 1 addition & 0 deletions src/types/routerPush.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type RouterPushOptions<
TState = unknown
> = {
query?: Record<string, string>,
hash?: string,
replace?: boolean,
state?: Partial<TState>,
}
Expand Down
1 change: 1 addition & 0 deletions src/types/routerReplace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type RouterReplaceOptions<
TState = unknown
> = {
query?: Record<string, string>,
hash?: string,
state?: Partial<TState>,
}

Expand Down

0 comments on commit a1c5bd6

Please sign in to comment.