= [];
 			imports.addDefault(ast, { from: './svelte.config.js', as: 'svelteConfig' });
@@ -85,18 +85,20 @@ export default defineAddon({
 			if (rules.properties[0].type !== 'Property') {
 				throw new Error('rules.properties[0].type !== "Property"');
 			}
-			rules.properties[0].key.leadingComments = [
+			additionalComments.set(rules.properties[0].key, [
 				{
 					type: 'Line',
 					value:
-						' typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.'
+						' typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.',
+					position: 'leading'
 				},
 				{
 					type: 'Line',
 					value:
-						' see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors'
+						' see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors',
+					position: 'leading'
 				}
-			];
+			]);
 
 			const globalsConfig = object.create({
 				languageOptions: {
@@ -153,7 +155,9 @@ export default defineAddon({
 
 			// type annotate config
 			if (!typescript)
-				common.addJsDocTypeComment(astNode, { type: "import('eslint').Linter.Config[]" });
+				common.addJsDocTypeComment(astNode, additionalComments, {
+					type: "import('eslint').Linter.Config[]"
+				});
 
 			if (typescript) imports.addDefault(ast, { from: 'typescript-eslint', as: 'ts' });
 			imports.addDefault(ast, { from: 'globals', as: 'globals' });
diff --git a/packages/addons/paraglide/index.ts b/packages/addons/paraglide/index.ts
index 02663e041..90298f38b 100644
--- a/packages/addons/paraglide/index.ts
+++ b/packages/addons/paraglide/index.ts
@@ -1,4 +1,3 @@
-import MagicString from 'magic-string';
 import { colors, defineAddon, defineAddonOptions, log } from '@sveltejs/cli-core';
 import { common, imports, variables, exports, kit as kitJs, vite } from '@sveltejs/cli-core/js';
 import * as html from '@sveltejs/cli-core/html';
@@ -183,35 +182,46 @@ export default defineAddon({
 
 			// add usage example
 			sv.file(`${kit.routesDirectory}/demo/paraglide/+page.svelte`, (content) => {
-				const { script, template, generateCode } = parseSvelte(content, { typescript });
-				imports.addNamed(script.ast, { from: '$lib/paraglide/messages.js', imports: ['m'] });
-				imports.addNamed(script.ast, { from: '$app/navigation', imports: ['goto'] });
-				imports.addNamed(script.ast, { from: '$app/state', imports: ['page'] });
-				imports.addNamed(script.ast, { from: '$lib/paraglide/runtime', imports: ['setLocale'] });
-
-				const scriptCode = new MagicString(script.generateCode());
+				const { ast, generateCode } = parseSvelte(content);
+
+				let scriptAst = ast.instance?.content;
+				if (!scriptAst) {
+					scriptAst = parseScript('').ast;
+					ast.instance = {
+						type: 'Script',
+						start: 0,
+						end: 0,
+						context: 'default',
+						attributes: [],
+						content: scriptAst
+					};
+				}
 
-				const templateCode = new MagicString(template.source);
+				imports.addNamed(scriptAst, { imports: { m: 'm' }, from: '$lib/paraglide/messages.js' });
+				imports.addNamed(scriptAst, {
+					imports: {
+						setLocale: 'setLocale'
+					},
+					from: '$lib/paraglide/runtime'
+				});
 
 				// add localized message
-				templateCode.append("\n\n{m.hello_world({ name: 'SvelteKit User' })} \n");
+				let templateCode = "{m.hello_world({ name: 'SvelteKit User' })} ";
 
 				// add links to other localized pages, the first one is the default
 				// language, thus it does not require any localized route
 				const { validLanguageTags } = parseLanguageTagInput(options.languageTags);
 				const links = validLanguageTags
-					.map(
-						(x) =>
-							`${templateCode.getIndentString()} setLocale('${x}')}>${x} `
-					)
-					.join('\n');
-				templateCode.append(`\n${links}\n
`);
-
-				templateCode.append(
-					'\nIf you use VSCode, install the Sherlock i18n extension  for a better i18n experience.\n
'
-				);
+					.map((x) => ` setLocale('${x}')}>${x} `)
+					.join('');
+				templateCode += `${links}
`;
 
-				return generateCode({ script: scriptCode.toString(), template: templateCode.toString() });
+				templateCode +=
+					'If you use VSCode, install the Sherlock i18n extension  for a better i18n experience.
';
+
+				ast.fragment.nodes.push(...html.toSvelteFragment(templateCode));
+
+				return generateCode();
 			});
 		}
 
diff --git a/packages/addons/sveltekit-adapter/index.ts b/packages/addons/sveltekit-adapter/index.ts
index 7c12859b7..1650966f4 100644
--- a/packages/addons/sveltekit-adapter/index.ts
+++ b/packages/addons/sveltekit-adapter/index.ts
@@ -49,7 +49,7 @@ export default defineAddon({
 		sv.devDependency(adapter.package, adapter.version);
 
 		sv.file('svelte.config.js', (content) => {
-			const { ast, generateCode } = parseScript(content);
+			const { ast, comments, generateCode } = parseScript(content);
 
 			// finds any existing adapter's import declaration
 			const importDecls = ast.body.filter((n) => n.type === 'ImportDeclaration');
@@ -86,8 +86,21 @@ export default defineAddon({
 			if (adapter.package !== '@sveltejs/adapter-auto') {
 				const fallback = object.create({});
 				const cfgKitValue = object.property(config, { name: 'kit', fallback });
-				const cfgAdapter = object.propertyNode(cfgKitValue, { name: 'adapter', fallback });
-				cfgAdapter.leadingComments = [];
+
+				// removes any existing adapter auto comments
+				const adapterAutoComments = comments.filter(
+					(c) =>
+						c.loc &&
+						cfgKitValue.loc &&
+						c.loc.start.line >= cfgKitValue.loc.start.line &&
+						c.loc.end.line <= cfgKitValue.loc.end.line
+				);
+				// modify the array in place
+				comments.splice(
+					0,
+					comments.length,
+					...comments.filter((c) => !adapterAutoComments.includes(c))
+				);
 			}
 
 			return generateCode();
diff --git a/packages/core/package.json b/packages/core/package.json
index 1138f0314..ddaeab0fa 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -34,12 +34,13 @@
 		"dom-serializer": "^2.0.0",
 		"domhandler": "^5.0.3",
 		"domutils": "^3.2.2",
-		"esrap": "^1.4.9",
+		"esrap": "https://pkg.pr.new/sveltejs/esrap@af12b38",
 		"htmlparser2": "^9.1.0",
 		"magic-string": "^0.30.17",
 		"picocolors": "^1.1.1",
 		"postcss": "^8.5.6",
 		"silver-fleece": "^1.2.1",
+		"svelte": "https://pkg.pr.new/sveltejs/svelte@1377c40",
 		"yaml": "^2.8.1",
 		"zimmerframe": "^1.1.2"
 	},
diff --git a/packages/core/tests/js/common/jsdoc-comment/run.ts b/packages/core/tests/js/common/jsdoc-comment/run.ts
index c0b6c06f1..15d0369b9 100644
--- a/packages/core/tests/js/common/jsdoc-comment/run.ts
+++ b/packages/core/tests/js/common/jsdoc-comment/run.ts
@@ -1,9 +1,9 @@
-import { common, type AstTypes } from '@sveltejs/cli-core/js';
+import { common, type AdditionalCommentMap, type AstTypes } from '@sveltejs/cli-core/js';
 
-export function run(ast: AstTypes.Program): void {
+export function run(ast: AstTypes.Program, additionalComments: AdditionalCommentMap): void {
 	const functionDeclaration = ast.body[0] as AstTypes.FunctionDeclaration;
 
-	common.addJsDocComment(functionDeclaration, {
+	common.addJsDocComment(functionDeclaration, additionalComments, {
 		params: { 'import("$lib/paraglide/runtime").AvailableLanguageTag': 'newLanguage' }
 	});
 }
diff --git a/packages/core/tests/js/common/jsdoc-type-comment/output.ts b/packages/core/tests/js/common/jsdoc-type-comment/output.ts
index 1aa734391..e8a715681 100644
--- a/packages/core/tests/js/common/jsdoc-type-comment/output.ts
+++ b/packages/core/tests/js/common/jsdoc-type-comment/output.ts
@@ -1,2 +1 @@
-/** @type {number} */
-const foo = 42;
+/** @type {number} */ const foo = 42;
diff --git a/packages/core/tests/js/common/jsdoc-type-comment/run.ts b/packages/core/tests/js/common/jsdoc-type-comment/run.ts
index 9b5e5a065..5074afd58 100644
--- a/packages/core/tests/js/common/jsdoc-type-comment/run.ts
+++ b/packages/core/tests/js/common/jsdoc-type-comment/run.ts
@@ -1,13 +1,13 @@
-import { common, variables, type AstTypes } from '@sveltejs/cli-core/js';
+import { common, variables, type AdditionalCommentMap, type AstTypes } from '@sveltejs/cli-core/js';
 
-export function run(ast: AstTypes.Program): void {
+export function run(ast: AstTypes.Program, additionalComments: AdditionalCommentMap): void {
 	const declaration = variables.declaration(ast, {
 		kind: 'const',
 		name: 'foo',
 		value: { type: 'Literal', value: 42 }
 	});
 
-	common.addJsDocTypeComment(declaration, {
+	common.addJsDocTypeComment(declaration, additionalComments, {
 		type: 'number'
 	});
 
diff --git a/packages/core/tests/js/index.ts b/packages/core/tests/js/index.ts
index c7f2021e6..bc32a5c83 100644
--- a/packages/core/tests/js/index.ts
+++ b/packages/core/tests/js/index.ts
@@ -16,13 +16,13 @@ for (const categoryDirectory of categoryDirectories) {
 
 				const inputFilePath = join(testDirectoryPath, 'input.ts');
 				const input = fs.existsSync(inputFilePath) ? fs.readFileSync(inputFilePath, 'utf8') : '';
-				const ast = parseScript(input);
+				const { ast, comments, additionalComments } = parseScript(input);
 
 				// dynamic imports always need to provide the path inline for static analysis
 				const module = await import(`./${categoryDirectory}/${testName}/run.ts`);
-				module.run(ast);
+				module.run(ast, additionalComments);
 
-				let output = serializeScript(ast, input);
+				let output = serializeScript(ast, comments, input, additionalComments);
 				if (!output.endsWith('\n')) output += '\n';
 				await expect(output).toMatchFileSnapshot(`${testDirectoryPath}/output.ts`);
 			});
diff --git a/packages/core/tests/js/object/create/output.ts b/packages/core/tests/js/object/create/output.ts
index 28ad96e4f..df190f0f4 100644
--- a/packages/core/tests/js/object/create/output.ts
+++ b/packages/core/tests/js/object/create/output.ts
@@ -1,15 +1,9 @@
 const empty = {};
 const created = { foo: 1, bar: 'string' };
 
-// prettier-ignore
 const created2 = {
 	foo: 1,
 	bar: 'string',
 	object: { foo: 'hello', nested: { bar: 'world' } },
-	array: [
-		123,
-		'hello',
-		{ foo: 'bar', bool: true },
-		[456, '789']
-	]
+	array: [123, 'hello', { foo: 'bar', bool: true }, [456, '789']]
 };
diff --git a/packages/core/tests/js/object/create/run.ts b/packages/core/tests/js/object/create/run.ts
index 8bdd272f5..5b19937e0 100644
--- a/packages/core/tests/js/object/create/run.ts
+++ b/packages/core/tests/js/object/create/run.ts
@@ -37,6 +37,5 @@ export function run(ast: AstTypes.Program): void {
 		name: 'created2',
 		value: createdObject2
 	});
-	createdVariable2.leadingComments = [{ type: 'Line', value: ' prettier-ignore' }];
 	ast.body.push(createdVariable2);
 }
diff --git a/packages/core/tests/js/object/ensure-nested-property/output.ts b/packages/core/tests/js/object/ensure-nested-property/output.ts
index 08bd5fbf9..b3824d36a 100644
--- a/packages/core/tests/js/object/ensure-nested-property/output.ts
+++ b/packages/core/tests/js/object/ensure-nested-property/output.ts
@@ -1 +1,8 @@
-const test = { a: { /** a comment */ keep: 'you', b: { c: '007' } } };
+const test = {
+	a: {
+		/** a comment */
+		keep: 'you',
+
+		b: { c: '007' }
+	}
+};
diff --git a/packages/core/tests/js/object/override-property/output.ts b/packages/core/tests/js/object/override-property/output.ts
index fbdef76fe..987c50888 100644
--- a/packages/core/tests/js/object/override-property/output.ts
+++ b/packages/core/tests/js/object/override-property/output.ts
@@ -1 +1,7 @@
-const test = { /** a comment */ foo: 2, bar: 'string2', lorem: false };
+const test = {
+	/** a comment */
+	foo: 2,
+
+	bar: 'string2',
+	lorem: false
+};
diff --git a/packages/core/tests/js/object/property-node/output.ts b/packages/core/tests/js/object/property-node/output.ts
index 98da8dea4..3719acb91 100644
--- a/packages/core/tests/js/object/property-node/output.ts
+++ b/packages/core/tests/js/object/property-node/output.ts
@@ -1 +1,6 @@
-const test = { /*a comment updated*/ foo: 1, /*aka: bond, james bond*/ james: '007' };
+const test = {
+	/** a comment */
+	foo: 1,
+
+	james: '007'
+};
diff --git a/packages/core/tests/js/vite/add-plugin-mode/output.ts b/packages/core/tests/js/vite/add-plugin-mode/output.ts
index f112d5fcc..df6d4692a 100644
--- a/packages/core/tests/js/vite/add-plugin-mode/output.ts
+++ b/packages/core/tests/js/vite/add-plugin-mode/output.ts
@@ -7,8 +7,10 @@ import { defineConfig } from 'vite';
 export default defineConfig({
 	plugins: [
 		firstPlugin(),
+
 		// a default plugin
 		sveltekit(),
+
 		middlePlugin(),
 		lastPlugin()
 	]
diff --git a/packages/core/tests/js/vite/with-satisfies/output.ts b/packages/core/tests/js/vite/with-satisfies/output.ts
index 4d6ed36e0..9c43348e2 100644
--- a/packages/core/tests/js/vite/with-satisfies/output.ts
+++ b/packages/core/tests/js/vite/with-satisfies/output.ts
@@ -18,23 +18,24 @@ const config = defineConfig({
 	plugins: [
 		// all plugins
 		examples,
+
 		tailwindcss(),
 		sveltekit(),
 		kitRoutes(),
 		myPlugin()
 	],
+
 	resolve: { alias: { $lib, $routes, $scripts, $actions } },
-	build: {
-		sourcemap: true,
-		target: 'esnext',
-		cssMinify: 'lightningcss'
-	},
+	build: { sourcemap: true, target: 'esnext', cssMinify: 'lightningcss' },
+
 	css: {
 		transformer: 'lightningcss',
+
 		lightningcss: {
 			targets: browserslistToTargets(browserslist('defaults, not ie 11'))
 		}
 	},
+
 	experimental: { enableNativePlugin: true }
 }) satisfies UserConfig;
 
diff --git a/packages/core/tests/utils.ts b/packages/core/tests/utils.ts
index 01139fbc4..88e95f125 100644
--- a/packages/core/tests/utils.ts
+++ b/packages/core/tests/utils.ts
@@ -4,7 +4,6 @@ import {
 	parseScript,
 	serializeScript,
 	guessIndentString,
-	guessQuoteStyle,
 	type AstTypes,
 	serializeYaml,
 	parseYaml
@@ -50,57 +49,6 @@ test('guessIndentString - eight spaces', () => {
 	expect(guessIndentString(code)).toBe('        ');
 });
 
-test('guessQuoteStyle - single simple', () => {
-	const code = dedent`
-    console.log('asd');
-    `;
-	const ast = parseScript(code);
-
-	expect(guessQuoteStyle(ast)).toBe('single');
-});
-
-test('guessQuoteStyle - single complex', () => {
-	const code = dedent`
-    import foo from 'bar';
-
-    console.log("bar");
-    const foobar = 'foo';
-    `;
-	const ast = parseScript(code);
-
-	expect(guessQuoteStyle(ast)).toBe('single');
-});
-
-test('guessQuoteStyle - double simple', () => {
-	const code = dedent`
-    console.log("asd");
-    `;
-	const ast = parseScript(code);
-
-	expect(guessQuoteStyle(ast)).toBe('double');
-});
-
-test('guessQuoteStyle - double complex', () => {
-	const code = dedent`
-    import foo from 'bar';
-
-    console.log("bar");
-    const foobar = "foo";
-    `;
-	const ast = parseScript(code);
-
-	expect(guessQuoteStyle(ast)).toBe('double');
-});
-
-test('guessQuoteStyle - no quotes', () => {
-	const code = dedent`
-    const foo = true;
-    `;
-	const ast = parseScript(code);
-
-	expect(guessQuoteStyle(ast)).toBe(undefined);
-});
-
 const newVariableDeclaration: AstTypes.VariableDeclaration = {
 	type: 'VariableDeclaration',
 	kind: 'const',
@@ -128,20 +76,20 @@ test('integration - simple', () => {
         const foobar = "foo";
     }
     `;
-	const ast = parseScript(code);
+	const { ast, comments } = parseScript(code);
 	const method = ast.body[1] as AstTypes.FunctionDeclaration;
 
 	method.body.body.push(newVariableDeclaration);
 
 	// new variable is added with correct indentation and matching quotes
-	expect(serializeScript(ast, code)).toMatchInlineSnapshot(`
+	expect(serializeScript(ast, comments, code)).toMatchInlineSnapshot(`
 		"import foo from 'bar';
 
 		function bar() {
 		    console.log("bar");
 
 		    const foobar = "foo";
-		    const foobar2 = "test";
+		    const foobar2 = 'test';
 		}"
 	`);
 });
@@ -155,13 +103,13 @@ test('integration - simple 2', () => {
       const foobar = 'foo';
     }
     `;
-	const ast = parseScript(code);
+	const { ast, comments } = parseScript(code);
 	const method = ast.body[1] as AstTypes.FunctionDeclaration;
 
 	method.body.body.push(newVariableDeclaration);
 
 	// new variable is added with correct indentation and matching quotes
-	expect(serializeScript(ast, code)).toMatchInlineSnapshot(`
+	expect(serializeScript(ast, comments, code)).toMatchInlineSnapshot(`
 		"import foo from 'bar';
 
 		function bar() {
@@ -178,9 +126,9 @@ test('integration - preserves comments', () => {
 	  /** @type {string} */
     let foo = 'bar';
     `;
-	const ast = parseScript(code);
+	const { ast, comments } = parseScript(code);
 
-	expect(serializeScript(ast, code)).toMatchInlineSnapshot(`
+	expect(serializeScript(ast, comments, code)).toMatchInlineSnapshot(`
 		"/** @type {string} */
 		let foo = 'bar';"
 	`);
diff --git a/packages/core/tooling/html/index.ts b/packages/core/tooling/html/index.ts
index 60b2ae078..e245c3bd9 100644
--- a/packages/core/tooling/html/index.ts
+++ b/packages/core/tooling/html/index.ts
@@ -7,9 +7,11 @@ import {
 	parseHtml
 } from '../index.ts';
 import { appendFromString } from '../js/common.ts';
+import { parseSvelte } from '../parsers.ts';
+import type { AST as SvelteAst } from 'svelte/compiler';
 
 export { HtmlElement, HtmlElementType };
-export type { HtmlDocument };
+export type { HtmlDocument, SvelteAst };
 
 export function createDiv(attributes: Record = {}): HtmlElement {
 	return createElement('div', attributes);
@@ -58,3 +60,9 @@ export function addSlot(
 	});
 	addFromRawHtml(options.htmlAst.childNodes, '{@render children()}');
 }
+
+export function toSvelteFragment(content: string): SvelteAst.Fragment['nodes'] {
+	// TODO write test
+	const { ast } = parseSvelte(content);
+	return ast.fragment.nodes;
+}
diff --git a/packages/core/tooling/index.ts b/packages/core/tooling/index.ts
index 68f3dc0b4..bcc9e04a1 100644
--- a/packages/core/tooling/index.ts
+++ b/packages/core/tooling/index.ts
@@ -14,10 +14,14 @@ import {
 } from 'postcss';
 import * as fleece from 'silver-fleece';
 import { print as esrapPrint } from 'esrap';
+import ts, { type AdditionalComment } from 'esrap/languages/ts';
 import * as acorn from 'acorn';
 import { tsPlugin } from '@sveltejs/acorn-typescript';
+import { parse as svelteParse, type AST as SvelteAst, print as sveltePrint } from 'svelte/compiler';
 import * as yaml from 'yaml';
 
+type AdditionalCommentMap = WeakMap;
+
 export {
 	// html
 	Document as HtmlDocument,
@@ -38,9 +42,11 @@ export {
 export type {
 	// html
 	ChildNode as HtmlChildNode,
+	SvelteAst,
 
 	// js
 	TsEstree as AstTypes,
+	AdditionalCommentMap,
 
 	//css
 	CssChildNode
@@ -48,19 +54,22 @@ export type {
 
 /**
  * Parses as string to an AST. Code below is taken from `esrap` to ensure compatibilty.
- * https://github.com/sveltejs/esrap/blob/9daf5dd43b31f17f596aa7da91678f2650666dd0/test/common.js#L12
+ * https://github.com/sveltejs/esrap/blob/920491535d31484ac5fae2327c7826839d851aed/test/common.js#L14
  */
-export function parseScript(content: string): TsEstree.Program {
+export function parseScript(content: string): {
+	ast: TsEstree.Program;
+	comments: TsEstree.Comment[];
+	additionalComments: AdditionalCommentMap;
+} {
 	const comments: TsEstree.Comment[] = [];
 
 	const acornTs = acorn.Parser.extend(tsPlugin());
 
-	// Acorn doesn't add comments to the AST by itself. This factory returns the capabilities to add them after the fact.
 	const ast = acornTs.parse(content, {
 		ecmaVersion: 'latest',
 		sourceType: 'module',
 		locations: true,
-		onComment: (block, value, start, end) => {
+		onComment: (block, value, start, end, startLoc, endLoc) => {
 			if (block && /\n/.test(value)) {
 				let a = start;
 				while (a > 0 && content[a - 1] !== '\n') a -= 1;
@@ -72,38 +81,33 @@ export function parseScript(content: string): TsEstree.Program {
 				value = value.replace(new RegExp(`^${indentation}`, 'gm'), '');
 			}
 
-			comments.push({ type: block ? 'Block' : 'Line', value, start, end });
+			comments.push({
+				type: block ? 'Block' : 'Line',
+				value,
+				start,
+				end,
+				loc: { start: startLoc as TsEstree.Position, end: endLoc as TsEstree.Position }
+			});
 		}
 	}) as TsEstree.Program;
 
-	Walker.walk(ast as TsEstree.Node, null, {
-		_(commentNode, { next }) {
-			let comment: TsEstree.Comment;
-
-			while (comments[0] && commentNode.start && comments[0].start! < commentNode.start) {
-				comment = comments.shift()!;
-				(commentNode.leadingComments ??= []).push(comment);
-			}
-
-			next();
-
-			if (comments[0]) {
-				const slice = content.slice(commentNode.end, comments[0].start);
-
-				if (/^[,) \t]*$/.test(slice)) {
-					commentNode.trailingComments = [comments.shift()!];
-				}
-			}
-		}
-	});
-
-	return ast;
+	return {
+		ast,
+		comments,
+		additionalComments: new WeakMap()
+	};
 }
 
-export function serializeScript(ast: TsEstree.Node, previousContent?: string): string {
-	const { code } = esrapPrint(ast, {
-		indent: guessIndentString(previousContent),
-		quotes: guessQuoteStyle(ast)
+export function serializeScript(
+	ast: TsEstree.Node,
+	comments: TsEstree.Comment[],
+	previousContent?: string,
+	additionalComments?: AdditionalCommentMap
+): string {
+	// @ts-expect-error we are still using `estree` while `esrap` is using `@typescript-eslint/types`
+	// which is causing these errors. But they are simmilar enough to work together.
+	const { code } = esrapPrint(ast, ts({ comments, additionalComments }), {
+		indent: guessIndentString(previousContent)
 	});
 	return code;
 }
@@ -207,39 +211,6 @@ export function guessIndentString(str: string | undefined): string {
 	}
 }
 
-export function guessQuoteStyle(ast: TsEstree.Node): 'single' | 'double' | undefined {
-	let singleCount = 0;
-	let doubleCount = 0;
-
-	Walker.walk(ast, null, {
-		Literal(node) {
-			if (node.raw && node.raw.length >= 2) {
-				// we have at least two characters in the raw string that could represent both quotes
-				const quotes = [node.raw[0], node.raw[node.raw.length - 1]];
-				for (const quote of quotes) {
-					switch (quote) {
-						case "'":
-							singleCount++;
-							break;
-						case '"':
-							doubleCount++;
-							break;
-						default:
-							break;
-					}
-				}
-			}
-		}
-	});
-
-	if (singleCount === 0 && doubleCount === 0) {
-		// new file or file without any quotes
-		return undefined;
-	}
-
-	return singleCount > doubleCount ? 'single' : 'double';
-}
-
 export function parseYaml(content: string): ReturnType {
 	return yaml.parseDocument(content);
 }
@@ -247,3 +218,11 @@ export function parseYaml(content: string): ReturnType): string {
 	return yaml.stringify(data, { singleQuote: true });
 }
+
+export function parseSvelte(content: string): SvelteAst.Root {
+	return svelteParse(content, { modern: true });
+}
+
+export function serializeSvelte(ast: SvelteAst.Root): string {
+	return sveltePrint(ast).code;
+}
diff --git a/packages/core/tooling/js/common.ts b/packages/core/tooling/js/common.ts
index 8812660e2..1f51dcf6a 100644
--- a/packages/core/tooling/js/common.ts
+++ b/packages/core/tooling/js/common.ts
@@ -1,18 +1,30 @@
-import { type AstTypes, Walker, parseScript, serializeScript, stripAst } from '../index.ts';
+import {
+	type AdditionalCommentMap,
+	type AstTypes,
+	Walker,
+	parseScript,
+	serializeScript,
+	stripAst
+} from '../index.ts';
 import decircular from 'decircular';
 import dedent from 'dedent';
 
-export function addJsDocTypeComment(node: AstTypes.Node, options: { type: string }): void {
+export function addJsDocTypeComment(
+	node: AstTypes.Node,
+	additionalComments: AdditionalCommentMap,
+	options: { type: string }
+): void {
 	const comment: AstTypes.Comment = {
 		type: 'Block',
 		value: `* @type {${options.type}} `
 	};
 
-	addComment(node, comment);
+	addComment(node, additionalComments, comment);
 }
 
 export function addJsDocComment(
 	node: AstTypes.Node,
+	additionalComments: AdditionalCommentMap,
 	options: { params: Record }
 ): void {
 	const commentLines: string[] = [];
@@ -25,16 +37,23 @@ export function addJsDocComment(
 		value: `*\n * ${commentLines.join('\n * ')}\n `
 	};
 
-	addComment(node, comment);
+	addComment(node, additionalComments, comment);
 }
 
-function addComment(node: AstTypes.Node, comment: AstTypes.Comment) {
-	node.leadingComments ??= [];
-
-	const found = node.leadingComments.find(
-		(item) => item.type === 'Block' && item.value === comment.value
-	);
-	if (!found) node.leadingComments.push(comment);
+function addComment(
+	node: AstTypes.Node,
+	additionalComments: AdditionalCommentMap,
+	comment: AstTypes.Comment
+) {
+	const found = additionalComments
+		.get(node)
+		?.find((item) => item.type === 'Block' && item.value === comment.value);
+
+	if (!found) {
+		const comments = additionalComments.get(node) ?? [];
+		comments.push({ ...comment, position: 'leading' });
+		additionalComments.set(node, comments);
+	}
 }
 
 export function typeAnnotate(
@@ -93,7 +112,7 @@ export function areNodesEqual(node: AstTypes.Node, otherNode: AstTypes.Node): bo
 
 	const nodeClone = stripAst(decircular(node), ['loc', 'raw']);
 	const otherNodeClone = stripAst(decircular(otherNode), ['loc', 'raw']);
-	return serializeScript(nodeClone) === serializeScript(otherNodeClone);
+	return serializeScript(nodeClone, []) === serializeScript(otherNodeClone, []);
 }
 
 export function createBlockStatement(): AstTypes.BlockStatement {
@@ -118,18 +137,18 @@ export function appendFromString(
 	node: AstTypes.BlockStatement | AstTypes.Program,
 	options: { code: string }
 ): void {
-	const program = parseScript(dedent(options.code));
+	const { ast } = parseScript(dedent(options.code));
 
-	for (const childNode of program.body) {
+	for (const childNode of ast.body) {
 		// @ts-expect-error
 		node.body.push(childNode);
 	}
 }
 
 export function parseExpression(code: string): AstTypes.Expression {
-	const program = parseScript(dedent(code));
-	stripAst(program, ['raw']);
-	const statement = program.body[0]!;
+	const { ast } = parseScript(dedent(code));
+	stripAst(ast, ['raw']);
+	const statement = ast.body[0]!;
 	if (statement.type !== 'ExpressionStatement') {
 		throw new Error('Code provided was not an expression');
 	}
@@ -142,8 +161,8 @@ export function parseStatement(code: string): AstTypes.Statement {
 }
 
 export function parseFromString(code: string): T {
-	const program = parseScript(dedent(code));
-	const statement = program.body[0]!;
+	const { ast } = parseScript(dedent(code));
+	const statement = ast.body[0]!;
 
 	return statement as T;
 }
diff --git a/packages/core/tooling/js/index.ts b/packages/core/tooling/js/index.ts
index 0b4c6e632..206d49d5a 100644
--- a/packages/core/tooling/js/index.ts
+++ b/packages/core/tooling/js/index.ts
@@ -7,4 +7,4 @@ export * as variables from './variables.ts';
 export * as exports from './exports.ts';
 export * as kit from './kit.ts';
 export * as vite from './vite.ts';
-export type { AstTypes } from '../index.ts';
+export type { AstTypes, AdditionalCommentMap } from '../index.ts';
diff --git a/packages/core/tooling/parsers.ts b/packages/core/tooling/parsers.ts
index 21b6b0993..b030a16b5 100644
--- a/packages/core/tooling/parsers.ts
+++ b/packages/core/tooling/parsers.ts
@@ -1,16 +1,19 @@
 import * as utils from './index.ts';
-import MagicString from 'magic-string';
 
 type ParseBase = {
 	source: string;
 	generateCode(): string;
 };
 
-export function parseScript(source: string): { ast: utils.AstTypes.Program } & ParseBase {
-	const ast = utils.parseScript(source);
-	const generateCode = () => utils.serializeScript(ast, source);
+export function parseScript(source: string): {
+	ast: utils.AstTypes.Program;
+	comments: utils.AstTypes.Comment[];
+	additionalComments: utils.AdditionalCommentMap;
+} & ParseBase {
+	const { ast, comments, additionalComments } = utils.parseScript(source);
+	const generateCode = () => utils.serializeScript(ast, comments, source, additionalComments);
 
-	return { ast, source, generateCode };
+	return { ast, comments, additionalComments, source, generateCode };
 }
 
 export function parseCss(source: string): { ast: utils.CssAst } & ParseBase {
@@ -45,136 +48,13 @@ export function parseYaml(
 	return { data, source, generateCode };
 }
 
-type SvelteGenerator = (code: {
-	script?: string;
-	module?: string;
-	css?: string;
-	template?: string;
-}) => string;
-export function parseSvelte(
-	source: string,
-	options?: { typescript?: boolean }
-): {
-	script: ReturnType;
-	module: ReturnType;
-	css: ReturnType;
-	template: ReturnType;
-	generateCode: SvelteGenerator;
-} {
-	// `xTag` captures the whole tag block (ex: )
-	// `xSource` is the contents within the tags
-	const scripts = extractScripts(source);
-	// instance block
-	const { tag: scriptTag = '', src: scriptSource = '' } =
-		scripts.find(({ attrs }) => !attrs.includes('module')) ?? {};
-	// module block
-	const { tag: moduleScriptTag = '', src: moduleSource = '' } =
-		scripts.find(({ attrs }) => attrs.includes('module')) ?? {};
-	// style block
-	const { styleTag, cssSource } = extractStyle(source);
-	// rest of the template
-	// TODO: needs more testing
-	const templateSource = source
-		.replace(moduleScriptTag, '')
-		.replace(scriptTag, '')
-		.replace(styleTag, '')
-		.trim();
-
-	const script = parseScript(scriptSource);
-	const module = parseScript(moduleSource);
-	const css = parseCss(cssSource);
-	const template = parseHtml(templateSource);
-
-	const generateCode: SvelteGenerator = (code) => {
-		const ms = new MagicString(source);
-		// TODO: this is imperfect and needs adjustments
-		if (code.script !== undefined) {
-			if (scriptSource.length === 0) {
-				const ts = options?.typescript ? ' lang="ts"' : '';
-				const indented = code.script.split('\n').join('\n\t');
-				const script = `\n\n`;
-				ms.prepend(script);
-			} else {
-				const { start, end } = locations(source, scriptSource);
-				const formatted = indent(code.script, ms.getIndentString());
-				ms.update(start, end, formatted);
-			}
-		}
-		if (code.module !== undefined) {
-			if (moduleSource.length === 0) {
-				const ts = options?.typescript ? ' lang="ts"' : '';
-				const indented = code.module.split('\n').join('\n\t');
-				// TODO: make a svelte 5 variant
-				const module = `\n\n`;
-				ms.prepend(module);
-			} else {
-				const { start, end } = locations(source, moduleSource);
-				const formatted = indent(code.module, ms.getIndentString());
-				ms.update(start, end, formatted);
-			}
-		}
-		if (code.css !== undefined) {
-			if (cssSource.length === 0) {
-				const indented = code.css.split('\n').join('\n\t');
-				const style = `\n\n`;
-				ms.append(style);
-			} else {
-				const { start, end } = locations(source, cssSource);
-				const formatted = indent(code.css, ms.getIndentString());
-				ms.update(start, end, formatted);
-			}
-		}
-		if (code.template !== undefined) {
-			if (templateSource.length === 0) {
-				ms.appendLeft(0, code.template);
-			} else {
-				const { start, end } = locations(source, templateSource);
-				ms.update(start, end, code.template);
-			}
-		}
-		return ms.toString();
-	};
+export function parseSvelte(source: string): { ast: utils.SvelteAst.Root } & ParseBase {
+	const ast = utils.parseSvelte(source);
+	const generateCode = () => utils.serializeSvelte(ast);
 
 	return {
-		script: { ...script, source: scriptSource },
-		module: { ...module, source: moduleSource },
-		css: { ...css, source: cssSource },
-		template: { ...template, source: templateSource },
+		ast,
+		source,
 		generateCode
 	};
 }
-
-function locations(source: string, search: string): { start: number; end: number } {
-	const start = source.indexOf(search);
-	const end = start + search.length;
-	return { start, end };
-}
-
-function indent(content: string, indent: string): string {
-	const indented = indent + content.split('\n').join(`\n${indent}`);
-	return `\n${indented}\n`;
-}
-
-// sourced from Svelte: https://github.com/sveltejs/svelte/blob/0d3d5a2a85c0f9eccb2c8dbbecc0532ec918b157/packages/svelte/src/compiler/preprocess/index.js#L253-L256
-const regexScriptTags =
-	/|