diff --git a/.changeset/wide-geese-smoke.md b/.changeset/wide-geese-smoke.md
new file mode 100644
index 000000000..5c58af8a2
--- /dev/null
+++ b/.changeset/wide-geese-smoke.md
@@ -0,0 +1,5 @@
+---
+'sv': patch
+---
+
+fix(cli): generating closing tags now works correctly
diff --git a/packages/addons/drizzle/index.ts b/packages/addons/drizzle/index.ts
index 00495fc70..b455218ed 100644
--- a/packages/addons/drizzle/index.ts
+++ b/packages/addons/drizzle/index.ts
@@ -94,7 +94,6 @@ export default defineAddon({
return cancel(`Preexisting ${fileType} file at '${filePath}'`);
}
}
- console.log(`no preexisting files`);
sv.devDependency('drizzle-orm', '^0.44.6');
sv.devDependency('drizzle-kit', '^0.31.5');
sv.devDependency('@types/node', getNodeTypesVersion());
diff --git a/packages/cli/lib/install.ts b/packages/cli/lib/install.ts
index aafd6446a..e11c30574 100644
--- a/packages/cli/lib/install.ts
+++ b/packages/cli/lib/install.ts
@@ -142,7 +142,8 @@ async function runAddon({ addon, multiple, workspace }: RunAddon) {
fileContent = content(fileContent);
if (!fileContent) return fileContent;
- writeFile(workspace, path, fileContent);
+ // TODO: fix https://github.com/rolldown/tsdown/issues/575 to remove the `replaceAll`
+ writeFile(workspace, path, fileContent.replaceAll('<\\/script>', ''));
files.add(path);
} catch (e) {
if (e instanceof Error) {
diff --git a/packages/core/tests/utils.ts b/packages/core/tests/utils.ts
index 01139fbc4..10350d1a2 100644
--- a/packages/core/tests/utils.ts
+++ b/packages/core/tests/utils.ts
@@ -269,3 +269,86 @@ describe('yaml', () => {
`);
});
});
+
+// TODO: fix https://github.com/rolldown/tsdown/issues/575 to remove the `skip`
+test.skip('tsdown escapes script tags in bundled source code', async () => {
+ const { execSync } = await import('node:child_process');
+ const fs = await import('node:fs');
+ const path = await import('node:path');
+
+ const testDir = path.join('../..', '.test-output', `tsdown-test`);
+ fs.rmSync(testDir, { recursive: true, force: true });
+ fs.mkdirSync(testDir, { recursive: true });
+
+ // Create a test file that uses dedent with script tags
+ const testFileLiteral = path.join(testDir, 'testLiteral.ts');
+ fs.writeFileSync(
+ testFileLiteral,
+ `import dedent from 'dedent';
+
+export const result = dedent\`
+
+\`;
+`
+ );
+
+ const testFileFunction = path.join(testDir, 'testFunction.ts');
+ fs.writeFileSync(
+ testFileFunction,
+ `import dedent from 'dedent';
+
+export const result = dedent(\`
+
+\`);
+`
+ );
+
+ // Create a tsdown config
+ const configFile = path.join(testDir, 'tsdown.config.ts');
+ fs.writeFileSync(
+ configFile,
+ `import { defineConfig } from 'tsdown';
+
+export default defineConfig({
+ entry: ['testLiteral.ts', 'testFunction.ts'],
+ format: ['esm'],
+ outDir: 'dist',
+});
+`
+ );
+
+ // Create package.json with tsdown
+ const pkgJson = {
+ name: 'test',
+ type: 'module',
+ devDependencies: {
+ tsdown: '^0.15.2',
+ dedent: '^1.6.0'
+ }
+ };
+ fs.writeFileSync(path.join(testDir, 'package.json'), JSON.stringify(pkgJson, null, 2));
+
+ // Install dependencies and build
+ execSync('npm install', { cwd: testDir, stdio: 'pipe' });
+ execSync('npx tsdown', { cwd: testDir, stdio: 'pipe' });
+
+ // Read the bundled output
+ const bundledFileLiteral = path.join(testDir, 'dist', 'testLiteral.js');
+ const bundledFileFunction = path.join(testDir, 'dist', 'testFunction.js');
+ const bundledCodeLiteral = fs.readFileSync(bundledFileLiteral, 'utf-8');
+ const bundledCodeFunction = fs.readFileSync(bundledFileFunction, 'utf-8');
+
+ // Check if the bundled code contains escaped script tags
+ const hasEscapedScriptTagLiteral = bundledCodeLiteral.includes('<\\/script>');
+ const hasEscapedScriptTagFunction = bundledCodeFunction.includes('<\\/script>');
+
+ // This test demonstrates the issue: tsdown escapes in the bundled source
+ // Expected: Bundled code should NOT contain escaped script tags
+ // Actual: Bundled code contains <\/script> when using dedent`...` syntax
+ expect(hasEscapedScriptTagLiteral).toBe(false);
+ expect(hasEscapedScriptTagFunction).toBe(false);
+}, 30000); // 30s timeout for npm install and build