From 9556abae4ba28c02ba468735beb9eb868876a9a1 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Tue, 9 Jan 2024 22:28:52 +0800 Subject: [PATCH] fix: respect trailing slash option when navigating from the root page of the basepath (#11388) * add failing test * only resolve root page trailing slash during navigation * changeset * fix test --------- Co-authored-by: Rich Harris --- .changeset/five-garlics-greet.md | 5 +++++ packages/kit/src/runtime/client/client.js | 20 +++++++++++-------- .../apps/options-2/src/routes/+page.svelte | 2 ++ packages/kit/test/apps/options-2/test/test.js | 15 ++++++++++++++ 4 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 .changeset/five-garlics-greet.md diff --git a/.changeset/five-garlics-greet.md b/.changeset/five-garlics-greet.md new file mode 100644 index 000000000000..8b1e1b123639 --- /dev/null +++ b/.changeset/five-garlics-greet.md @@ -0,0 +1,5 @@ +--- +"@sveltejs/kit": patch +--- + +fix: respect the trailing slash option when navigating from the basepath root page diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 33c9c54a6844..f71e93d6f149 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -441,10 +441,19 @@ async function get_navigation_result_from_branch({ }) { /** @type {import('types').TrailingSlash} */ let slash = 'never'; - for (const node of branch) { - if (node?.slash !== undefined) slash = node.slash; + + // if `paths.base === '/a/b/c`, then the root route is always `/a/b/c/`, regardless of + // the `trailingSlash` route option, so that relative paths to JS and CSS work + if (base && (url.pathname === base || url.pathname === base + '/')) { + slash = 'always'; + } else { + for (const node of branch) { + if (node?.slash !== undefined) slash = node.slash; + } } + url.pathname = normalize_path(url.pathname, slash); + // eslint-disable-next-line url.search = url.search; // turn `/?` into `/` @@ -694,12 +703,7 @@ async function load_node({ loader, parent, url, params, route, server_data_node server: server_data_node, universal: node.universal?.load ? { type: 'data', data, uses } : null, data: data ?? server_data_node?.data ?? null, - // if `paths.base === '/a/b/c`, then the root route is always `/a/b/c/`, regardless of - // the `trailingSlash` route option, so that relative paths to JS and CSS work - slash: - base && (url.pathname === base || url.pathname === base + '/') - ? 'always' - : node.universal?.trailingSlash ?? server_data_node?.slash + slash: node.universal?.trailingSlash ?? server_data_node?.slash }; } diff --git a/packages/kit/test/apps/options-2/src/routes/+page.svelte b/packages/kit/test/apps/options-2/src/routes/+page.svelte index d6232afc0cc9..badacc8173d8 100644 --- a/packages/kit/test/apps/options-2/src/routes/+page.svelte +++ b/packages/kit/test/apps/options-2/src/routes/+page.svelte @@ -6,3 +6,5 @@

base: {base}

assets: {assets}

+ +Go to /hello diff --git a/packages/kit/test/apps/options-2/test/test.js b/packages/kit/test/apps/options-2/test/test.js index 7defc47a6804..3f9514de8799 100644 --- a/packages/kit/test/apps/options-2/test/test.js +++ b/packages/kit/test/apps/options-2/test/test.js @@ -37,6 +37,21 @@ test.describe('paths', () => { expect(await page.textContent('[data-testid="base"]')).toBe(`base: ${base}`); expect(await page.textContent('[data-testid="assets"]')).toBe(`assets: ${base}`); }); + + test('serves /basepath with trailing slash always', async ({ page }) => { + await page.goto('/basepath'); + expect(new URL(page.url()).pathname).toBe('/basepath/'); + }); + + test('respects trailing slash option when navigating from /basepath', async ({ + page, + clicknav + }) => { + await page.goto('/basepath'); + expect(new URL(page.url()).pathname).toBe('/basepath/'); + await clicknav('[data-testid="link"]'); + expect(new URL(page.url()).pathname).toBe('/basepath/hello'); + }); }); test.describe('Service worker', () => {