Repository: sveltejs/kit (js)

Issue:
`create-svelte` duplicates app template options.
### Describe the bug

When moving away from the "SvelteKit demo app" option in the `create-svelte` CLI, the option will duplicate.

### Reproduction

1. Run `npm create svelte duplication-repro`.
2. Press down arrow key.
3. "SvelteKit demo app" option will appear twice. If you move back up and down, it will duplicate again.

### Logs

```Shell
❯ npm create svelte duplication-repro

create-svelte version 3.1.0

┌  Welcome to SvelteKit!
│
◆  Which Svelte app template?
│  ● SvelteKit demo app (A demo app showcasing some of the features of SvelteKit - play a word guessing game that works
│  ● SvelteKit demo app (A demo app showcasing some of the features of SvelteKit - play a word guessing game that works
│  ● SvelteKit demo app (A demo app showcasing some of the features of SvelteKit - play a word guessing game that works
│  ● SvelteKit demo app (A demo app showcasing some of the features of SvelteKit - play a word guessing game that works
│  ● SvelteKit demo app (A demo app showcasing some of the features of SvelteKit - play a word guessing game that works
│  ● SvelteKit demo app (A demo app showcasing some of the features of SvelteKit - play a word guessing game that works
│  ● SvelteKit demo app (A demo app showcasing some of the features of SvelteKit - play a word guessing game that works without JavaScript!)
│  ○ Skeleton project
│  ○ Library project
```


### System Info

```Shell
System:
    OS: Linux 5.15 Ubuntu 22.04.1 LTS 22.04.1 LTS (Jammy Jellyfish)
    CPU: (8) x64 Intel(R) Core(TM) i5-1035G1 CPU @ 1.00GHz
    Memory: 808.49 MB / 1.86 GB
    Container: Yes
    Shell: 5.8.1 - /usr/bin/zsh
Binaries:
    Node: 19.4.0 - ~/.nvm/versions/node/v19.4.0/bin/node
    npm: 9.3.1 - ~/.nvm/versions/node/v19.4.0/bin/npm
Browsers:
    Chrome: 110.0.5481.100
```


### Severity

annoyance

### Additional Information

_No response_

Pull request:
update @clack/prompts
closes #9231

### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [ ] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [ ] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`.


Patch:
diff --git a/.changeset/breezy-beans-peel.md b/.changeset/breezy-beans-peel.md
new file mode 100644
index 000000000..a562bbf60
--- /dev/null
+++ b/.changeset/breezy-beans-peel.md
@@ -0,0 +1,5 @@
+---
+'create-svelte': patch
+---
+
+fix: prevent duplicated lines in project creation CLI
diff --git a/.changeset/dirty-pianos-try.md b/.changeset/dirty-pianos-try.md
new file mode 100644
index 000000000..1a83f1748
--- /dev/null
+++ b/.changeset/dirty-pianos-try.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: use 308 responses for trailing slash redirects, instead of 301s
diff --git a/.changeset/gold-ways-repair.md b/.changeset/gold-ways-repair.md
new file mode 100644
index 000000000..c08ba1148
--- /dev/null
+++ b/.changeset/gold-ways-repair.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: don't prevent `beforeNavigate` callbacks from running following a cancelled unloading navigation
diff --git a/.changeset/itchy-jobs-leave.md b/.changeset/itchy-jobs-leave.md
new file mode 100644
index 000000000..bb6c03672
--- /dev/null
+++ b/.changeset/itchy-jobs-leave.md
@@ -0,0 +1,6 @@
+---
+'@sveltejs/adapter-netlify': patch
+'@sveltejs/adapter-vercel': patch
+---
+
+docs: remove comment discourage direct use of adapters
diff --git a/packages/adapter-netlify/README.md b/packages/adapter-netlify/README.md
index ccbd34426..a5ae3a601 100644
--- a/packages/adapter-netlify/README.md
+++ b/packages/adapter-netlify/README.md
@@ -2,8 +2,6 @@
 
 A SvelteKit adapter that creates a Netlify app.
 
