From 8f4c6d0dbc08e814f77b8e3b8284718c3fb34019 Mon Sep 17 00:00:00 2001
From: paoloricciuti <ricciutipaolo@gmail.com>
Date: Mon, 24 Mar 2025 14:53:16 +0100
Subject: [PATCH 1/2] feat: add templating mode selector

---
 packages/editor/src/lib/Workspace.svelte.ts   |  9 ++++++++-
 .../editor/src/lib/compile-worker/worker.ts   |  3 ++-
 .../src/lib/Output/CompilerOptions.svelte     | 19 ++++++++++++++++++-
 packages/repl/src/lib/Output/Viewer.svelte    |  1 +
 packages/repl/src/lib/Repl.svelte             |  5 ++++-
 .../repl/src/lib/workers/bundler/index.ts     | 14 ++++++++++----
 6 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/packages/editor/src/lib/Workspace.svelte.ts b/packages/editor/src/lib/Workspace.svelte.ts
index 17e1e2f65..a6e8039e5 100644
--- a/packages/editor/src/lib/Workspace.svelte.ts
+++ b/packages/editor/src/lib/Workspace.svelte.ts
@@ -94,6 +94,7 @@ export interface ExposedCompilerOptions {
 	generate: 'client' | 'server';
 	dev: boolean;
 	modernAst: boolean;
+	templatingMode: 'string' | 'functional';
 }
 
 export class Workspace {
@@ -104,7 +105,8 @@ export class Workspace {
 	#compiler_options = $state.raw<ExposedCompilerOptions>({
 		generate: 'client',
 		dev: false,
-		modernAst: true
+		modernAst: true,
+		templatingMode: 'string'
 	});
 	compiled = $state<Record<string, Compiled>>({});
 
