diff --git a/cli/deno.lock b/cli/deno.lock index 9b0009da9f..c7007123ba 100644 --- a/cli/deno.lock +++ b/cli/deno.lock @@ -89,6 +89,7 @@ "npm:minimatch@*": "10.0.3", "npm:open@*": "10.2.0", "npm:svelte-preprocess@6.0.3": "6.0.3_svelte@5.45.2__acorn@8.14.1", + "npm:svelte@5.45.2": "5.45.2_acorn@8.14.1", "npm:ws@*": "8.18.3", "npm:ws@8.18.0": "8.18.0", "npm:ws@8.18.3": "8.18.3" @@ -199,7 +200,10 @@ ] }, "@std/io@0.224.9": { - "integrity": "4414664b6926f665102e73c969cfda06d2c4c59bd5d0c603fd4f1b1c840d6ee3" + "integrity": "4414664b6926f665102e73c969cfda06d2c4c59bd5d0c603fd4f1b1c840d6ee3", + "dependencies": [ + "jsr:@std/bytes@^1.0.2" + ] }, "@std/io@0.225.2": { "integrity": "3c740cd4ee4c082e6cfc86458f47e2ab7cb353dc6234d5e9b1f91a2de5f4d6c7", diff --git a/cli/src/commands/app/bundle.ts b/cli/src/commands/app/bundle.ts index daa1dd24d0..23e67872cf 100644 --- a/cli/src/commands/app/bundle.ts +++ b/cli/src/commands/app/bundle.ts @@ -56,6 +56,52 @@ export function detectFrameworks(appDir: string): { svelte: boolean; vue: boolea } } +/** + * Creates a Svelte esbuild plugin + * Uses the svelte compiler from the project's node_modules + */ +function createSveltePlugin(appDir: string): any { + return { + name: "svelte", + setup(build: any) { + build.onLoad({ filter: /\.svelte$/ }, async (args: any) => { + // Import svelte compiler from the project's node_modules + const svelte = await import("npm:svelte@5.45.2/compiler"); + + // Load the file from the file system + const source = await fs.promises.readFile(args.path, "utf8"); + const filename = path.relative(process.cwd(), args.path); + + // This converts a message in Svelte's format to esbuild's format + const convertMessage = ({ message, start, end }: any) => { + let location; + if (start && end) { + const lineText = source.split(/\r\n|\r|\n/g)[start.line - 1]; + const lineEnd = start.line === end.line ? end.column : lineText.length; + location = { + file: filename, + line: start.line, + column: start.column, + length: lineEnd - start.column, + lineText, + }; + } + return { text: message, location }; + }; + + // Convert Svelte syntax to JavaScript + try { + const { js, warnings } = svelte.compile(source, { filename }); + const contents = js.code + `//# sourceMappingURL=` + js.map.toUrl(); + return { contents, warnings: warnings.map(convertMessage) }; + } catch (e: any) { + return { errors: [convertMessage(e)] }; + } + }); + }, + }; +} + /** * Creates framework-specific esbuild plugins based on detected dependencies */ @@ -65,17 +111,7 @@ export async function createFrameworkPlugins(appDir: string): Promise { if (frameworks.svelte) { log.info(colors.blue("🔧 Svelte detected, adding svelte plugin...")); - try { - const esbuildSvelte = await import("npm:esbuild-svelte@0.9.3"); - const sveltePreprocess = await import("npm:svelte-preprocess@6.0.3"); - plugins.push( - esbuildSvelte.default({ - preprocess: sveltePreprocess.default(), - }) - ); - } catch (error: any) { - log.warn(colors.yellow(`Failed to load svelte plugin: ${error.message}`)); - } + plugins.push(createSveltePlugin(appDir)); } if (frameworks.vue) {