-If you're using [adapter-auto](https://kit.svelte.dev/docs/adapter-auto), you don't need to install this unless you need to specify Netlify-specific options, since it's already included.
-
 ## Docs
 
 [Docs](https://kit.svelte.dev/docs/adapter-netlify)
diff --git a/packages/adapter-vercel/README.md b/packages/adapter-vercel/README.md
index 6c9f1278a..8a09e256d 100644
--- a/packages/adapter-vercel/README.md
+++ b/packages/adapter-vercel/README.md
@@ -2,8 +2,6 @@
 
 A SvelteKit adapter that creates a Vercel app.
 
-If you're using [adapter-auto](https://kit.svelte.dev/docs/adapter-auto), you don't need to install this unless you need to specify Vercel-specific options, since it's already included.
-
 ## Docs
 
 [Docs](https://kit.svelte.dev/docs/adapter-vercel)
diff --git a/packages/create-svelte/bin.js b/packages/create-svelte/bin.js
index 04a61ae16..ce5251d69 100755
--- a/packages/create-svelte/bin.js
+++ b/packages/create-svelte/bin.js
@@ -47,6 +47,7 @@ const options = await p.group(
 		template: () =>
 			p.select({
 				message: 'Which Svelte app template?',
+				// @ts-expect-error i have no idea what is going on here
 				options: fs.readdirSync(dist('templates')).map((dir) => {
 					const meta_file = dist(`templates/${dir}/meta.json`);
 					const { title, description } = JSON.parse(fs.readFileSync(meta_file, 'utf8'));
@@ -65,10 +66,12 @@ const options = await p.group(
 				options: [
 					{
 						label: 'Yes, using JavaScript with JSDoc comments',
+						// @ts-expect-error :shrug:
 						value: 'checkjs'
 					},
 					{
 						label: 'Yes, using TypeScript syntax',
+						// @ts-expect-error :shrug:
 						value: 'typescript'
 					},
 					{ label: 'No', value: null }
diff --git a/packages/create-svelte/package.json b/packages/create-svelte/package.json
index 747f803a4..1f5c2a609 100644
--- a/packages/create-svelte/package.json
+++ b/packages/create-svelte/package.json
@@ -11,7 +11,7 @@
 	"bin": "./bin.js",
 	"main": "./index.js",
 	"dependencies": {
-		"@clack/prompts": "^0.6.0",
+		"@clack/prompts": "^0.6.3",
 		"kleur": "^4.1.5"
 	},
 	"devDependencies": {
diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js
index f4c12fe23..41cb3b376 100644
--- a/packages/kit/src/runtime/client/client.js
+++ b/packages/kit/src/runtime/client/client.js
@@ -1521,11 +1521,14 @@ export function create_client(app, target) {
 
 				// Ignore the following but fire beforeNavigate
 				if (external || options.reload) {
-					const navigation = before_navigate({ url, type: 'link' });
-					if (!navigation) {
+					if (before_navigate({ url, type: 'link' })) {
+						// set `navigating` to `true` to prevent `beforeNavigate` callbacks
+						// being called when the page unloads
+						navigating = true;
+					} else {
 						event.preventDefault();
 					}
-					navigating = true;
+
 					return;
 				}
 
diff --git a/packages/kit/src/runtime/server/respond.js b/packages/kit/src/runtime/server/respond.js
index 0707898df..13d89588a 100644
--- a/packages/kit/src/runtime/server/respond.js
+++ b/packages/kit/src/runtime/server/respond.js
@@ -213,7 +213,7 @@ export async function respond(request, options, manifest, state) {
 
 			if (normalized !== url.pathname && !state.prerendering?.fallback) {
 				return new Response(undefined, {
-					status: 301,
+					status: 308,
 					headers: {
 						'x-sveltekit-normalize': '1',
 						location:
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 59614f098..0578685eb 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -207,7 +207,7 @@ importers:
 
   packages/create-svelte:
     specifiers:
-      '@clack/prompts': ^0.6.0
+      '@clack/prompts': ^0.6.3
       '@playwright/test': ^1.28.1
       '@types/gitignore-parser': ^0.0.0
       '@types/prettier': ^2.7.1
@@ -221,7 +221,7 @@ importers:
       tiny-glob: ^0.2.9
       uvu: ^0.5.6
     dependencies:
-      '@clack/prompts': 0.6.0
+      '@clack/prompts': 0.6.3
       kleur: 4.1.5
     devDependencies:
       '@playwright/test': 1.29.2
@@ -973,17 +973,17 @@ packages:
       prettier: 2.8.0
     dev: true
 
-  /@clack/core/0.3.0:
-    resolution: {integrity: sha512-ujw1888RciTArxUvwLOf24XSygRX7F4qiCPI7WLH3zCTZJuqKPMcTS7Wqjz0x/AuMpwGPlzhKln4+sCuQqYxzA==}
+  /@clack/core/0.3.2:
+    resolution: {integrity: sha512-FZnsNynwGDIDktx6PEZK1EuCkFpY4ldEX6VYvfl0dqeoLPb9Jpw1xoUXaVcGR8ExmYNm1w2vdGdJkEUYD/2pqg==}
     dependencies:
       picocolors: 1.0.0
       sisteransi: 1.0.5
     dev: false
 
-  /@clack/prompts/0.6.0:
-    resolution: {integrity: sha512-lNg3MFPLA2rrMAZ6R2QFg+jGo2Pt3ACJERDbPgxjPU9QJwVFB3D2v3x7SzzVoS6schggcMN0tDJ4zSdcI+kqJg==}
+  /@clack/prompts/0.6.3:
+    resolution: {integrity: sha512-AM+kFmAHawpUQv2q9+mcB6jLKxXGjgu/r2EQjEwujgpCdzrST6BJqYw00GRn56/L/Izw5U7ImoLmy00X/r80Pw==}
     dependencies:
-      '@clack/core': 0.3.0
+      '@clack/core': 0.3.2
       picocolors: 1.0.0
       sisteransi: 1.0.5
     dev: false


Test patch:
diff --git a/packages/kit/test/apps/basics/src/routes/before-navigate/prevent-navigation/+page.svelte b/packages/kit/test/apps/basics/src/routes/before-navigate/prevent-navigation/+page.svelte
index 3f76f2cf9..1e30b09f6 100644
--- a/packages/kit/test/apps/basics/src/routes/before-navigate/prevent-navigation/+page.svelte
+++ b/packages/kit/test/apps/basics/src/routes/before-navigate/prevent-navigation/+page.svelte
@@ -17,6 +17,7 @@
 <h1>prevent navigation</h1>
 <a href="/before-navigate/a">a</a>
 <a href="/before-navigate/redirect">redirect</a>
+<a href="/before-navigate/prevent-navigation?x=1">self</a>
 <a href="https://google.com" target="_blank" rel="noreferrer">_blank</a>
 <a href="https://google.de">external</a>
 <pre>{times_triggered} {unload} {navigation_type}</pre>
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 f9109342f..e4d86df02 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
@@ -200,6 +200,19 @@ test.describe('beforeNavigate', () => {
 		await page.goBack();
 		expect(await page.textContent('h1')).toBe('before_navigate_ran: false');
 	});
+
+	test('cancel() on an unloading navigation does not prevent subsequent beforeNavigate callbacks', async ({
+		page,
+		app
+	}) => {
+		await page.goto('/before-navigate/prevent-navigation');
+		await page.click('h1'); // The browsers block attempts to prevent navigation on a frame that's never had a user gesture.
+
+		await app.goto('https://google.de');
+		await app.goto('/before-navigate/prevent-navigation?x=1');
+
+		expect(await page.innerHTML('pre')).toBe('2 false goto');
+	});
 });
 
 test.describe('Scrolling', () => {
diff --git a/packages/kit/test/apps/options/test/test.js b/packages/kit/test/apps/options/test/test.js
index d50125ae8..9921b6ef8 100644
--- a/packages/kit/test/apps/options/test/test.js
+++ b/packages/kit/test/apps/options/test/test.js
@@ -1,3 +1,4 @@
+import * as http from 'node:http';
 import { expect } from '@playwright/test';
 import { test } from '../../../utils.js';
 
@@ -173,6 +174,16 @@ test.describe('env', () => {
 
 test.describe('trailingSlash', () => {
 	test('adds trailing slash', async ({ baseURL, page, clicknav }) => {
+		// we can't use Playwright's `request` here, because it resolves redirects
+		const status = await new Promise((fulfil, reject) => {
+			const request = http.get(`${baseURL}/path-base/slash`);
+			request.on('error', reject);
+			request.on('response', (response) => {
+				fulfil(response.statusCode);
+			});
+		});
+		expect(status).toBe(308);
+
 		await page.goto('/path-base/slash');
 
 		expect(page.url()).toBe(`${baseURL}/path-base/slash/`);