@@ -453,6 +455,11 @@ export class Workspace {
 	update_compiler_options(options: Partial<ExposedCompilerOptions>) {
 		this.#compiler_options = { ...this.#compiler_options, ...options };
 		this.#reset_diagnostics();
+		for (let file of this.#files) {
+			if (is_file(file)) {
+				this.#onupdate(file);
+			}
+		}
 	}
 
 	update_file(file: File) {
diff --git a/packages/editor/src/lib/compile-worker/worker.ts b/packages/editor/src/lib/compile-worker/worker.ts
index c00ed75e9..6766f02c0 100644
--- a/packages/editor/src/lib/compile-worker/worker.ts
+++ b/packages/editor/src/lib/compile-worker/worker.ts
@@ -116,7 +116,8 @@ addEventListener('message', async (event) => {
 						: 'ssr'
 					: options.generate,
 				dev: options.dev,
-				filename: file.name
+				filename: file.name,
+				templatingMode: options.templatingMode
 			};
 
 			if (!is_svelte_3_or_4) {
diff --git a/packages/repl/src/lib/Output/CompilerOptions.svelte b/packages/repl/src/lib/Output/CompilerOptions.svelte
index b67f20f4d..617916f80 100644
--- a/packages/repl/src/lib/Output/CompilerOptions.svelte
+++ b/packages/repl/src/lib/Output/CompilerOptions.svelte
@@ -24,6 +24,23 @@
 		{/each},
 	</div>
 
+	<div class="option">
+		<span class="key">templatingMode:</span>
+
+		{#each ['string', 'functional'] as const as templating_mode}
+			<input
+				id={templating_mode}
+				type="radio"
+				checked={workspace.compiler_options.templatingMode === templating_mode}
+				value={templating_mode}
+				onchange={() => {
+					workspace.update_compiler_options({ templatingMode: templating_mode });
+				}}
+			/>
+			<label for={templating_mode}><span class="string">"{templating_mode}"</span></label>
+		{/each},
+	</div>
+
 	<!-- svelte-ignore a11y_label_has_associated_control (TODO this warning should probably be disabled if there's a component)-->
 	<label class="option">
 		<span class="key">dev:</span>
@@ -55,7 +72,7 @@
 
 	.key {
 		display: inline-block;
-		width: 6em;
+		width: 10em;
 	}
 
 	.string {
diff --git a/packages/repl/src/lib/Output/Viewer.svelte b/packages/repl/src/lib/Output/Viewer.svelte
index 3931e79a1..c3a5570da 100644
--- a/packages/repl/src/lib/Output/Viewer.svelte
+++ b/packages/repl/src/lib/Output/Viewer.svelte
@@ -101,6 +101,7 @@
 	$: if (ready) proxy?.iframe_command('set_theme', { theme });
 
 	async function apply_bundle($bundle: Bundle | null | undefined) {
+		console.log({ $bundle });
 		if (!$bundle) return;
 
 		try {
diff --git a/packages/repl/src/lib/Repl.svelte b/packages/repl/src/lib/Repl.svelte
index 26da2bd72..9b20a1f51 100644
--- a/packages/repl/src/lib/Repl.svelte
+++ b/packages/repl/src/lib/Repl.svelte
@@ -95,7 +95,10 @@
 
 	async function rebundle() {
 		const token = (current_token = Symbol());
-		const result = await bundler!.bundle(workspace.files as File[]);
+		const result = await bundler!.bundle(workspace.files as File[], {
+			// @ts-ignore
+			templatingMode: workspace.compiler_options.templatingMode
+		});
 		if (token === current_token) $bundle = result as Bundle;
 	}
 
diff --git a/packages/repl/src/lib/workers/bundler/index.ts b/packages/repl/src/lib/workers/bundler/index.ts
index 6b2f7b26d..59127b058 100644
--- a/packages/repl/src/lib/workers/bundler/index.ts
+++ b/packages/repl/src/lib/workers/bundler/index.ts
@@ -140,7 +140,7 @@ self.addEventListener('message', async (event: MessageEvent<BundleMessageData>)
 
 let cached: Record<
 	'client' | 'server',
-	Map<string, { code: string; result: ReturnType<typeof svelte.compile> }>
+	Map<string, { code: string; result: ReturnType<typeof svelte.compile>; templatingMode: string }>
 > = {
 	client: new Map(),
 	server: new Map()
@@ -419,14 +419,20 @@ async function get_bundle(
 			const cached_id = cache.get(id);
 			let result: CompileResult;
 
-			if (cached_id && cached_id.code === code) {
+			if (
+				cached_id &&
+				cached_id.code === code &&
+				cached_id.templatingMode === (options as any).templatingMode
+			) {
 				result = cached_id.result;
 			} else if (id.endsWith('.svelte')) {
 				const compilerOptions: any = {
 					...options,
 					filename: name + '.svelte',
 					generate: Number(svelte.VERSION.split('.')[0]) >= 5 ? 'client' : 'dom',
-					dev: true
+					dev: true,
+					// @ts-expect-error
+					templatingMode: options.templatingMode
 				};
 
 				if (can_use_experimental_async) {
@@ -482,7 +488,7 @@ async function get_bundle(
 				return null;
 			}
 
-			new_cache.set(id, { code, result });
+			new_cache.set(id, { code, result, templatingMode: (options as any).templatingMode });
 
 			// @ts-expect-error
 			(result.warnings || result.stats?.warnings)?.forEach((warning) => {

From 1a1609396e4d6bcc54d153dbd7cd81b8b1db1ec7 Mon Sep 17 00:00:00 2001
From: Rich Harris <rich.harris@vercel.com>
Date: Mon, 31 Mar 2025 17:12:51 -0400
Subject: [PATCH 2/2] Update packages/repl/src/lib/Output/Viewer.svelte

---
 packages/repl/src/lib/Output/Viewer.svelte | 1 -
 1 file changed, 1 deletion(-)

diff --git a/packages/repl/src/lib/Output/Viewer.svelte b/packages/repl/src/lib/Output/Viewer.svelte
index 464b752df..9ab087e4a 100644
--- a/packages/repl/src/lib/Output/Viewer.svelte
+++ b/packages/repl/src/lib/Output/Viewer.svelte
@@ -102,7 +102,6 @@
 	$: if (ready) proxy?.iframe_command('set_theme', { theme });
 
 	async function apply_bundle($bundle: Bundle | null | undefined) {
-		console.log({ $bundle });
 		if (!$bundle) return;
 
 		try {