Repository: sveltejs/kit
Pull request #7939 (2022-12-04 19:34:50)

[fix]Continuous optionals should not throw conflict error
fix issue [7925](https://github.com/sveltejs/kit/issues/7925)

folder structure [[a]]/[[b]]/+page will throw routes conflict error

the error from the function `prevent_conflicts`

here:
```
permutations = [
...permutations.map((x) => x + next),
...permutations.map((x) => x + `<${matcher}>${next}`)
];
```
will generate permutations [ '//', '/<*>/', '//<*>', '/<*>/<*>' ]
but  actually, it' impossible match route  /empty/[[b]] . so '//<*>' should be remove from result.




### 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.
- [x] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] 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. All changesets should be `patch` until SvelteKit 1.0


changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: f0d58667ed0941dbbfa903292c00cde132360bca

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/master/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/aolose/kit/new/7925?filename=.changeset/poor-ads-clap.md&value=---%0A%22%40sveltejs%2Fkit%22%3A%20patch%0A---%0A%0A%5Bfix%5DContinuous%20optionals%20should%20not%20throw%20conflict%20error%0A)



Patch:
diff --git a/.changeset/chatty-mice-tan.md b/.changeset/chatty-mice-tan.md
new file mode 100644
index 000000000..49e6b85ce
--- /dev/null
+++ b/.changeset/chatty-mice-tan.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': minor
+---
+
+Checks that element is not null before reading getAttribute
diff --git a/.changeset/healthy-readers-camp.md b/.changeset/healthy-readers-camp.md
new file mode 100644
index 000000000..6e95d9145
--- /dev/null
+++ b/.changeset/healthy-readers-camp.md
@@ -0,0 +1,5 @@
+---
+"@sveltejs/kit": patch
+---
+
+[chore] update `magic-string`
diff --git a/.changeset/healthy-walls-move.md b/.changeset/healthy-walls-move.md
new file mode 100644
index 000000000..a5ff8ab9b
--- /dev/null
+++ b/.changeset/healthy-walls-move.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+add $app and $env to optimizeDeps.exclude so that libraries using these work correctly when prebundled
diff --git a/.changeset/hot-news-bake.md b/.changeset/hot-news-bake.md
new file mode 100644
index 000000000..ab6178a23
--- /dev/null
+++ b/.changeset/hot-news-bake.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+reload dev page on change of app.html
diff --git a/.changeset/pre.json b/.changeset/pre.json
index 3066e4224..241f28a59 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -148,6 +148,7 @@
     "chatty-ducks-shop",
     "chatty-impalas-smash",
     "chatty-mangos-raise",
+    "chatty-mice-tan",
     "chatty-moose-love",
     "chatty-pumas-shake",
     "chatty-steaks-yell",
@@ -530,8 +531,10 @@
     "healthy-penguins-fail",
     "healthy-pigs-fly",
     "healthy-pumpkins-bathe",
+    "healthy-readers-camp",
     "healthy-rivers-share",
     "healthy-vans-build",
+    "healthy-walls-move",
     "healthy-wasps-poke",
     "heavy-donuts-grab",
     "heavy-forks-search",
@@ -577,6 +580,7 @@
     "hot-kings-confess",
     "hot-lions-cough",
     "hot-mayflies-visit",
+    "hot-news-bake",
     "hot-planes-shout",
     "hot-shoes-bow",
     "hot-steaks-hang",
diff --git a/.changeset/six-ravens-attack.md b/.changeset/six-ravens-attack.md
new file mode 100644
index 000000000..c2217a344
--- /dev/null
+++ b/.changeset/six-ravens-attack.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+[fix] continuous optionals should not throw conflict error
diff --git a/package.json b/package.json
index c5f41dbdd..4860b91e7 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
 		"@rollup/plugin-commonjs": "^23.0.3",
 		"@rollup/plugin-json": "^5.0.2",
 		"@rollup/plugin-node-resolve": "^15.0.1",
-		"@svitejs/changesets-changelog-github-compact": "^0.1.1",
+		"@svitejs/changesets-changelog-github-compact": "^1.0.0",
 		"playwright": "^1.28.1",
 		"prettier": "^2.8.0",
 		"rollup": "^2.79.1",
@@ -35,7 +35,7 @@
 		"turbo": "^1.6.3",
 		"typescript": "^4.9.3"
 	},
