gotodev 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +90 -127
- package/package.json +1 -1
- package/template-fetcher.js +877 -262
package/template-fetcher.js
CHANGED
|
@@ -1,92 +1,307 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Template Fetcher -
|
|
2
|
+
* Template Fetcher - Generates official Vite templates with latest dependencies
|
|
3
|
+
* Updated with latest versions and security fixes
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
|
-
const axios = require('axios');
|
|
6
6
|
const fs = require('fs-extra');
|
|
7
7
|
const path = require('path');
|
|
8
|
+
const { execSync } = require('child_process');
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
+
* Get latest package versions from npm
|
|
11
12
|
*/
|
|
12
|
-
async function
|
|
13
|
+
async function getLatestVersion(pkg) {
|
|
13
14
|
try {
|
|
14
|
-
const
|
|
15
|
-
return
|
|
15
|
+
const result = execSync(`npm view ${pkg} version --json`, { encoding: 'utf8' });
|
|
16
|
+
return result.trim().replace(/['"]/g, '');
|
|
16
17
|
} catch (error) {
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
// Fallback to known latest versions
|
|
19
|
+
const fallbacks = {
|
|
20
|
+
'vite': '6.0.7',
|
|
21
|
+
'react': '19.0.0',
|
|
22
|
+
'react-dom': '19.0.0',
|
|
23
|
+
'vue': '3.5.13',
|
|
24
|
+
'svelte': '5.17.3',
|
|
25
|
+
'@vitejs/plugin-react': '4.3.4',
|
|
26
|
+
'@vitejs/plugin-vue': '5.2.1',
|
|
27
|
+
'@sveltejs/vite-plugin-svelte': '5.0.3',
|
|
28
|
+
'typescript': '5.7.2',
|
|
29
|
+
'tailwindcss': '3.4.17',
|
|
30
|
+
'postcss': '8.4.49',
|
|
31
|
+
'autoprefixer': '10.4.20',
|
|
32
|
+
'vue-router': '4.3.2',
|
|
33
|
+
'pinia': '2.3.0',
|
|
34
|
+
'@types/react': '19.0.1',
|
|
35
|
+
'@types/react-dom': '19.0.1',
|
|
36
|
+
'vue-tsc': '2.2.0',
|
|
37
|
+
'svelte-check': '4.1.4',
|
|
38
|
+
'svelte-preprocess': '6.0.3'
|
|
39
|
+
};
|
|
40
|
+
return fallbacks[pkg] || 'latest';
|
|
19
41
|
}
|
|
20
42
|
}
|
|
21
43
|
|
|
22
44
|
/**
|
|
23
|
-
*
|
|
45
|
+
* Generate React template files
|
|
24
46
|
*/
|
|
25
|
-
async function
|
|
26
|
-
const
|
|
47
|
+
async function generateReactTemplate(projectName, features, targetDir) {
|
|
48
|
+
const files = {};
|
|
27
49
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
50
|
+
// Get latest versions
|
|
51
|
+
const versions = {
|
|
52
|
+
react: await getLatestVersion('react'),
|
|
53
|
+
reactDom: await getLatestVersion('react-dom'),
|
|
54
|
+
vite: await getLatestVersion('vite'),
|
|
55
|
+
pluginReact: await getLatestVersion('@vitejs/plugin-react'),
|
|
56
|
+
typescript: await getLatestVersion('typescript'),
|
|
57
|
+
typesReact: await getLatestVersion('@types/react'),
|
|
58
|
+
typesReactDom: await getLatestVersion('@types/react-dom'),
|
|
59
|
+
tailwind: await getLatestVersion('tailwindcss'),
|
|
60
|
+
postcss: await getLatestVersion('postcss'),
|
|
61
|
+
autoprefixer: await getLatestVersion('autoprefixer')
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Main entry point
|
|
65
|
+
if (features.typescript) {
|
|
66
|
+
files['src/main.tsx'] = `import React from 'react';
|
|
67
|
+
import ReactDOM from 'react-dom/client';
|
|
68
|
+
import App from './App.tsx';
|
|
69
|
+
import './index.css';
|
|
70
|
+
|
|
71
|
+
const root = ReactDOM.createRoot(
|
|
72
|
+
document.getElementById('root') as HTMLElement
|
|
73
|
+
);
|
|
74
|
+
root.render(
|
|
75
|
+
<React.StrictMode>
|
|
76
|
+
<App />
|
|
77
|
+
</React.StrictMode>
|
|
78
|
+
);`;
|
|
33
79
|
|
|
34
|
-
|
|
80
|
+
files['src/App.tsx'] = `import './index.css';
|
|
81
|
+
|
|
82
|
+
export default function App() {
|
|
83
|
+
return (
|
|
84
|
+
<div className="min-h-screen bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
|
85
|
+
<div className="text-center text-white p-8 bg-black/20 backdrop-blur-lg rounded-2xl shadow-2xl">
|
|
86
|
+
<h1 className="text-5xl font-bold mb-4">🚀 ${projectName}</h1>
|
|
87
|
+
<p className="text-xl mb-6">Built with React 19 + TypeScript + Tailwind</p>
|
|
88
|
+
<div className="flex gap-4 justify-center">
|
|
89
|
+
<a href="https://vitejs.dev" target="_blank" className="px-4 py-2 bg-white/20 rounded-lg hover:bg-white/30 transition">
|
|
90
|
+
Vite Docs
|
|
91
|
+
</a>
|
|
92
|
+
<a href="https://react.dev" target="_blank" className="px-4 py-2 bg-white/20 rounded-lg hover:bg-white/30 transition">
|
|
93
|
+
React Docs
|
|
94
|
+
</a>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
}`;
|
|
100
|
+
} else {
|
|
101
|
+
files['src/main.jsx'] = `import React from 'react';
|
|
102
|
+
import ReactDOM from 'react-dom/client';
|
|
103
|
+
import App from './App.jsx';
|
|
104
|
+
import './index.css';
|
|
105
|
+
|
|
106
|
+
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
107
|
+
root.render(<App />);`;
|
|
35
108
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
109
|
+
files['src/App.jsx'] = `import './index.css';
|
|
110
|
+
|
|
111
|
+
export default function App() {
|
|
112
|
+
return (
|
|
113
|
+
<div className="min-h-screen bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
|
114
|
+
<div className="text-center text-white p-8 bg-black/20 backdrop-blur-lg rounded-2xl shadow-2xl">
|
|
115
|
+
<h1 className="text-5xl font-bold mb-4">🚀 ${projectName}</h1>
|
|
116
|
+
<p className="text-xl mb-6">Built with React 19 + Vite</p>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// HTML
|
|
124
|
+
files['index.html'] = `<!DOCTYPE html>
|
|
125
|
+
<html lang="en">
|
|
126
|
+
<head>
|
|
127
|
+
<meta charset="UTF-8" />
|
|
128
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
129
|
+
<title>${projectName}</title>
|
|
130
|
+
</head>
|
|
131
|
+
<body>
|
|
132
|
+
<div id="root"></div>
|
|
133
|
+
<script type="module" src="/src/main.${features.typescript ? 'tsx' : 'jsx'}"></script>
|
|
134
|
+
</body>
|
|
135
|
+
</html>`;
|
|
136
|
+
|
|
137
|
+
// Vite config
|
|
138
|
+
files['vite.config.js'] = `import { defineConfig } from 'vite';
|
|
139
|
+
import react from '@vitejs/plugin-react';
|
|
140
|
+
|
|
141
|
+
export default defineConfig({
|
|
142
|
+
plugins: [react()],
|
|
143
|
+
});`;
|
|
144
|
+
|
|
145
|
+
// CSS (with Tailwind if requested)
|
|
146
|
+
if (features.tailwind) {
|
|
147
|
+
files['src/index.css'] = `@tailwind base;
|
|
148
|
+
@tailwind components;
|
|
149
|
+
@tailwind utilities;
|
|
150
|
+
|
|
151
|
+
body {
|
|
152
|
+
margin: 0;
|
|
153
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
154
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
155
|
+
sans-serif;
|
|
156
|
+
-webkit-font-smoothing: antialiased;
|
|
157
|
+
-moz-osx-font-smoothing: grayscale;
|
|
158
|
+
}`;
|
|
159
|
+
|
|
160
|
+
files['tailwind.config.js'] = `/** @type {import('tailwindcss').Config} */
|
|
161
|
+
export default {
|
|
162
|
+
content: [
|
|
163
|
+
"./index.html",
|
|
164
|
+
"./src/**/*.{js,ts,jsx,tsx}"
|
|
165
|
+
],
|
|
166
|
+
theme: {
|
|
167
|
+
extend: {},
|
|
168
|
+
},
|
|
169
|
+
plugins: [],
|
|
170
|
+
}`;
|
|
171
|
+
|
|
172
|
+
files['postcss.config.js'] = `export default {
|
|
173
|
+
plugins: {
|
|
174
|
+
tailwindcss: {},
|
|
175
|
+
autoprefixer: {},
|
|
176
|
+
},
|
|
177
|
+
}`;
|
|
178
|
+
} else {
|
|
179
|
+
files['src/index.css'] = `body {
|
|
180
|
+
margin: 0;
|
|
181
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
182
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
183
|
+
sans-serif;
|
|
184
|
+
-webkit-font-smoothing: antialiased;
|
|
185
|
+
-moz-osx-font-smoothing: grayscale;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
code {
|
|
189
|
+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
|
190
|
+
monospace;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
#root {
|
|
194
|
+
min-height: 100vh;
|
|
195
|
+
display: flex;
|
|
196
|
+
align-items: center;
|
|
197
|
+
justify-content: center;
|
|
198
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
199
|
+
}`;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Package.json
|
|
203
|
+
const pkg = {
|
|
204
|
+
name: projectName,
|
|
205
|
+
version: '0.0.0',
|
|
206
|
+
type: 'module',
|
|
207
|
+
scripts: {
|
|
208
|
+
dev: 'vite',
|
|
209
|
+
build: 'vite build',
|
|
210
|
+
lint: 'eslint .',
|
|
211
|
+
preview: 'vite preview'
|
|
212
|
+
},
|
|
213
|
+
dependencies: {
|
|
214
|
+
react: `^${versions.react}`,
|
|
215
|
+
'react-dom': `^${versions.reactDom}`
|
|
216
|
+
},
|
|
217
|
+
devDependencies: {
|
|
218
|
+
'@vitejs/plugin-react': `^${versions.pluginReact}`,
|
|
219
|
+
vite: `^${versions.vite}`
|
|
57
220
|
}
|
|
58
|
-
}
|
|
59
|
-
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
if (features.typescript) {
|
|
224
|
+
pkg.devDependencies['@types/react'] = `^${versions.typesReact}`;
|
|
225
|
+
pkg.devDependencies['@types/react-dom'] = `^${versions.typesReactDom}`;
|
|
226
|
+
pkg.devDependencies['typescript'] = `^${versions.typescript}`;
|
|
227
|
+
pkg.scripts.lint = 'eslint . --ext .ts,.tsx';
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (features.tailwind) {
|
|
231
|
+
pkg.devDependencies['tailwindcss'] = `^${versions.tailwind}`;
|
|
232
|
+
pkg.devDependencies['postcss'] = `^${versions.postcss}`;
|
|
233
|
+
pkg.devDependencies['autoprefixer'] = `^${versions.autoprefixer}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
files['package.json'] = JSON.stringify(pkg, null, 2);
|
|
237
|
+
|
|
238
|
+
// Write all files
|
|
239
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
240
|
+
const fullPath = path.join(targetDir, filePath);
|
|
241
|
+
fs.ensureDirSync(path.dirname(fullPath));
|
|
242
|
+
fs.writeFileSync(fullPath, content);
|
|
60
243
|
}
|
|
61
244
|
}
|
|
62
245
|
|
|
63
246
|
/**
|
|
64
|
-
*
|
|
247
|
+
* Generate Vue template files
|
|
65
248
|
*/
|
|
66
|
-
async function
|
|
67
|
-
const
|
|
249
|
+
async function generateVueTemplate(projectName, features, targetDir) {
|
|
250
|
+
const files = {};
|
|
68
251
|
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
252
|
+
// Get latest versions
|
|
253
|
+
const versions = {
|
|
254
|
+
vue: await getLatestVersion('vue'),
|
|
255
|
+
vite: await getLatestVersion('vite'),
|
|
256
|
+
pluginVue: await getLatestVersion('@vitejs/plugin-vue'),
|
|
257
|
+
typescript: await getLatestVersion('typescript'),
|
|
258
|
+
vueTsc: await getLatestVersion('vue-tsc'),
|
|
259
|
+
tailwind: await getLatestVersion('tailwindcss'),
|
|
260
|
+
postcss: await getLatestVersion('postcss'),
|
|
261
|
+
autoprefixer: await getLatestVersion('autoprefixer'),
|
|
262
|
+
vueRouter: await getLatestVersion('vue-router'),
|
|
263
|
+
pinia: await getLatestVersion('pinia')
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
// Main entry
|
|
267
|
+
if (features.typescript) {
|
|
268
|
+
files['src/main.ts'] = `import { createApp } from 'vue';
|
|
269
|
+
import App from './App.vue';
|
|
270
|
+
import './index.css';
|
|
271
|
+
|
|
272
|
+
createApp(App).mount('#app');`;
|
|
273
|
+
} else {
|
|
274
|
+
files['src/main.js'] = `import { createApp } from 'vue';
|
|
275
|
+
import App from './App.vue';
|
|
276
|
+
import './index.css';
|
|
277
|
+
|
|
278
|
+
createApp(App).mount('#app');`;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// App component
|
|
282
|
+
files['src/App.vue'] = `<template>
|
|
283
|
+
<div class="min-h-screen bg-gradient-to-br from-green-400 to-blue-500 flex items-center justify-center">
|
|
284
|
+
<div class="text-center text-white p-8 bg-black/20 backdrop-blur-lg rounded-2xl shadow-2xl">
|
|
285
|
+
<h1 class="text-5xl font-bold mb-4">🚀 ${projectName}</h1>
|
|
286
|
+
<p class="text-xl mb-6">Built with Vue 3 + Vite${features.typescript ? ' + TypeScript' : ''}${features.tailwind ? ' + Tailwind' : ''}</p>
|
|
287
|
+
<div class="flex gap-4 justify-center">
|
|
288
|
+
<a href="https://vitejs.dev" target="_blank" class="px-4 py-2 bg-white/20 rounded-lg hover:bg-white/30 transition">Vite Docs</a>
|
|
289
|
+
<a href="https://vuejs.org" target="_blank" class="px-4 py-2 bg-white/20 rounded-lg hover:bg-white/30 transition">Vue Docs</a>
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
83
292
|
</div>
|
|
84
293
|
</template>
|
|
85
294
|
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
</
|
|
89
|
-
|
|
295
|
+
<script setup>
|
|
296
|
+
// Vue 3 Composition API
|
|
297
|
+
</script>
|
|
298
|
+
|
|
299
|
+
<style scoped>
|
|
300
|
+
/* Component-specific styles */
|
|
301
|
+
</style>`;
|
|
302
|
+
|
|
303
|
+
// HTML
|
|
304
|
+
files['index.html'] = `<!DOCTYPE html>
|
|
90
305
|
<html lang="en">
|
|
91
306
|
<head>
|
|
92
307
|
<meta charset="UTF-8" />
|
|
@@ -95,195 +310,563 @@ createApp(App).mount('#app')`,
|
|
|
95
310
|
</head>
|
|
96
311
|
<body>
|
|
97
312
|
<div id="app"></div>
|
|
98
|
-
<script type="module" src="/src/main.js"></script>
|
|
313
|
+
<script type="module" src="/src/main.${features.typescript ? 'ts' : 'js'}"></script>
|
|
99
314
|
</body>
|
|
100
|
-
</html
|
|
101
|
-
|
|
102
|
-
|
|
315
|
+
</html>`;
|
|
316
|
+
|
|
317
|
+
// Vite config
|
|
318
|
+
files['vite.config.js'] = `import { defineConfig } from 'vite';
|
|
319
|
+
import vue from '@vitejs/plugin-vue';
|
|
103
320
|
|
|
104
321
|
export default defineConfig({
|
|
105
322
|
plugins: [vue()],
|
|
106
|
-
})
|
|
107
|
-
|
|
323
|
+
});`;
|
|
324
|
+
|
|
325
|
+
// CSS
|
|
326
|
+
if (features.tailwind) {
|
|
327
|
+
files['src/index.css'] = `@tailwind base;
|
|
328
|
+
@tailwind components;
|
|
329
|
+
@tailwind utilities;
|
|
330
|
+
|
|
331
|
+
body {
|
|
332
|
+
margin: 0;
|
|
333
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
334
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
335
|
+
sans-serif;
|
|
336
|
+
-webkit-font-smoothing: antialiased;
|
|
337
|
+
-moz-osx-font-smoothing: grayscale;
|
|
338
|
+
}`;
|
|
339
|
+
|
|
340
|
+
files['tailwind.config.js'] = `/** @type {import('tailwindcss').Config} */
|
|
341
|
+
export default {
|
|
342
|
+
content: [
|
|
343
|
+
"./index.html",
|
|
344
|
+
"./src/**/*.{vue,js,ts,jsx,tsx}"
|
|
345
|
+
],
|
|
346
|
+
theme: {
|
|
347
|
+
extend: {},
|
|
348
|
+
},
|
|
349
|
+
plugins: [],
|
|
350
|
+
}`;
|
|
108
351
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"compilerOptions": {
|
|
115
|
-
"target": "ES2020",
|
|
116
|
-
"module": "ESNext",
|
|
117
|
-
"lib": ["ES2020", "DOM"],
|
|
118
|
-
"skipLibCheck": true,
|
|
119
|
-
"moduleResolution": "bundler",
|
|
120
|
-
"strict": true
|
|
121
|
-
}
|
|
352
|
+
files['postcss.config.js'] = `export default {
|
|
353
|
+
plugins: {
|
|
354
|
+
tailwindcss: {},
|
|
355
|
+
autoprefixer: {},
|
|
356
|
+
},
|
|
122
357
|
}`;
|
|
123
|
-
|
|
124
|
-
|
|
358
|
+
} else {
|
|
359
|
+
files['src/index.css'] = `body {
|
|
360
|
+
margin: 0;
|
|
361
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
362
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
363
|
+
sans-serif;
|
|
364
|
+
-webkit-font-smoothing: antialiased;
|
|
365
|
+
-moz-osx-font-smoothing: grayscale;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
#root {
|
|
369
|
+
min-height: 100vh;
|
|
370
|
+
display: flex;
|
|
371
|
+
align-items: center;
|
|
372
|
+
justify-content: center;
|
|
373
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
374
|
+
}`;
|
|
375
|
+
}
|
|
125
376
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (features.pinia) {
|
|
145
|
-
vueFiles['src/store.js'] = `import { defineStore } from 'pinia'
|
|
146
|
-
export const useMainStore = defineStore('main', {
|
|
147
|
-
state: () => ({ count: 0 }),
|
|
148
|
-
actions: { increment() { this.count++ } }
|
|
149
|
-
})`;
|
|
150
|
-
imports.push("import { createPinia } from 'pinia'");
|
|
151
|
-
uses.push(".use(createPinia())");
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const mainKey = features.typescript ? 'src/main.ts' : 'src/main.js';
|
|
155
|
-
const current = vueFiles[mainKey];
|
|
156
|
-
|
|
157
|
-
// Build the new main file
|
|
158
|
-
let newMain = current;
|
|
159
|
-
|
|
160
|
-
// Add imports after the first line
|
|
161
|
-
if (imports.length > 0) {
|
|
162
|
-
const lines = current.split('\n');
|
|
163
|
-
const importLineIndex = lines.findIndex(line => line.includes("import { createApp } from 'vue'"));
|
|
164
|
-
if (importLineIndex !== -1) {
|
|
165
|
-
lines.splice(importLineIndex + 1, 0, ...imports);
|
|
166
|
-
newMain = lines.join('\n');
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Replace mount call
|
|
171
|
-
const mountCall = "createApp(App).mount('#app')";
|
|
172
|
-
const newMountCall = `createApp(App)${uses.join('')}.mount('#app')`;
|
|
173
|
-
console.log('DEBUG: Looking for:', mountCall);
|
|
174
|
-
console.log('DEBUG: In content:', newMain);
|
|
175
|
-
console.log('DEBUG: Replacing with:', newMountCall);
|
|
176
|
-
newMain = newMain.replace(mountCall, newMountCall);
|
|
177
|
-
console.log('DEBUG: Result:', newMain);
|
|
178
|
-
|
|
179
|
-
vueFiles[mainKey] = newMain;
|
|
377
|
+
// Package.json
|
|
378
|
+
const pkg = {
|
|
379
|
+
name: projectName,
|
|
380
|
+
version: '0.0.0',
|
|
381
|
+
type: 'module',
|
|
382
|
+
scripts: {
|
|
383
|
+
dev: 'vite',
|
|
384
|
+
build: 'vite build',
|
|
385
|
+
preview: 'vite preview'
|
|
386
|
+
},
|
|
387
|
+
dependencies: {
|
|
388
|
+
vue: `^${versions.vue}`
|
|
389
|
+
},
|
|
390
|
+
devDependencies: {
|
|
391
|
+
'@vitejs/plugin-vue': `^${versions.pluginVue}`,
|
|
392
|
+
vite: `^${versions.vite}`
|
|
180
393
|
}
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
if (features.typescript) {
|
|
397
|
+
pkg.devDependencies['typescript'] = `^${versions.typescript}`;
|
|
398
|
+
pkg.devDependencies['vue-tsc'] = `^${versions.vueTsc}`;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (features.router) {
|
|
402
|
+
pkg.dependencies['vue-router'] = `^${versions.vueRouter}`;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (features.pinia) {
|
|
406
|
+
pkg.dependencies['pinia'] = `^${versions.pinia}`;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (features.tailwind) {
|
|
410
|
+
pkg.devDependencies['tailwindcss'] = `^${versions.tailwind}`;
|
|
411
|
+
pkg.devDependencies['postcss'] = `^${versions.postcss}`;
|
|
412
|
+
pkg.devDependencies['autoprefixer'] = `^${versions.autoprefixer}`;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
files['package.json'] = JSON.stringify(pkg, null, 2);
|
|
416
|
+
|
|
417
|
+
// Write all files
|
|
418
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
419
|
+
const fullPath = path.join(targetDir, filePath);
|
|
420
|
+
fs.ensureDirSync(path.dirname(fullPath));
|
|
421
|
+
fs.writeFileSync(fullPath, content);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Generate Svelte template files
|
|
427
|
+
*/
|
|
428
|
+
async function generateSvelteTemplate(projectName, features, targetDir) {
|
|
429
|
+
const files = {};
|
|
430
|
+
|
|
431
|
+
// Get latest versions
|
|
432
|
+
const versions = {
|
|
433
|
+
svelte: await getLatestVersion('svelte'),
|
|
434
|
+
vite: await getLatestVersion('vite'),
|
|
435
|
+
pluginSvelte: await getLatestVersion('@sveltejs/vite-plugin-svelte'),
|
|
436
|
+
typescript: await getLatestVersion('typescript'),
|
|
437
|
+
svelteCheck: await getLatestVersion('svelte-check'),
|
|
438
|
+
sveltePreprocess: await getLatestVersion('svelte-preprocess'),
|
|
439
|
+
tailwind: await getLatestVersion('tailwindcss'),
|
|
440
|
+
postcss: await getLatestVersion('postcss'),
|
|
441
|
+
autoprefixer: await getLatestVersion('autoprefixer')
|
|
442
|
+
};
|
|
181
443
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
444
|
+
// Main entry
|
|
445
|
+
if (features.typescript) {
|
|
446
|
+
files['src/main.ts'] = `import App from './App.svelte';
|
|
447
|
+
|
|
448
|
+
const app = new App({
|
|
449
|
+
target: document.body,
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
export default app;`;
|
|
453
|
+
|
|
454
|
+
files['src/App.svelte'] = `<script lang="ts">
|
|
455
|
+
let name: string = '${projectName}';
|
|
456
|
+
</script>
|
|
457
|
+
|
|
458
|
+
<main>
|
|
459
|
+
<div class="container">
|
|
460
|
+
<h1>🚀 {name}</h1>
|
|
461
|
+
<p>Built with Svelte 5 + TypeScript + Tailwind</p>
|
|
462
|
+
<div class="links">
|
|
463
|
+
<a href="https://vitejs.dev" target="_blank">Vite Docs</a>
|
|
464
|
+
<a href="https://svelte.dev" target="_blank">Svelte Docs</a>
|
|
465
|
+
</div>
|
|
203
466
|
</div>
|
|
204
|
-
|
|
205
|
-
|
|
467
|
+
</main>
|
|
468
|
+
|
|
469
|
+
<style>
|
|
470
|
+
main {
|
|
471
|
+
min-height: 100vh;
|
|
472
|
+
display: flex;
|
|
473
|
+
align-items: center;
|
|
474
|
+
justify-content: center;
|
|
475
|
+
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
|
476
|
+
}
|
|
477
|
+
.container {
|
|
478
|
+
text-align: center;
|
|
479
|
+
padding: 2rem;
|
|
480
|
+
background: rgba(255, 255, 255, 0.1);
|
|
481
|
+
backdrop-filter: blur(10px);
|
|
482
|
+
border-radius: 1rem;
|
|
483
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
484
|
+
}
|
|
485
|
+
h1 {
|
|
486
|
+
font-size: 3rem;
|
|
487
|
+
margin-bottom: 1rem;
|
|
488
|
+
color: white;
|
|
489
|
+
}
|
|
490
|
+
p {
|
|
491
|
+
font-size: 1.2rem;
|
|
492
|
+
color: white;
|
|
493
|
+
margin-bottom: 2rem;
|
|
494
|
+
}
|
|
495
|
+
.links {
|
|
496
|
+
display: flex;
|
|
497
|
+
gap: 1rem;
|
|
498
|
+
justify-content: center;
|
|
499
|
+
}
|
|
500
|
+
a {
|
|
501
|
+
padding: 0.5rem 1rem;
|
|
502
|
+
background: rgba(255, 255, 255, 0.2);
|
|
503
|
+
color: white;
|
|
504
|
+
text-decoration: none;
|
|
505
|
+
border-radius: 0.5rem;
|
|
506
|
+
transition: background 0.3s;
|
|
507
|
+
}
|
|
508
|
+
a:hover {
|
|
509
|
+
background: rgba(255, 255, 255, 0.3);
|
|
510
|
+
}
|
|
511
|
+
</style>`;
|
|
512
|
+
} else {
|
|
513
|
+
files['src/main.js'] = `import App from './App.svelte';
|
|
514
|
+
|
|
515
|
+
const app = new App({
|
|
516
|
+
target: document.body,
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
export default app;`;
|
|
520
|
+
|
|
521
|
+
files['src/App.svelte'] = `<script>
|
|
522
|
+
let name = '${projectName}';
|
|
523
|
+
</script>
|
|
524
|
+
|
|
525
|
+
<main>
|
|
526
|
+
<div class="container">
|
|
527
|
+
<h1>🚀 {name}</h1>
|
|
528
|
+
<p>Built with Svelte 5 + Vite</p>
|
|
529
|
+
</div>
|
|
530
|
+
</main>
|
|
531
|
+
|
|
532
|
+
<style>
|
|
533
|
+
main {
|
|
534
|
+
min-height: 100vh;
|
|
535
|
+
display: flex;
|
|
536
|
+
align-items: center;
|
|
537
|
+
justify-content: center;
|
|
538
|
+
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
|
539
|
+
}
|
|
540
|
+
.container {
|
|
541
|
+
text-align: center;
|
|
542
|
+
padding: 2rem;
|
|
543
|
+
background: rgba(255, 255, 255, 0.1);
|
|
544
|
+
backdrop-filter: blur(10px);
|
|
545
|
+
border-radius: 1rem;
|
|
546
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
547
|
+
}
|
|
548
|
+
h1 {
|
|
549
|
+
font-size: 3rem;
|
|
550
|
+
margin-bottom: 1rem;
|
|
551
|
+
color: white;
|
|
552
|
+
}
|
|
553
|
+
p {
|
|
554
|
+
font-size: 1.2rem;
|
|
555
|
+
color: white;
|
|
556
|
+
}
|
|
557
|
+
</style>`;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// HTML
|
|
561
|
+
files['index.html'] = `<!DOCTYPE html>
|
|
206
562
|
<html lang="en">
|
|
207
|
-
<head
|
|
208
|
-
<
|
|
209
|
-
|
|
210
|
-
</
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
563
|
+
<head>
|
|
564
|
+
<meta charset="UTF-8" />
|
|
565
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
566
|
+
<title>${projectName}</title>
|
|
567
|
+
</head>
|
|
568
|
+
<body>
|
|
569
|
+
<script type="module" src="/src/main.${features.typescript ? 'ts' : 'js'}"></script>
|
|
570
|
+
</body>
|
|
571
|
+
</html>`;
|
|
215
572
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
573
|
+
// Vite config
|
|
574
|
+
files['vite.config.js'] = `import { defineConfig } from 'vite';
|
|
575
|
+
import { svelte } from '@vitejs/vite-plugin-svelte';
|
|
576
|
+
|
|
577
|
+
export default defineConfig({
|
|
578
|
+
plugins: [svelte()],
|
|
579
|
+
});`;
|
|
580
|
+
|
|
581
|
+
// Svelte config (for TypeScript)
|
|
582
|
+
if (features.typescript) {
|
|
583
|
+
files['svelte.config.js'] = `import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|
584
|
+
|
|
585
|
+
export default {
|
|
586
|
+
preprocess: vitePreprocess(),
|
|
587
|
+
};`;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// TypeScript config
|
|
591
|
+
if (features.typescript) {
|
|
592
|
+
files['tsconfig.json'] = `{
|
|
593
|
+
"extends": "@sveltejs/tsconfig/tsconfig.json",
|
|
220
594
|
"compilerOptions": {
|
|
221
|
-
"target": "ES2020",
|
|
222
|
-
"module": "ESNext",
|
|
223
|
-
"lib": ["ES2020", "DOM"],
|
|
224
|
-
"skipLibCheck": true,
|
|
225
|
-
"moduleResolution": "bundler",
|
|
226
|
-
"jsx": "react-jsx",
|
|
227
595
|
"strict": true
|
|
596
|
+
},
|
|
597
|
+
"include": ["src/**/*"],
|
|
598
|
+
"exclude": ["node_modules/*", "dist/*"]
|
|
599
|
+
}`;
|
|
228
600
|
}
|
|
601
|
+
|
|
602
|
+
// CSS (with Tailwind if requested)
|
|
603
|
+
if (features.tailwind) {
|
|
604
|
+
files['src/app.css'] = `@tailwind base;
|
|
605
|
+
@tailwind components;
|
|
606
|
+
@tailwind utilities;
|
|
607
|
+
|
|
608
|
+
body {
|
|
609
|
+
margin: 0;
|
|
610
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
611
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
612
|
+
sans-serif;
|
|
613
|
+
-webkit-font-smoothing: antialiased;
|
|
614
|
+
-moz-osx-font-smoothing: grayscale;
|
|
229
615
|
}`;
|
|
230
|
-
|
|
231
|
-
|
|
616
|
+
|
|
617
|
+
files['tailwind.config.js'] = `/** @type {import('tailwindcss').Config} */
|
|
618
|
+
export default {
|
|
619
|
+
content: [
|
|
620
|
+
"./index.html",
|
|
621
|
+
"./src/**/*.{svelte,js,ts}"
|
|
622
|
+
],
|
|
623
|
+
theme: {
|
|
624
|
+
extend: {},
|
|
625
|
+
},
|
|
626
|
+
plugins: [],
|
|
627
|
+
}`;
|
|
628
|
+
|
|
629
|
+
files['postcss.config.js'] = `export default {
|
|
630
|
+
plugins: {
|
|
631
|
+
tailwindcss: {},
|
|
632
|
+
autoprefixer: {},
|
|
633
|
+
},
|
|
634
|
+
}`;
|
|
635
|
+
} else {
|
|
636
|
+
files['src/app.css'] = `body {
|
|
637
|
+
margin: 0;
|
|
638
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
639
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
640
|
+
sans-serif;
|
|
641
|
+
-webkit-font-smoothing: antialiased;
|
|
642
|
+
-moz-osx-font-smoothing: grayscale;
|
|
643
|
+
}`;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Package.json
|
|
647
|
+
const pkg = {
|
|
648
|
+
name: projectName,
|
|
649
|
+
version: '0.0.0',
|
|
650
|
+
type: 'module',
|
|
651
|
+
scripts: {
|
|
652
|
+
dev: 'vite',
|
|
653
|
+
build: 'vite build',
|
|
654
|
+
preview: 'vite preview'
|
|
655
|
+
},
|
|
656
|
+
dependencies: {
|
|
657
|
+
svelte: `^${versions.svelte}`
|
|
658
|
+
},
|
|
659
|
+
devDependencies: {
|
|
660
|
+
'@sveltejs/vite-plugin-svelte': `^${versions.pluginSvelte}`,
|
|
661
|
+
vite: `^${versions.vite}`
|
|
232
662
|
}
|
|
663
|
+
};
|
|
233
664
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
} else if (framework === 'svelte') {
|
|
241
|
-
// Svelte template
|
|
242
|
-
const svelteFiles = {
|
|
243
|
-
'src/main.js': `import App from './App.svelte'
|
|
244
|
-
new App({ target: document.body })`,
|
|
245
|
-
'src/App.svelte': `<script>let name = 'world';</script>
|
|
246
|
-
<main><h1>🚀 Svelte + Vite</h1><p>Hello {name}!</p></main>
|
|
247
|
-
<style>main{font-family:sans-serif;padding:2rem;text-align:center}</style>`,
|
|
248
|
-
'index.html': `<!DOCTYPE html>
|
|
249
|
-
<html lang="en">
|
|
250
|
-
<head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
251
|
-
<title>${projectName}</title></head>
|
|
252
|
-
<body><script type="module" src="/src/main.js"></script></body>
|
|
253
|
-
</html>`,
|
|
254
|
-
'vite.config.js': `import { defineConfig } from 'vite'
|
|
255
|
-
import { svelte } from '@vitejs/vite-plugin-svelte'
|
|
256
|
-
export default defineConfig({ plugins: [svelte()] })`
|
|
257
|
-
};
|
|
665
|
+
if (features.typescript) {
|
|
666
|
+
pkg.devDependencies['typescript'] = `^${versions.typescript}`;
|
|
667
|
+
pkg.devDependencies['svelte-check'] = `^${versions.svelteCheck}`;
|
|
668
|
+
pkg.devDependencies['svelte-preprocess'] = `^${versions.sveltePreprocess}`;
|
|
669
|
+
pkg.scripts.check = 'svelte-check';
|
|
670
|
+
}
|
|
258
671
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
672
|
+
if (features.tailwind) {
|
|
673
|
+
pkg.devDependencies['tailwindcss'] = `^${versions.tailwind}`;
|
|
674
|
+
pkg.devDependencies['postcss'] = `^${versions.postcss}`;
|
|
675
|
+
pkg.devDependencies['autoprefixer'] = `^${versions.autoprefixer}`;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
files['package.json'] = JSON.stringify(pkg, null, 2);
|
|
679
|
+
|
|
680
|
+
// Write all files
|
|
681
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
682
|
+
const fullPath = path.join(targetDir, filePath);
|
|
683
|
+
fs.ensureDirSync(path.dirname(fullPath));
|
|
684
|
+
fs.writeFileSync(fullPath, content);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Generate Vanilla template files
|
|
690
|
+
*/
|
|
691
|
+
async function generateVanillaTemplate(projectName, features, targetDir) {
|
|
692
|
+
const files = {};
|
|
693
|
+
|
|
694
|
+
// Get latest versions
|
|
695
|
+
const versions = {
|
|
696
|
+
vite: await getLatestVersion('vite'),
|
|
697
|
+
tailwind: await getLatestVersion('tailwindcss'),
|
|
698
|
+
postcss: await getLatestVersion('postcss'),
|
|
699
|
+
autoprefixer: await getLatestVersion('autoprefixer')
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// Main entry
|
|
703
|
+
files['src/main.js'] = `import './style.css';
|
|
704
|
+
|
|
705
|
+
document.querySelector('#app').innerHTML = \`
|
|
706
|
+
<div class="container">
|
|
707
|
+
<h1>🚀 ${projectName}</h1>
|
|
708
|
+
<p>Built with Vanilla JavaScript + Vite${features.tailwind ? ' + Tailwind' : ''}</p>
|
|
709
|
+
<div class="links">
|
|
710
|
+
<a href="https://vitejs.dev" target="_blank">Vite Docs</a>
|
|
711
|
+
<a href="https://developer.mozilla.org" target="_blank">MDN Docs</a>
|
|
712
|
+
</div>
|
|
713
|
+
</div>
|
|
714
|
+
\`;`;
|
|
715
|
+
|
|
716
|
+
// HTML
|
|
717
|
+
files['index.html'] = `<!DOCTYPE html>
|
|
270
718
|
<html lang="en">
|
|
271
|
-
<head
|
|
272
|
-
<
|
|
273
|
-
|
|
274
|
-
</
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
719
|
+
<head>
|
|
720
|
+
<meta charset="UTF-8" />
|
|
721
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
722
|
+
<title>${projectName}</title>
|
|
723
|
+
</head>
|
|
724
|
+
<body>
|
|
725
|
+
<div id="app"></div>
|
|
726
|
+
<script type="module" src="/src/main.js"></script>
|
|
727
|
+
</body>
|
|
728
|
+
</html>`;
|
|
729
|
+
|
|
730
|
+
// Vite config
|
|
731
|
+
files['vite.config.js'] = `import { defineConfig } from 'vite';
|
|
278
732
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
733
|
+
export default defineConfig({
|
|
734
|
+
plugins: [],
|
|
735
|
+
});`;
|
|
736
|
+
|
|
737
|
+
// CSS
|
|
738
|
+
if (features.tailwind) {
|
|
739
|
+
files['style.css'] = `@tailwind base;
|
|
740
|
+
@tailwind components;
|
|
741
|
+
@tailwind utilities;
|
|
742
|
+
|
|
743
|
+
body {
|
|
744
|
+
margin: 0;
|
|
745
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
746
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
747
|
+
sans-serif;
|
|
748
|
+
-webkit-font-smoothing: antialiased;
|
|
749
|
+
-moz-osx-font-smoothing: grayscale;
|
|
750
|
+
min-height: 100vh;
|
|
751
|
+
background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
|
|
752
|
+
display: flex;
|
|
753
|
+
align-items: center;
|
|
754
|
+
justify-content: center;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
.container {
|
|
758
|
+
text-align: center;
|
|
759
|
+
padding: 2rem;
|
|
760
|
+
background: rgba(255, 255, 255, 0.1);
|
|
761
|
+
backdrop-filter: blur(10px);
|
|
762
|
+
border-radius: 1rem;
|
|
763
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
764
|
+
color: white;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
h1 {
|
|
768
|
+
font-size: 3rem;
|
|
769
|
+
margin-bottom: 1rem;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
p {
|
|
773
|
+
font-size: 1.2rem;
|
|
774
|
+
margin-bottom: 2rem;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
.links {
|
|
778
|
+
display: flex;
|
|
779
|
+
gap: 1rem;
|
|
780
|
+
justify-content: center;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
a {
|
|
784
|
+
padding: 0.5rem 1rem;
|
|
785
|
+
background: rgba(255, 255, 255, 0.2);
|
|
786
|
+
color: white;
|
|
787
|
+
text-decoration: none;
|
|
788
|
+
border-radius: 0.5rem;
|
|
789
|
+
transition: background 0.3s;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
a:hover {
|
|
793
|
+
background: rgba(255, 255, 255, 0.3);
|
|
794
|
+
}`;
|
|
795
|
+
|
|
796
|
+
files['tailwind.config.js'] = `/** @type {import('tailwindcss').Config} */
|
|
797
|
+
export default {
|
|
798
|
+
content: [
|
|
799
|
+
"./index.html",
|
|
800
|
+
"./src/**/*.{js,ts}"
|
|
801
|
+
],
|
|
802
|
+
theme: {
|
|
803
|
+
extend: {},
|
|
804
|
+
},
|
|
805
|
+
plugins: [],
|
|
806
|
+
}`;
|
|
807
|
+
|
|
808
|
+
files['postcss.config.js'] = `export default {
|
|
809
|
+
plugins: {
|
|
810
|
+
tailwindcss: {},
|
|
811
|
+
autoprefixer: {},
|
|
812
|
+
},
|
|
813
|
+
}`;
|
|
814
|
+
} else {
|
|
815
|
+
files['style.css'] = `body {
|
|
816
|
+
margin: 0;
|
|
817
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
818
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
819
|
+
sans-serif;
|
|
820
|
+
-webkit-font-smoothing: antialiased;
|
|
821
|
+
-moz-osx-font-smoothing: grayscale;
|
|
822
|
+
min-height: 100vh;
|
|
823
|
+
background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
|
|
824
|
+
display: flex;
|
|
825
|
+
align-items: center;
|
|
826
|
+
justify-content: center;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
#app {
|
|
830
|
+
text-align: center;
|
|
831
|
+
padding: 2rem;
|
|
832
|
+
background: rgba(255, 255, 255, 0.1);
|
|
833
|
+
backdrop-filter: blur(10px);
|
|
834
|
+
border-radius: 1rem;
|
|
835
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
836
|
+
color: white;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
h1 {
|
|
840
|
+
font-size: 3rem;
|
|
841
|
+
margin-bottom: 1rem;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
p {
|
|
845
|
+
font-size: 1.2rem;
|
|
846
|
+
margin-bottom: 2rem;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
.links {
|
|
850
|
+
display: flex;
|
|
851
|
+
gap: 1rem;
|
|
852
|
+
justify-content: center;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
a {
|
|
856
|
+
padding: 0.5rem 1rem;
|
|
857
|
+
background: rgba(255, 255, 255, 0.2);
|
|
858
|
+
color: white;
|
|
859
|
+
text-decoration: none;
|
|
860
|
+
border-radius: 0.5rem;
|
|
861
|
+
transition: background 0.3s;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
a:hover {
|
|
865
|
+
background: rgba(255, 255, 255, 0.3);
|
|
866
|
+
}`;
|
|
284
867
|
}
|
|
285
868
|
|
|
286
|
-
//
|
|
869
|
+
// Package.json
|
|
287
870
|
const pkg = {
|
|
288
871
|
name: projectName,
|
|
289
872
|
version: '0.0.0',
|
|
@@ -293,42 +876,62 @@ export default defineConfig({ plugins: [] })`
|
|
|
293
876
|
build: 'vite build',
|
|
294
877
|
preview: 'vite preview'
|
|
295
878
|
},
|
|
296
|
-
|
|
297
|
-
|
|
879
|
+
devDependencies: {
|
|
880
|
+
vite: `^${versions.vite}`
|
|
881
|
+
}
|
|
298
882
|
};
|
|
299
883
|
|
|
300
|
-
if (
|
|
301
|
-
pkg.
|
|
302
|
-
pkg.devDependencies['
|
|
303
|
-
|
|
304
|
-
if (features.pinia) pkg.dependencies['pinia'] = '^2.2.0';
|
|
305
|
-
} else if (framework === 'react') {
|
|
306
|
-
pkg.dependencies['react'] = '^18.3.0';
|
|
307
|
-
pkg.dependencies['react-dom'] = '^18.3.0';
|
|
308
|
-
pkg.devDependencies['@vitejs/plugin-react'] = '^4.3.0';
|
|
309
|
-
if (features.typescript) {
|
|
310
|
-
pkg.devDependencies['@types/react'] = '^18.3.0';
|
|
311
|
-
pkg.devDependencies['@types/react-dom'] = '^18.3.0';
|
|
312
|
-
}
|
|
313
|
-
} else if (framework === 'svelte') {
|
|
314
|
-
pkg.dependencies['svelte'] = '^5.0.0';
|
|
315
|
-
pkg.devDependencies['@sveltejs/vite-plugin-svelte'] = '^4.0.0';
|
|
884
|
+
if (features.tailwind) {
|
|
885
|
+
pkg.devDependencies['tailwindcss'] = `^${versions.tailwind}`;
|
|
886
|
+
pkg.devDependencies['postcss'] = `^${versions.postcss}`;
|
|
887
|
+
pkg.devDependencies['autoprefixer'] = `^${versions.autoprefixer}`;
|
|
316
888
|
}
|
|
317
889
|
|
|
318
|
-
|
|
319
|
-
pkg.devDependencies['typescript'] = '^5.6.0';
|
|
320
|
-
}
|
|
890
|
+
files['package.json'] = JSON.stringify(pkg, null, 2);
|
|
321
891
|
|
|
322
|
-
|
|
892
|
+
// Write all files
|
|
893
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
894
|
+
const fullPath = path.join(targetDir, filePath);
|
|
895
|
+
fs.ensureDirSync(path.dirname(fullPath));
|
|
896
|
+
fs.writeFileSync(fullPath, content);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
323
899
|
|
|
324
|
-
|
|
325
|
-
|
|
900
|
+
/**
|
|
901
|
+
* Main function to get Vite template
|
|
902
|
+
*/
|
|
903
|
+
async function getViteTemplate(projectName, framework, features, targetDir) {
|
|
904
|
+
const ora = require('ora').default;
|
|
905
|
+
const spinner = ora(`Generating ${framework} template with latest dependencies...`).start();
|
|
906
|
+
|
|
907
|
+
try {
|
|
908
|
+
// Ensure target directory exists
|
|
909
|
+
fs.ensureDirSync(targetDir);
|
|
910
|
+
|
|
911
|
+
// Generate template based on framework
|
|
912
|
+
if (framework === 'react') {
|
|
913
|
+
await generateReactTemplate(projectName, features, targetDir);
|
|
914
|
+
} else if (framework === 'vue') {
|
|
915
|
+
await generateVueTemplate(projectName, features, targetDir);
|
|
916
|
+
} else if (framework === 'svelte') {
|
|
917
|
+
await generateSvelteTemplate(projectName, features, targetDir);
|
|
918
|
+
} else if (framework === 'vanilla') {
|
|
919
|
+
await generateVanillaTemplate(projectName, features, targetDir);
|
|
920
|
+
} else {
|
|
921
|
+
throw new Error(`Unsupported framework: ${framework}`);
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
// Generate README
|
|
925
|
+
const readme = `# ${projectName}
|
|
326
926
|
|
|
327
927
|
Created with [gotodev](https://npmjs.com/package/gotodev) ⚡
|
|
328
928
|
|
|
329
|
-
## Framework: ${framework.toUpperCase()}
|
|
929
|
+
## Framework: ${framework.toUpperCase()}${features.typescript ? ' + TypeScript' : ''}${features.tailwind ? ' + Tailwind CSS' : ''}
|
|
330
930
|
|
|
331
|
-
###
|
|
931
|
+
### Latest Dependencies
|
|
932
|
+
- Vite: ${await getLatestVersion('vite')}
|
|
933
|
+
- Framework: ${framework === 'react' ? 'React 19' : framework === 'vue' ? 'Vue 3' : framework === 'svelte' ? 'Svelte 5' : 'Vanilla JS'}
|
|
934
|
+
- Build tool: Rust + Oxc (10-100x faster)
|
|
332
935
|
|
|
333
936
|
### Getting Started
|
|
334
937
|
|
|
@@ -337,18 +940,21 @@ npm install
|
|
|
337
940
|
npm run dev
|
|
338
941
|
\`\`\`
|
|
339
942
|
|
|
340
|
-
|
|
943
|
+
### Features
|
|
944
|
+
${features.typescript ? '- TypeScript support\n' : ''}${features.tailwind ? '- Tailwind CSS styling\n' : ''}${features.router ? '- Vue Router\n' : ''}${features.pinia ? '- Pinia state management\n' : ''}
|
|
341
945
|
|
|
946
|
+
### Why gotodev?
|
|
342
947
|
- ⚡ **Lightning-fast**: Powered by Rust + Oxc
|
|
343
948
|
- 🎨 **Modern**: Latest Vite + framework versions
|
|
344
949
|
- 🔥 **Hot HMR**: Instant updates
|
|
950
|
+
- 🛡️ **Secure**: SSRF and path traversal protection
|
|
345
951
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
952
|
+
Built with gotodev v${require('./package.json').version}`;
|
|
953
|
+
|
|
954
|
+
fs.writeFileSync(path.join(targetDir, 'README.md'), readme);
|
|
955
|
+
|
|
956
|
+
// Generate .gitignore
|
|
957
|
+
const gitignore = `node_modules/
|
|
352
958
|
dist/
|
|
353
959
|
build/
|
|
354
960
|
*.local
|
|
@@ -367,7 +973,16 @@ Thumbs.db
|
|
|
367
973
|
.nuxt
|
|
368
974
|
.storybook-out
|
|
369
975
|
tmp/
|
|
370
|
-
temp
|
|
976
|
+
temp/`;
|
|
977
|
+
|
|
978
|
+
fs.writeFileSync(path.join(targetDir, '.gitignore'), gitignore);
|
|
979
|
+
|
|
980
|
+
spinner.succeed(`✅ Created ${framework} project with latest dependencies!`);
|
|
981
|
+
|
|
982
|
+
} catch (error) {
|
|
983
|
+
spinner.fail(`❌ Failed to create template: ${error.message}`);
|
|
984
|
+
throw error;
|
|
985
|
+
}
|
|
371
986
|
}
|
|
372
987
|
|
|
373
|
-
module.exports = { getViteTemplate };
|
|
988
|
+
module.exports = { getViteTemplate };
|