diff --git a/.changeset/witty-vans-smash.md b/.changeset/witty-vans-smash.md new file mode 100644 index 000000000000..858c1366b824 --- /dev/null +++ b/.changeset/witty-vans-smash.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': major +--- + +fix: navigate without reloading for links with a `target` attribute and will display in the current browsing context diff --git a/packages/kit/src/runtime/client/utils.js b/packages/kit/src/runtime/client/utils.js index 28a06d862489..46ecd08f091a 100644 --- a/packages/kit/src/runtime/client/utils.js +++ b/packages/kit/src/runtime/client/utils.js @@ -136,7 +136,7 @@ export function get_link_info(a, base, uses_hash_router) { const external = !url || - !!target || + (target || '_self') !== '_self' || is_external_url(url, base, uses_hash_router) || (a.getAttribute('rel') || '').split(/\s+/).includes('external'); diff --git a/packages/kit/test/apps/basics/src/routes/routing/+page.svelte b/packages/kit/test/apps/basics/src/routes/routing/+page.svelte index 2d5d50c8c338..4d125e45f016 100644 --- a/packages/kit/test/apps/basics/src/routes/routing/+page.svelte +++ b/packages/kit/test/apps/basics/src/routes/routing/+page.svelte @@ -14,3 +14,7 @@ b
+ +_self +_parent +_top diff --git a/packages/kit/test/apps/basics/test/cross-platform/client.test.js b/packages/kit/test/apps/basics/test/cross-platform/client.test.js index 5ac76c9b724c..42fe4d3cb33c 100644 --- a/packages/kit/test/apps/basics/test/cross-platform/client.test.js +++ b/packages/kit/test/apps/basics/test/cross-platform/client.test.js @@ -737,6 +737,32 @@ test.describe('Routing', () => { expect(requests.filter((url) => !url.endsWith('/favicon.png'))).toEqual([]); }); + test('navigates to a new page without reloading when `target` is the current browsing context', async ({ + app, + page, + clicknav + }) => { + const targets = ['_self', '_parent', '_top']; + + for (const target of targets) { + await page.goto('/routing'); + + await app.preloadData('/routing/a?target').catch((e) => { + // from error handler tests; ignore + if (!e.message.includes('Crashing now')) throw e; + }); + + /** @type {string[]} */ + const requests = []; + page.on('request', (r) => requests.push(r.url())); + + await clicknav(`a[target="${target}"]`); + expect(await page.textContent('h1')).toBe('a'); + + expect(requests.filter((url) => !url.endsWith('/favicon.png'))).toEqual([]); + } + }); + test('navigates programmatically', async ({ page, app }) => { await page.goto('/routing/a'); await app.goto('/routing/b');