-	"packageManager": "pnpm@7.17.1",
+	"packageManager": "pnpm@7.18.0",
 	"engines": {
 		"pnpm": "^7.0.0"
 	},
diff --git a/packages/adapter-auto/package.json b/packages/adapter-auto/package.json
index e18da9512..65f5521e2 100644
--- a/packages/adapter-auto/package.json
+++ b/packages/adapter-auto/package.json
@@ -31,7 +31,7 @@
 	},
 	"devDependencies": {
 		"@sveltejs/kit": "workspace:*",
-		"@types/node": "^16.18.3",
+		"@types/node": "^16.18.6",
 		"typescript": "^4.9.3"
 	},
 	"dependencies": {
diff --git a/packages/adapter-cloudflare-workers/package.json b/packages/adapter-cloudflare-workers/package.json
index 9ca433bfb..400d7484b 100644
--- a/packages/adapter-cloudflare-workers/package.json
+++ b/packages/adapter-cloudflare-workers/package.json
@@ -35,7 +35,7 @@
 	},
 	"devDependencies": {
 		"@cloudflare/kv-asset-handler": "^0.2.0",
-		"@types/node": "^16.18.3",
+		"@types/node": "^16.18.6",
 		"typescript": "^4.9.3"
 	}
 }
diff --git a/packages/adapter-cloudflare/package.json b/packages/adapter-cloudflare/package.json
index 50bf3f004..79b22f99a 100644
--- a/packages/adapter-cloudflare/package.json
+++ b/packages/adapter-cloudflare/package.json
@@ -37,7 +37,7 @@
 		"worktop": "0.8.0-next.14"
 	},
 	"devDependencies": {
-		"@types/node": "^16.18.3",
+		"@types/node": "^16.18.6",
 		"@types/ws": "^8.5.3",
 		"typescript": "^4.9.3"
 	},
diff --git a/packages/adapter-netlify/package.json b/packages/adapter-netlify/package.json
index c14f4d009..06973d96a 100644
--- a/packages/adapter-netlify/package.json
+++ b/packages/adapter-netlify/package.json
@@ -42,7 +42,7 @@
 		"@rollup/plugin-json": "^5.0.2",
 		"@rollup/plugin-node-resolve": "^15.0.1",
 		"@sveltejs/kit": "workspace:*",
-		"@types/node": "^16.18.3",
+		"@types/node": "^16.18.6",
 		"@types/set-cookie-parser": "^2.4.2",
 		"rimraf": "^3.0.2",
 		"rollup": "^2.79.1",
diff --git a/packages/adapter-node/package.json b/packages/adapter-node/package.json
index 83f3d5e7e..6fe0ff230 100644
--- a/packages/adapter-node/package.json
+++ b/packages/adapter-node/package.json
@@ -33,7 +33,7 @@
 	},
 	"devDependencies": {
 		"@sveltejs/kit": "workspace:*",
-		"@types/node": "^16.18.3",
+		"@types/node": "^16.18.6",
 		"c8": "^7.12.0",
 		"polka": "^1.0.0-next.22",
 		"rimraf": "^3.0.2",
diff --git a/packages/adapter-static/package.json b/packages/adapter-static/package.json
index 33b3c32e8..97a02170b 100644
--- a/packages/adapter-static/package.json
+++ b/packages/adapter-static/package.json
@@ -26,7 +26,7 @@
 	},
 	"devDependencies": {
 		"@sveltejs/kit": "workspace:*",
-		"@types/node": "^16.18.3",
+		"@types/node": "^16.18.6",
 		"sirv": "^2.0.2",
 		"svelte": "^3.53.1",
 		"typescript": "^4.9.3",
diff --git a/packages/adapter-vercel/package.json b/packages/adapter-vercel/package.json
index 7a048c5f5..f016b27c0 100644
--- a/packages/adapter-vercel/package.json
+++ b/packages/adapter-vercel/package.json
@@ -33,7 +33,7 @@
 	},
 	"devDependencies": {
 		"@sveltejs/kit": "workspace:*",
-		"@types/node": "^16.18.3",
+		"@types/node": "^16.18.6",
 		"typescript": "^4.9.3"
 	}
 }
