diff --git a/.changeset/blue-baboons-jam.md b/.changeset/blue-baboons-jam.md new file mode 100644 index 000000000000..1b8e646a27b0 --- /dev/null +++ b/.changeset/blue-baboons-jam.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: include hash when using `resolve` with hash routing enabled diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 4a441b23d4d5..7d6cf2a9589f 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -350,6 +350,7 @@ async function kit({ svelte_config }) { __SVELTEKIT_PATHS_BASE__: s(kit.paths.base), __SVELTEKIT_PATHS_RELATIVE__: s(kit.paths.relative), __SVELTEKIT_CLIENT_ROUTING__: s(kit.router.resolution === 'client'), + __SVELTEKIT_HASH_ROUTING__: s(kit.router.type === 'hash'), __SVELTEKIT_SERVER_TRACING_ENABLED__: s(kit.experimental.tracing.server) }; diff --git a/packages/kit/src/runtime/app/paths/client.js b/packages/kit/src/runtime/app/paths/client.js index 510f42ede418..4de84a1d7c8f 100644 --- a/packages/kit/src/runtime/app/paths/client.js +++ b/packages/kit/src/runtime/app/paths/client.js @@ -1,6 +1,6 @@ /** @import { Asset, RouteId, Pathname, ResolvedPathname } from '$app/types' */ /** @import { ResolveArgs } from './types.js' */ -import { base, assets } from './internal/client.js'; +import { base, assets, hash_routing } from './internal/client.js'; import { resolve_route } from '../../../utils/routing.js'; /** @@ -25,6 +25,8 @@ export function asset(file) { return (assets || base) + file; } +const pathname_prefix = hash_routing ? '#' : ''; + /** * Resolve a pathname by prefixing it with the base path, if any, or resolve a route ID by populating dynamic segments with parameters. * @@ -51,7 +53,9 @@ export function asset(file) { export function resolve(...args) { // The type error is correct here, and if someone doesn't pass params when they should there's a runtime error, // but we don't want to adjust the internal resolve_route function to accept `undefined`, hence the type cast. - return base + resolve_route(args[0], /** @type {Record} */ (args[1])); + return ( + base + pathname_prefix + resolve_route(args[0], /** @type {Record} */ (args[1])) + ); } export { base, assets, resolve as resolveRoute }; diff --git a/packages/kit/src/runtime/app/paths/internal/client.js b/packages/kit/src/runtime/app/paths/internal/client.js index 462b95de28b9..a5679afff6ef 100644 --- a/packages/kit/src/runtime/app/paths/internal/client.js +++ b/packages/kit/src/runtime/app/paths/internal/client.js @@ -1,3 +1,4 @@ export const base = __SVELTEKIT_PAYLOAD__?.base ?? __SVELTEKIT_PATHS_BASE__; export const assets = __SVELTEKIT_PAYLOAD__?.assets ?? base ?? __SVELTEKIT_PATHS_ASSETS__; export const app_dir = __SVELTEKIT_APP_DIR__; +export const hash_routing = __SVELTEKIT_HASH_ROUTING__; diff --git a/packages/kit/src/types/global-private.d.ts b/packages/kit/src/types/global-private.d.ts index 3ab871bd5b48..47c78935ba23 100644 --- a/packages/kit/src/types/global-private.d.ts +++ b/packages/kit/src/types/global-private.d.ts @@ -13,6 +13,8 @@ declare global { const __SVELTEKIT_EXPERIMENTAL__REMOTE_FUNCTIONS__: boolean; /** True if `config.kit.router.resolution === 'client'` */ const __SVELTEKIT_CLIENT_ROUTING__: boolean; + /** True if `config.kit.router.type === 'hash'` */ + const __SVELTEKIT_HASH_ROUTING__: boolean; /** * True if any node in the manifest has a server load function. * Used for treeshaking server load code from client bundles when no server loads exist. diff --git a/packages/kit/test/apps/hash-based-routing/src/routes/resolve/+page.svelte b/packages/kit/test/apps/hash-based-routing/src/routes/resolve/+page.svelte new file mode 100644 index 000000000000..e86f737a7b40 --- /dev/null +++ b/packages/kit/test/apps/hash-based-routing/src/routes/resolve/+page.svelte @@ -0,0 +1,5 @@ + + +go to home diff --git a/packages/kit/test/apps/hash-based-routing/test/test.js b/packages/kit/test/apps/hash-based-routing/test/test.js index de423cc9bcb0..6801d80444d0 100644 --- a/packages/kit/test/apps/hash-based-routing/test/test.js +++ b/packages/kit/test/apps/hash-based-routing/test/test.js @@ -126,4 +126,13 @@ test.describe('hash based navigation', () => { await expect(page.locator('#button3')).toBeFocused(); await expect(page.locator('button[id="button3"]')).toBeFocused(); }); + + test('resolve works', async ({ page }) => { + await page.goto('/#/resolve'); + await page.locator('a', { hasText: 'go to home' }).click(); + await expect(page.locator('p')).toHaveText('home'); + const url = new URL(page.url()); + expect(url.pathname).toBe('/'); + expect(url.hash).toBe('#/'); + }); });