diff --git a/.changeset/great-stingrays-flash.md b/.changeset/great-stingrays-flash.md new file mode 100644 index 000000000000..19b89c84c35a --- /dev/null +++ b/.changeset/great-stingrays-flash.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: use correct relative paths when rendering base path diff --git a/packages/kit/src/runtime/server/page/render.js b/packages/kit/src/runtime/server/page/render.js index 22be19737272..d330001c47a1 100644 --- a/packages/kit/src/runtime/server/page/render.js +++ b/packages/kit/src/runtime/server/page/render.js @@ -95,23 +95,12 @@ export async function render_response({ // if appropriate, use relative paths for greater portability if (paths.relative !== false && !state.prerendering?.fallback) { - const segments = event.url.pathname.slice(paths.base.length).split('/'); + const segments = event.url.pathname.slice(paths.base.length).split('/').slice(2); - if (segments.length === 1 && paths.base !== '') { - // if we're on `/my-base-path`, relative links need to start `./my-base-path` rather than `.` - base = `./${paths.base.split('/').at(-1)}`; + base = segments.map(() => '..').join('/') || '.'; - base_expression = `new URL(${s(base)}, location).pathname`; - } else { - base = - segments - .slice(2) - .map(() => '..') - .join('/') || '.'; - - // resolve e.g. '../..' against current location, then remove trailing slash - base_expression = `new URL(${s(base)}, location).pathname.slice(0, -1)`; - } + // resolve e.g. '../..' against current location, then remove trailing slash + base_expression = `new URL(${s(base)}, location).pathname.slice(0, -1)`; if (!paths.assets || (paths.assets[0] === '/' && paths.assets !== SVELTE_KIT_ASSETS)) { assets = base; diff --git a/packages/kit/src/runtime/server/respond.js b/packages/kit/src/runtime/server/respond.js index 0707898dff72..972dc85629ae 100644 --- a/packages/kit/src/runtime/server/respond.js +++ b/packages/kit/src/runtime/server/respond.js @@ -172,7 +172,11 @@ export async function respond(request, options, manifest, state) { try { // determine whether we need to redirect to add/remove a trailing slash if (route && !is_data_request) { - if (route.page) { + // if `paths.base === '/a/b/c`, then the root route is `/a/b/c/`, + // regardless of the `trailingSlash` route option + if (url.pathname === base || url.pathname === base + '/') { + trailing_slash = 'always'; + } else if (route.page) { const nodes = await Promise.all([ // we use == here rather than === because [undefined] serializes as "[null]" ...route.page.layouts.map((n) => (n == undefined ? n : manifest._.nodes[n]())), diff --git a/packages/kit/test/apps/options-2/test/test.js b/packages/kit/test/apps/options-2/test/test.js index 31520020b8f0..baf3038d3f41 100644 --- a/packages/kit/test/apps/options-2/test/test.js +++ b/packages/kit/test/apps/options-2/test/test.js @@ -27,7 +27,7 @@ test.describe('paths', () => { test('uses relative paths during SSR', async ({ page, javaScriptEnabled }) => { await page.goto('/basepath'); - let base = javaScriptEnabled ? '/basepath' : './basepath'; + let base = javaScriptEnabled ? '/basepath' : '.'; expect(await page.textContent('[data-testid="base"]')).toBe(`base: ${base}`); expect(await page.textContent('[data-testid="assets"]')).toBe(`assets: ${base}`);