diff --git a/packages/kit/CHANGELOG.md b/packages/kit/CHANGELOG.md
index be50844d2..a5c7dacd9 100644
--- a/packages/kit/CHANGELOG.md
+++ b/packages/kit/CHANGELOG.md
@@ -1,5 +1,19 @@
 # @sveltejs/kit
 
+## 1.0.0-next.572
+
+### Minor Changes
+
+- Checks that element is not null before reading getAttribute ([#7930](https://github.com/sveltejs/kit/pull/7930))
+
+### Patch Changes
+
+- [chore] update `magic-string` ([#7931](https://github.com/sveltejs/kit/pull/7931))
+
+- add $app and $env to optimizeDeps.exclude so that libraries using these work correctly when prebundled ([#7933](https://github.com/sveltejs/kit/pull/7933))
+
+- reload dev page on change of app.html ([#7944](https://github.com/sveltejs/kit/pull/7944))
+
 ## 1.0.0-next.571
 
 ### Patch Changes
diff --git a/packages/kit/package.json b/packages/kit/package.json
index d13bc7aaa..837a9df52 100644
--- a/packages/kit/package.json
+++ b/packages/kit/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/kit",
-	"version": "1.0.0-next.571",
+	"version": "1.0.0-next.572",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
@@ -15,7 +15,7 @@
 		"cookie": "^0.5.0",
 		"devalue": "^4.2.0",
 		"kleur": "^4.1.5",
-		"magic-string": "^0.26.7",
+		"magic-string": "^0.27.0",
 		"mime": "^3.0.0",
 		"sade": "^1.8.1",
 		"set-cookie-parser": "^2.5.1",
@@ -28,7 +28,7 @@
 		"@types/connect": "^3.4.35",
 		"@types/marked": "^4.0.7",
 		"@types/mime": "^3.0.1",
-		"@types/node": "^16.18.3",
+		"@types/node": "^16.18.6",
 		"@types/sade": "^1.7.4",
 		"@types/set-cookie-parser": "^2.4.2",
 		"marked": "^4.2.3",
diff --git a/packages/kit/src/core/sync/create_manifest_data/index.js b/packages/kit/src/core/sync/create_manifest_data/index.js
index 4fc738f92..8beb9b53c 100644
--- a/packages/kit/src/core/sync/create_manifest_data/index.js
+++ b/packages/kit/src/core/sync/create_manifest_data/index.js
@@ -486,10 +486,11 @@ function prevent_conflicts(routes) {
 			const matcher = split[i];
 			const next = split[i + 1];
 
-			permutations = [
-				...permutations.map((x) => x + next),
-				...permutations.map((x) => x + `<${matcher}>${next}`)
-			];
+			permutations = permutations.reduce((a, b) => {
+				a.push(b + next);
+				if (!(matcher === '*' && b.endsWith('//'))) a.push(b + `<${matcher}>${next}`);
+				return a;
+			}, /** @type {string[]} */ ([]));
 		}
 
 		for (const permutation of permutations) {
diff --git a/packages/kit/src/core/sync/create_manifest_data/index.spec.js b/packages/kit/src/core/sync/create_manifest_data/index.spec.js
index c386d8ac0..ff52bda7c 100644
--- a/packages/kit/src/core/sync/create_manifest_data/index.spec.js
+++ b/packages/kit/src/core/sync/create_manifest_data/index.spec.js
@@ -386,6 +386,35 @@ test('optional parameters', () => {
 	]);
 });
 
+test('nested optionals', () => {
+	const { nodes, routes } = create('samples/nested-optionals');
+	assert.equal(nodes.map(simplify_node), [
+		default_layout,
+		default_error,
+		{ component: 'samples/nested-optionals/[[a]]/[[b]]/+page.svelte' }
+	]);
+
+	assert.equal(routes.map(simplify_route), [
+		{
+			id: '/',
+			pattern: '/^/$/'
+		},
+		{
+			id: '/[[a]]/[[b]]',
+			pattern: '/^(?:/([^/]+))?(?:/([^/]+))?/?$/',
+			page: {
+				layouts: [0],
+				errors: [1],
+				leaf: nodes.findIndex((node) => node.component?.includes('/[[a]]/[[b]]'))
+			}
+		},
+		{
+			id: '/[[a]]',
+			pattern: '/^(?:/([^/]+))?/?$/'
+		}
+	]);
+});
+
 test('ignores files and directories with leading underscores', () => {
 	const { routes } = create('samples/hidden-underscore');
 
diff --git a/packages/kit/src/core/sync/create_manifest_data/test/samples/nested-optionals/[[a]]/[[b]]/+page.svelte b/packages/kit/src/core/sync/create_manifest_data/test/samples/nested-optionals/[[a]]/[[b]]/+page.svelte
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/kit/src/exports/vite/dev/index.js b/packages/kit/src/exports/vite/dev/index.js
index 778b369de..02056f176 100644
--- a/packages/kit/src/exports/vite/dev/index.js
+++ b/packages/kit/src/exports/vite/dev/index.js
@@ -235,6 +235,18 @@ export async function dev(vite, vite_config, svelte_config) {
 		sync.update(svelte_config, manifest_data, file);
 	});
 
+	const { appTemplate } = svelte_config.kit.files;
+	// vite client only executes a full reload if the triggering html file path is index.html
+	// kit defaults to src/app.html, so unless user changed that to index.html
+	// send the vite client a full-reload event without path being set
+	if (appTemplate !== 'index.html') {
+		vite.watcher.on('change', (file) => {
+			if (file === appTemplate) {
+				vite.ws.send({ type: 'full-reload' });
+			}
+		});
+	}
+
 	const assets = svelte_config.kit.paths.assets ? SVELTE_KIT_ASSETS : svelte_config.kit.paths.base;
 	const asset_server = sirv(svelte_config.kit.files.assets, {
 		dev: true,
diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js
index 3c947f258..179104d8c 100644
--- a/packages/kit/src/exports/vite/index.js
+++ b/packages/kit/src/exports/vite/index.js
@@ -274,7 +274,13 @@ function kit() {
 					external: ['@sveltejs/kit']
 				},
 				optimizeDeps: {
-					exclude: ['@sveltejs/kit']
+					exclude: [
+						'@sveltejs/kit',
+						// exclude kit features so that libraries using them work even when they are prebundled
+						// this does not affect app code, just handling of imported libraries that use $app or $env
+						'$app',
+						'$env'
+					]
 				}
 			};
 
diff --git a/packages/kit/src/runtime/client/utils.js b/packages/kit/src/runtime/client/utils.js
index 8cdd0146f..7f953d1f4 100644
--- a/packages/kit/src/runtime/client/utils.js
+++ b/packages/kit/src/runtime/client/utils.js
@@ -153,7 +153,7 @@ export function get_router_options(element) {
 	/** @type {Element} */
 	let el = element;
 
-	while (el !== document.documentElement) {
+	while (el && el !== document.documentElement) {
 		if (preload_code === null) preload_code = link_option(el, 'preload-code');
 		if (preload_data === null) preload_data = link_option(el, 'preload-data');
 		if (noscroll === null) noscroll = link_option(el, 'noscroll');
diff --git a/packages/migrate/package.json b/packages/migrate/package.json
index 63a3632e6..e8a12ee82 100644
--- a/packages/migrate/package.json
+++ b/packages/migrate/package.json
@@ -21,7 +21,7 @@
 	],
 	"dependencies": {
 		"kleur": "^4.1.5",
-		"magic-string": "^0.26.7",
+		"magic-string": "^0.27.0",
 		"prompts": "^2.4.2",
 		"tiny-glob": "^0.2.9",
 		"typescript": "^4.9.3"
diff --git a/packages/package/package.json b/packages/package/package.json
index 52501c5a8..e6973c577 100644
--- a/packages/package/package.json
+++ b/packages/package/package.json
@@ -16,7 +16,7 @@
 		"svelte2tsx": "~0.5.20"
 	},
 	"devDependencies": {
-		"@types/node": "^16.18.3",
+		"@types/node": "^16.18.6",
 		"svelte": "^3.53.1",
 		"svelte-preprocess": "^4.10.7",
 		"typescript": "^4.9.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4d8432f5e..e6b06609b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,7 +8,7 @@ importers:
       '@rollup/plugin-commonjs': ^23.0.3
       '@rollup/plugin-json': ^5.0.2
       '@rollup/plugin-node-resolve': ^15.0.1
-      '@svitejs/changesets-changelog-github-compact': ^0.1.1
+      '@svitejs/changesets-changelog-github-compact': ^1.0.0
       playwright: ^1.28.1
       prettier: ^2.8.0
       rollup: ^2.79.1
@@ -21,7 +21,7 @@ importers:
       '@rollup/plugin-commonjs': 23.0.3_rollup@2.79.1
       '@rollup/plugin-json': 5.0.2_rollup@2.79.1
       '@rollup/plugin-node-resolve': 15.0.1_rollup@2.79.1
-      '@svitejs/changesets-changelog-github-compact': 0.1.1
+      '@svitejs/changesets-changelog-github-compact': 1.0.0
       playwright: 1.28.1
       prettier: 2.8.0
       rollup: 2.79.1
@@ -33,20 +33,20 @@ importers:
   packages/adapter-auto:
     specifiers:
       '@sveltejs/kit': workspace:*
-      '@types/node': ^16.18.3
+      '@types/node': ^16.18.6
       import-meta-resolve: ^2.2.0
       typescript: ^4.9.3
     dependencies:
       import-meta-resolve: 2.2.0
     devDependencies:
       '@sveltejs/kit': link:../kit
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       typescript: 4.9.3
 
   packages/adapter-cloudflare:
     specifiers:
       '@cloudflare/workers-types': ^4.20221111.1
-      '@types/node': ^16.18.3
+      '@types/node': ^16.18.6
       '@types/ws': ^8.5.3
       esbuild: ^0.15.12
       typescript: ^4.9.3
@@ -56,7 +56,7 @@ importers:
       esbuild: 0.15.13
       worktop: 0.8.0-next.14
     devDependencies:
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       '@types/ws': 8.5.3
       typescript: 4.9.3
 
@@ -65,7 +65,7 @@ importers:
       '@cloudflare/kv-asset-handler': ^0.2.0
       '@cloudflare/workers-types': ^4.20221111.1
       '@iarna/toml': ^2.2.5
-      '@types/node': ^16.18.3
+      '@types/node': ^16.18.6
       esbuild: ^0.15.12
       typescript: ^4.9.3
     dependencies:
@@ -74,7 +74,7 @@ importers:
       esbuild: 0.15.13
     devDependencies:
       '@cloudflare/kv-asset-handler': 0.2.0
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       typescript: 4.9.3
 
   packages/adapter-netlify:
@@ -85,7 +85,7 @@ importers:
       '@rollup/plugin-json': ^5.0.2
       '@rollup/plugin-node-resolve': ^15.0.1
       '@sveltejs/kit': workspace:*
-      '@types/node': ^16.18.3
+      '@types/node': ^16.18.6
       '@types/set-cookie-parser': ^2.4.2
       esbuild: ^0.15.12
       rimraf: ^3.0.2
@@ -103,7 +103,7 @@ importers:
       '@rollup/plugin-json': 5.0.2_rollup@2.79.1
       '@rollup/plugin-node-resolve': 15.0.1_rollup@2.79.1
       '@sveltejs/kit': link:../kit
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       '@types/set-cookie-parser': 2.4.2
       rimraf: 3.0.2
       rollup: 2.79.1
@@ -116,7 +116,7 @@ importers:
       '@rollup/plugin-json': ^5.0.1
       '@rollup/plugin-node-resolve': ^15.0.1
       '@sveltejs/kit': workspace:*
-      '@types/node': ^16.18.3
+      '@types/node': ^16.18.6
       c8: ^7.12.0
       polka: ^1.0.0-next.22
       rimraf: ^3.0.2
@@ -131,7 +131,7 @@ importers:
       rollup: 2.79.1
     devDependencies:
       '@sveltejs/kit': link:../kit
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       c8: 7.12.0
       polka: 1.0.0-next.22
       rimraf: 3.0.2
@@ -142,7 +142,7 @@ importers:
   packages/adapter-static:
     specifiers:
       '@sveltejs/kit': workspace:*
-      '@types/node': ^16.18.3
+      '@types/node': ^16.18.6
       sirv: ^2.0.2
       svelte: ^3.53.1
       typescript: ^4.9.3
@@ -150,12 +150,12 @@ importers:
       vite: ^3.2.4
     devDependencies:
       '@sveltejs/kit': link:../kit
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       sirv: 2.0.2
       svelte: 3.53.1
       typescript: 4.9.3
       uvu: 0.5.6
-      vite: 3.2.4_@types+node@16.18.3
+      vite: 3.2.4_@types+node@16.18.6
 
   packages/adapter-static/test/apps/prerendered:
     specifiers:
@@ -184,7 +184,7 @@ importers:
   packages/adapter-vercel:
     specifiers:
       '@sveltejs/kit': workspace:*
-      '@types/node': ^16.18.3
+      '@types/node': ^16.18.6
       '@vercel/nft': ^0.22.1
       esbuild: ^0.15.12
       typescript: ^4.9.3
@@ -193,7 +193,7 @@ importers:
       esbuild: 0.15.13
     devDependencies:
       '@sveltejs/kit': link:../kit
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       typescript: 4.9.3
 
   packages/amp:
@@ -269,13 +269,13 @@ importers:
       '@types/cookie': ^0.5.1
       '@types/marked': ^4.0.7
       '@types/mime': ^3.0.1
-      '@types/node': ^16.18.3
+      '@types/node': ^16.18.6
       '@types/sade': ^1.7.4
       '@types/set-cookie-parser': ^2.4.2
       cookie: ^0.5.0
       devalue: ^4.2.0
       kleur: ^4.1.5
-      magic-string: ^0.26.7
+      magic-string: ^0.27.0
       marked: ^4.2.3
       mime: ^3.0.0
       rollup: ^2.79.1
@@ -295,7 +295,7 @@ importers:
       cookie: 0.5.0
       devalue: 4.2.0
       kleur: 4.1.5
-      magic-string: 0.26.7
+      magic-string: 0.27.0
       mime: 3.0.0
       sade: 1.8.1
       set-cookie-parser: 2.5.1
@@ -307,7 +307,7 @@ importers:
       '@types/connect': 3.4.35
       '@types/marked': 4.0.7
       '@types/mime': 3.0.1
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       '@types/sade': 1.7.4
       '@types/set-cookie-parser': 2.4.2
       marked: 4.2.3
@@ -316,7 +316,7 @@ importers:
       svelte-preprocess: 4.10.7_7dvewpees4iyn2tkw2qzal77a4
       typescript: 4.9.3
       uvu: 0.5.6
-      vite: 3.2.4_@types+node@16.18.3
+      vite: 3.2.4_@types+node@16.18.6
 
   packages/kit/test/apps/amp:
     specifiers:
@@ -630,7 +630,7 @@ importers:
     specifiers:
       '@types/prompts': ^2.4.1
       kleur: ^4.1.5
-      magic-string: ^0.26.7
+      magic-string: ^0.27.0
       prettier: ^2.8.0
       prompts: ^2.4.2
       tiny-glob: ^0.2.9
@@ -638,7 +638,7 @@ importers:
       uvu: ^0.5.6
     dependencies:
       kleur: 4.1.5
-      magic-string: 0.26.7
+      magic-string: 0.27.0
       prompts: 2.4.2
       tiny-glob: 0.2.9
       typescript: 4.9.3
@@ -649,7 +649,7 @@ importers:
 
   packages/package:
     specifiers:
-      '@types/node': ^16.18.3
+      '@types/node': ^16.18.6
       chokidar: ^3.5.3
       kleur: ^4.1.5
       sade: ^1.8.1
@@ -664,7 +664,7 @@ importers:
       sade: 1.8.1
       svelte2tsx: 0.5.20_7dvewpees4iyn2tkw2qzal77a4
     devDependencies:
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       svelte: 3.53.1
       svelte-preprocess: 4.10.7_7dvewpees4iyn2tkw2qzal77a4
       typescript: 4.9.3
@@ -677,9 +677,9 @@ importers:
       '@sveltejs/amp': workspace:*
       '@sveltejs/kit': workspace:*
       '@sveltejs/site-kit': ^2.1.4
-      '@types/node': ^16.18.3
+      '@types/node': ^16.18.6
       flexsearch: ^0.7.31
-      magic-string: ^0.26.7
+      magic-string: ^0.27.0
       marked: ^4.2.3
       prism-svelte: ^0.5.0
       prismjs: ^1.29.0
@@ -696,9 +696,9 @@ importers:
       '@sveltejs/amp': link:../../packages/amp
       '@sveltejs/kit': link:../../packages/kit
       '@sveltejs/site-kit': link:../site-kit
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       flexsearch: 0.7.31
-      magic-string: 0.26.7
+      magic-string: 0.27.0
       marked: 4.2.3
       prism-svelte: 0.5.0
       prismjs: 1.29.0
@@ -707,7 +707,7 @@ importers:
       tiny-glob: 0.2.9
       typescript: 4.9.3
       uvu: 0.5.6
-      vite: 3.2.4_@types+node@16.18.3
+      vite: 3.2.4_@types+node@16.18.6
       vite-imagetools: 4.0.11
 
   sites/site-kit:
@@ -1017,7 +1017,6 @@ packages:
 
   /@jridgewell/sourcemap-codec/1.4.14:
     resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
-    dev: true
 
   /@jridgewell/trace-mapping/0.3.17:
     resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==}
@@ -1101,7 +1100,7 @@ packages:
     engines: {node: '>=14'}
     hasBin: true
     dependencies:
-      '@types/node': 18.11.9
+      '@types/node': 18.11.11
       playwright-core: 1.28.1
     dev: true
 
@@ -1232,15 +1231,15 @@ packages:
       magic-string: 0.26.7
       svelte: 3.53.1
       svelte-hmr: 0.15.1_svelte@3.53.1
-      vite: 3.2.4_@types+node@16.18.3
+      vite: 3.2.4_@types+node@16.18.6
       vitefu: 0.2.2_vite@3.2.4
     transitivePeerDependencies:
       - supports-color
     dev: false
 
-  /@svitejs/changesets-changelog-github-compact/0.1.1:
-    resolution: {integrity: sha512-eBi211CfmKtkxB6tINicaDPBMbolswPbaAy7kCx+uUFL/LxztLm9cB+7jP54TgCrv+mMz8vSJWIs/baH63PjsA==}
-    engines: {node: ^12.20 || ^14.13.1 || >= 16}
+  /@svitejs/changesets-changelog-github-compact/1.0.0:
+    resolution: {integrity: sha512-h9pvZ3Bkk1K9bVr707OlWMtjreBPmXnh/GsxbiIp3ukNu9RjmkxlLmyD+h/DCkr8e0l3UpOlDDAUvbUHYNfGnA==}
+    engines: {node: ^14.13.1 || ^16.0.0 || >=18}
     dependencies:
       '@changesets/get-github-info': 0.5.1
       dotenv: 16.0.3
@@ -1251,7 +1250,7 @@ packages:
   /@types/connect/3.4.35:
     resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==}
     dependencies:
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
     dev: true
 
   /@types/cookie/0.5.1:
@@ -1295,11 +1294,11 @@ packages:
     resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
     dev: true
 
-  /@types/node/16.18.3:
-    resolution: {integrity: sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==}
+  /@types/node/16.18.6:
+    resolution: {integrity: sha512-vmYJF0REqDyyU0gviezF/KHq/fYaUbFhkcNbQCuPGFQj6VTbXuHZoxs/Y7mutWe73C8AC6l9fFu8mSYiBAqkGA==}
 
-  /@types/node/18.11.9:
-    resolution: {integrity: sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==}
+  /@types/node/18.11.11:
+    resolution: {integrity: sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g==}
     dev: true
 
   /@types/normalize-package-data/2.4.1:
@@ -1313,7 +1312,7 @@ packages:
   /@types/prompts/2.4.1:
     resolution: {integrity: sha512-1Mqzhzi9W5KlooNE4o0JwSXGUDeQXKldbGn9NO4tpxwZbHXYd+WcKpCksG2lbhH7U9I9LigfsdVsP2QAY0lNPA==}
     dependencies:
-      '@types/node': 18.11.9
+      '@types/node': 18.11.11
     dev: true
 
   /@types/pug/2.0.6:
@@ -1332,7 +1331,7 @@ packages:
   /@types/sass/1.43.1:
     resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==}
     dependencies:
-      '@types/node': 18.11.9
+      '@types/node': 18.11.11
     dev: true
 
   /@types/semver/6.2.3:
@@ -1342,13 +1341,13 @@ packages:
   /@types/set-cookie-parser/2.4.2:
     resolution: {integrity: sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w==}
     dependencies:
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
     dev: true
 
   /@types/ws/8.5.3:
     resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==}
     dependencies:
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
     dev: true
 
   /@typescript/twoslash/3.1.0:
@@ -3212,6 +3211,12 @@ packages:
     dependencies:
       sourcemap-codec: 1.4.8
 
+  /magic-string/0.27.0:
+    resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
+    engines: {node: '>=12'}
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.4.14
+
   /make-dir/3.1.0:
     resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
     engines: {node: '>=8'}
@@ -4834,7 +4839,7 @@ packages:
       fsevents: 2.3.2
     dev: true
 
-  /vite/3.2.4_@types+node@16.18.3:
+  /vite/3.2.4_@types+node@16.18.6:
     resolution: {integrity: sha512-Z2X6SRAffOUYTa+sLy3NQ7nlHFU100xwanq1WDwqaiFiCe+25zdxP1TfCS5ojPV2oDDcXudHIoPnI1Z/66B7Yw==}
     engines: {node: ^14.18.0 || >=16.0.0}
     hasBin: true
@@ -4859,7 +4864,7 @@ packages:
       terser:
         optional: true
     dependencies:
-      '@types/node': 16.18.3
+      '@types/node': 16.18.6
       esbuild: 0.15.16
       postcss: 8.4.19
       resolve: 1.22.1
@@ -4875,7 +4880,7 @@ packages:
       vite:
         optional: true
     dependencies:
-      vite: 3.2.4_@types+node@16.18.3
+      vite: 3.2.4_@types+node@16.18.6
     dev: false
 
   /vscode-oniguruma/1.6.2:
diff --git a/sites/kit.svelte.dev/package.json b/sites/kit.svelte.dev/package.json
index 54c044344..27735414e 100644
--- a/sites/kit.svelte.dev/package.json
+++ b/sites/kit.svelte.dev/package.json
@@ -15,9 +15,9 @@
 		"@sveltejs/amp": "workspace:*",
 		"@sveltejs/kit": "workspace:*",
 		"@sveltejs/site-kit": "^2.1.4",
-		"@types/node": "^16.18.3",
+		"@types/node": "^16.18.6",
 		"flexsearch": "^0.7.31",
-		"magic-string": "^0.26.7",
+		"magic-string": "^0.27.0",
 		"marked": "^4.2.3",
 		"prism-svelte": "^0.5.0",
 		"prismjs": "^1.29.0",
diff --git a/sites/kit.svelte.dev/src/routes/+layout.svelte b/sites/kit.svelte.dev/src/routes/+layout.svelte
index b5133216f..4334be7ca 100644
--- a/sites/kit.svelte.dev/src/routes/+layout.svelte
+++ b/sites/kit.svelte.dev/src/routes/+layout.svelte
@@ -60,8 +60,7 @@
 		position: relative;
 		margin: 0 auto;
 		padding-top: var(--sk-nav-height);
-		overflow: auto;
-		overflow-x: hidden;
+		overflow: hidden;
 	}
 
 	.small {


Test patch:
diff --git a/packages/kit/test/apps/basics/src/routes/interactivity/toggle-element/+page.svelte b/packages/kit/test/apps/basics/src/routes/interactivity/toggle-element/+page.svelte
index 449acb986..cc0dcf6b0 100644
--- a/packages/kit/test/apps/basics/src/routes/interactivity/toggle-element/+page.svelte
+++ b/packages/kit/test/apps/basics/src/routes/interactivity/toggle-element/+page.svelte
@@ -8,6 +8,8 @@
 
 {#if visible}
 	<button on:click={toggle}>remove</button>
+	<a on:click={toggle}>remove</a>
 {:else}
 	<button on:click={toggle}>add</button>
+	<a on:click={toggle}>add</a>
 {/if}
diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js
index ed5270f28..b81213171 100644
--- a/packages/kit/test/apps/basics/test/client.test.js
+++ b/packages/kit/test/apps/basics/test/client.test.js
@@ -1200,6 +1200,10 @@ test.describe('Interactivity', () => {
 
 		await page.click('button');
 		expect(await page.textContent('button')).toBe('add');
+		expect(await page.textContent('a')).toBe('add');
+
+		await page.click('a');
+		expect(await page.textContent('a')).toBe('remove');
 
 		expect(errored).toBe(false);
 	});