diff --git a/apps/svelte.dev/.gitignore b/apps/svelte.dev/.gitignore index a3079a3c21..b45f37b025 100644 --- a/apps/svelte.dev/.gitignore +++ b/apps/svelte.dev/.gitignore @@ -8,6 +8,7 @@ /src/routes/_home/Supporters/donors.js /scripts/svelte-template /static/svelte-template.json +/static/svelte-tailwind-template.json # git-repositories of synced docs go here /repos/ diff --git a/apps/svelte.dev/scripts/get_svelte_tailwind_template.js b/apps/svelte.dev/scripts/get_svelte_tailwind_template.js new file mode 100644 index 0000000000..5fec9acde7 --- /dev/null +++ b/apps/svelte.dev/scripts/get_svelte_tailwind_template.js @@ -0,0 +1,102 @@ +// @ts-check +import { readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { create } from 'sv'; + +// This download the currente Vite template from Github, adjusts it to our needs, and saves it to static/svelte-template.json +// This is used by the Svelte REPL as part of the "download project" feature + +const viteConfigTailwind = + "import { sveltekit } from '@sveltejs/kit/vite';\nimport { defineConfig } from 'vite';\nimport tailwindcss from '@tailwindcss/vite'\nexport default defineConfig({\n\tplugins: [sveltekit(),tailwindcss()]\n});\n"; + +const force = process.env.FORCE_UPDATE === 'true'; +const output_file = fileURLToPath( + new URL('../static/svelte-tailwind-template.json', import.meta.url) +); +const output_dir = fileURLToPath(new URL('./svelte-tailwind-template', import.meta.url)); + +try { + if (!force && statSync(output_file)) { + console.info(`[update/template] ${output_file} exists. Skipping`); + process.exit(0); + } +} catch { + // create Svelte-Kit skelton app + create(output_dir, { template: 'minimal', types: 'typescript', name: 'your-app' }); + + function get_all_files(dir) { + const files = []; + const items = readdirSync(dir, { withFileTypes: true }); + + for (const item of items) { + const full_path = join(dir, item.name); + if (item.isDirectory()) { + files.push(...get_all_files(full_path)); + } else { + files.push(full_path.replaceAll('\\', '/')); + } + } + + return files; + } + + const all_files = get_all_files(output_dir); + const files = []; + + for (let path of all_files) { + const bytes = readFileSync(path); + const string = bytes.toString(); + let data = bytes.compare(Buffer.from(string)) === 0 ? string : [...bytes]; + + // vite config to use along with Tailwind CSS + if (path.endsWith('vite.config.ts')) { + files.push({ + path: 'vite.config.ts', + data: viteConfigTailwind + }); + } + + // add Tailwind CSS as devDependencies + if (path.endsWith('package.json')) { + try { + const pkg = JSON.parse(string); + + pkg.devDependencies ||= {}; + pkg.devDependencies['tailwindcss'] = '^4.1.8'; + pkg.devDependencies['@tailwindcss/vite'] = '^4.1.8'; + + data = JSON.stringify(pkg, null, 2); // Pretty-print with 2 spaces + } catch (err) { + console.error('Failed to parse package.json:', err); + } + } + + if (path.endsWith('routes/+page.svelte')) { + data = `\n\n\n`; + } + + files.push({ path: path.slice(output_dir.length + 1), data }); + } + + files.push({ + path: 'src/routes/+page.js', + data: + "// Because we don't know whether or not your playground app can run in a server environment, we disable server-side rendering.\n" + + '// Make sure to test whether or not you can re-enable it, as SSR improves perceived performance and site accessibility.\n' + + '// Read more about this option here: https://svelte.dev/docs/kit/page-options#ssr\n' + + 'export const ssr = false;\n' + }); + + // add CSS styles from playground to the project + + files.push({ + path: 'src/app.css', + data: '@import "tailwindcss";' + }); + + writeFileSync(output_file, JSON.stringify(files)); + + // remove output dir afterwards to prevent it messing with Vite watcher + rmSync(output_dir, { force: true, recursive: true }); +} diff --git a/apps/svelte.dev/scripts/get_svelte_template.js b/apps/svelte.dev/scripts/get_svelte_template.js index d525eaa3df..7fc7eba0a3 100644 --- a/apps/svelte.dev/scripts/get_svelte_template.js +++ b/apps/svelte.dev/scripts/get_svelte_template.js @@ -66,7 +66,7 @@ try { { encoding: 'utf-8' } ); const css = html - .slice(html.indexOf('')) + .slice(html.indexOf('')) .split('\n') .map((line) => // remove leading \t diff --git a/apps/svelte.dev/scripts/update.js b/apps/svelte.dev/scripts/update.js index 9c25d958dc..7ec5ef95fe 100644 --- a/apps/svelte.dev/scripts/update.js +++ b/apps/svelte.dev/scripts/update.js @@ -9,4 +9,5 @@ const env = { fork(`${dir}/get_contributors.js`, { env }); fork(`${dir}/get_donors.js`, { env }); +fork(`${dir}/get_svelte_tailwind_template.js`, { env }); fork(`${dir}/get_svelte_template.js`, { env }); diff --git a/apps/svelte.dev/src/routes/(authed)/playground/[id]/+page.svelte b/apps/svelte.dev/src/routes/(authed)/playground/[id]/+page.svelte index 134402a78e..9761d10749 100644 --- a/apps/svelte.dev/src/routes/(authed)/playground/[id]/+page.svelte +++ b/apps/svelte.dev/src/routes/(authed)/playground/[id]/+page.svelte @@ -97,10 +97,12 @@ } async function download() { - const { files: components, imports } = repl.toJSON(); + const { files: components, imports, tailwind } = repl.toJSON(); const files: Array<{ path: string; data: string }> = await ( - await fetch('/svelte-template.json') + tailwind + ? await fetch('/svelte-tailwind-template.json') + : await fetch('/svelte-template.json') ).json(); if (imports.length > 0) {