diff --git a/packages/create/src/create-solid-v2.ts b/packages/create/src/create-solid-v2.ts index c4366d4..cfac554 100644 --- a/packages/create/src/create-solid-v2.ts +++ b/packages/create/src/create-solid-v2.ts @@ -25,6 +25,22 @@ export const createSolidV2TS = async ({ template, destination, path = "solid-v2" if (ssr) await applySsrFlip(destination); }; +/** + * Retarget `.ts`/`.tsx` filename mentions in converted text (vite config, + * README) to the transpiled `.js`/`.jsx` output. `.d.ts` files are deleted + * (not transpiled) by the conversion, so their mentions are left alone. + */ +export const retargetTSFilenames = (text: string) => + text + .replace(/\.tsx\b/g, ".jsx") + .replace(/(? { + const deduped = [...new Set(entries.split(",").map((entry) => entry.trim()).filter(Boolean))]; + return `extensions: [${deduped.join(", ")}]`; + }); + export const createSolidV2JS = async (args: CreateSolidV2Args, ssr?: boolean) => { // Create typescript project in `/.project` // then transpile this to javascript and clean up. @@ -34,15 +50,13 @@ export const createSolidV2JS = async (args: CreateSolidV2Args, ssr?: boolean) => await createSolidV2TS({ ...args, destination: tempDir }, ssr); await handleTSConversion(tempDir, args.destination, JS_CONFIG_SOLID_V2); // Solid 2.0 templates have no `index.html` (turnkey entries), but their vite - // config references `.ts`/`.tsx` files by path (setup files, middleware, test - // globs) — retarget those to the transpiled `.js`/`.jsx` output - const viteConfigPath = join(args.destination, "vite.config.js"); - if (existsSync(viteConfigPath)) { - const viteConfig = (await readFile(viteConfigPath)) - .toString() - .replace(/\.tsx(?=['"])/g, ".jsx") - .replace(/\.ts(?=['"])/g, ".js"); - await writeFile(viteConfigPath, viteConfig); + // config and README reference `.ts`/`.tsx` files (setup files, comments, + // route examples) — retarget those to the transpiled `.js`/`.jsx` output + for (const file of ["vite.config.js", "README.md"]) { + const filePath = join(args.destination, file); + if (existsSync(filePath)) { + await writeFile(filePath, retargetTSFilenames((await readFile(filePath)).toString())); + } } // Add .gitignore writeFileSync(join(args.destination, ".gitignore"), GIT_IGNORE); diff --git a/packages/create/tests/ts-retarget.test.ts b/packages/create/tests/ts-retarget.test.ts new file mode 100644 index 0000000..cabb70b --- /dev/null +++ b/packages/create/tests/ts-retarget.test.ts @@ -0,0 +1,28 @@ +import { expect, it } from "vitest"; +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { retargetTSFilenames } from "../src/create-solid-v2"; + +const fixtureConfig = fileURLToPath(new URL("./fixtures/solid-v2-basic/vite.config.ts", import.meta.url)); + +it("dedupes the extensions array instead of writing ['.jsx', '.jsx']", () => { + const converted = retargetTSFilenames(readFileSync(fixtureConfig).toString()); + + expect(converted).toContain("extensions: ['.jsx']"); + expect(converted).not.toContain("'.tsx'"); + expect(converted).not.toContain("'.jsx', '.jsx'"); + // Setup files are transpiled alongside the rest of the template + expect(converted).toContain("./vitest-setup.js"); +}); + +it("retargets filename mentions in comments and prose", () => { + const converted = retargetTSFilenames( + "// generates the entries around src/App.tsx\nSee `vite.config.ts` and `src/routes/users/[id].tsx`. Type declarations stay in `global.d.ts`.", + ); + + expect(converted).toContain("src/App.jsx"); + expect(converted).toContain("`vite.config.js`"); + expect(converted).toContain("[id].jsx"); + // `.d.ts` files are deleted by the conversion, not renamed + expect(converted).toContain("global.d.ts"); +});