create-what 0.1.1 → 0.1.2
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/index.js +254 -22
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// create-what: npm create what@latest my-app
|
|
4
|
-
// Scaffolds a new What
|
|
4
|
+
// Scaffolds a new What Framework project with sensible defaults.
|
|
5
|
+
//
|
|
6
|
+
// Usage:
|
|
7
|
+
// npm create what@latest my-app # JSX project (default)
|
|
8
|
+
// npm create what@latest my-app --no-jsx # vanilla h() project
|
|
9
|
+
// npm create what@latest my-app --vanilla # vanilla h() project
|
|
5
10
|
|
|
6
11
|
import { mkdirSync, writeFileSync, existsSync } from 'fs';
|
|
7
12
|
import { join } from 'path';
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
const
|
|
14
|
+
// --- Parse CLI arguments ---
|
|
15
|
+
const args = process.argv.slice(2);
|
|
16
|
+
const flags = args.filter(a => a.startsWith('-'));
|
|
17
|
+
const positional = args.filter(a => !a.startsWith('-'));
|
|
18
|
+
|
|
19
|
+
const name = positional[0] || 'my-what-app';
|
|
20
|
+
const template = positional[1] || 'default'; // default | minimal | full
|
|
21
|
+
|
|
22
|
+
// JSX is the default; opt out with --no-jsx or --vanilla
|
|
23
|
+
const useJSX = !flags.includes('--no-jsx') && !flags.includes('--vanilla');
|
|
24
|
+
|
|
11
25
|
const cwd = process.cwd();
|
|
12
26
|
const root = join(cwd, name);
|
|
13
27
|
|
|
@@ -16,7 +30,11 @@ if (existsSync(root)) {
|
|
|
16
30
|
process.exit(1);
|
|
17
31
|
}
|
|
18
32
|
|
|
19
|
-
|
|
33
|
+
const mode = useJSX ? 'JSX' : 'vanilla (h())';
|
|
34
|
+
console.log(`\n Creating ${name} with template: ${template} (${mode})\n`);
|
|
35
|
+
|
|
36
|
+
// File extension helper
|
|
37
|
+
const ext = useJSX ? '.jsx' : '.js';
|
|
20
38
|
|
|
21
39
|
// Create directory structure
|
|
22
40
|
const dirs = [
|
|
@@ -29,22 +47,48 @@ const dirs = [
|
|
|
29
47
|
dirs.forEach(d => mkdirSync(join(root, d), { recursive: true }));
|
|
30
48
|
|
|
31
49
|
// --- package.json ---
|
|
32
|
-
|
|
50
|
+
const pkgDeps = {
|
|
51
|
+
'what-framework': '^0.1.0',
|
|
52
|
+
'what-framework-cli': '^0.1.0',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const pkgDevDeps = useJSX
|
|
56
|
+
? {
|
|
57
|
+
'what-compiler': '^0.1.0',
|
|
58
|
+
'vite': '^5.0.0',
|
|
59
|
+
}
|
|
60
|
+
: {};
|
|
61
|
+
|
|
62
|
+
const pkg = {
|
|
33
63
|
name,
|
|
34
64
|
private: true,
|
|
35
65
|
version: '0.0.1',
|
|
36
66
|
type: 'module',
|
|
37
67
|
scripts: {
|
|
38
|
-
dev: 'what dev',
|
|
39
|
-
build: 'what build',
|
|
40
|
-
preview: 'what preview',
|
|
68
|
+
dev: useJSX ? 'vite' : 'what dev',
|
|
69
|
+
build: useJSX ? 'vite build' : 'what build',
|
|
70
|
+
preview: useJSX ? 'vite preview' : 'what preview',
|
|
41
71
|
generate: 'what generate',
|
|
42
72
|
},
|
|
43
|
-
dependencies:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
73
|
+
dependencies: pkgDeps,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
if (Object.keys(pkgDevDeps).length > 0) {
|
|
77
|
+
pkg.devDependencies = pkgDevDeps;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
writeFileSync(join(root, 'package.json'), JSON.stringify(pkg, null, 2) + '\n');
|
|
81
|
+
|
|
82
|
+
// --- vite.config.js (JSX only) ---
|
|
83
|
+
if (useJSX) {
|
|
84
|
+
writeFileSync(join(root, 'vite.config.js'), `import { defineConfig } from 'vite';
|
|
85
|
+
import what from 'what-compiler/vite';
|
|
86
|
+
|
|
87
|
+
export default defineConfig({
|
|
88
|
+
plugins: [what()],
|
|
89
|
+
});
|
|
90
|
+
`);
|
|
91
|
+
}
|
|
48
92
|
|
|
49
93
|
// --- what.config.js ---
|
|
50
94
|
writeFileSync(join(root, 'what.config.js'), `// What Framework Configuration
|
|
@@ -64,6 +108,7 @@ export default {
|
|
|
64
108
|
`);
|
|
65
109
|
|
|
66
110
|
// --- src/index.html ---
|
|
111
|
+
const appScript = useJSX ? '/app.jsx' : '/app.js';
|
|
67
112
|
writeFileSync(join(root, 'src/index.html'), `<!DOCTYPE html>
|
|
68
113
|
<html lang="en">
|
|
69
114
|
<head>
|
|
@@ -74,14 +119,128 @@ writeFileSync(join(root, 'src/index.html'), `<!DOCTYPE html>
|
|
|
74
119
|
</head>
|
|
75
120
|
<body>
|
|
76
121
|
<div id="app"></div>
|
|
77
|
-
<script type="module" src="
|
|
122
|
+
<script type="module" src="${appScript}"></script>
|
|
78
123
|
</body>
|
|
79
124
|
</html>
|
|
80
125
|
`);
|
|
81
126
|
|
|
127
|
+
// ==========================================================================
|
|
128
|
+
// JSX templates
|
|
129
|
+
// ==========================================================================
|
|
130
|
+
if (useJSX) {
|
|
131
|
+
|
|
132
|
+
// --- src/app.jsx ---
|
|
133
|
+
writeFileSync(join(root, 'src/app.jsx'), `import { mount, signal } from 'what-framework';
|
|
134
|
+
import { Router, Link, defineRoutes } from 'what-framework/router';
|
|
135
|
+
import { Layout } from './layouts/main.jsx';
|
|
136
|
+
import { Home } from './pages/index.jsx';
|
|
137
|
+
import { About } from './pages/about.jsx';
|
|
138
|
+
|
|
139
|
+
const routes = defineRoutes({
|
|
140
|
+
'/': { component: Home, layout: Layout },
|
|
141
|
+
'/about': { component: About, layout: Layout },
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
function App() {
|
|
145
|
+
return <Router routes={routes} fallback={NotFound} />;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function NotFound() {
|
|
149
|
+
return (
|
|
150
|
+
<div class="not-found">
|
|
151
|
+
<h1>404</h1>
|
|
152
|
+
<p>Page not found</p>
|
|
153
|
+
<Link href="/">Go home</Link>
|
|
154
|
+
</div>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
mount(<App />, '#app');
|
|
159
|
+
`);
|
|
160
|
+
|
|
161
|
+
// --- src/layouts/main.jsx ---
|
|
162
|
+
writeFileSync(join(root, 'src/layouts/main.jsx'), `import { Nav } from '../components/nav.jsx';
|
|
163
|
+
|
|
164
|
+
export function Layout({ children }) {
|
|
165
|
+
return (
|
|
166
|
+
<div class="layout">
|
|
167
|
+
<Nav />
|
|
168
|
+
<main class="content">{children}</main>
|
|
169
|
+
<footer class="footer">
|
|
170
|
+
<p>Built with What</p>
|
|
171
|
+
</footer>
|
|
172
|
+
</div>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
`);
|
|
176
|
+
|
|
177
|
+
// --- src/components/nav.jsx ---
|
|
178
|
+
writeFileSync(join(root, 'src/components/nav.jsx'), `import { Link } from 'what-framework/router';
|
|
179
|
+
|
|
180
|
+
export function Nav() {
|
|
181
|
+
return (
|
|
182
|
+
<nav class="nav">
|
|
183
|
+
<a href="/" class="nav-logo">What</a>
|
|
184
|
+
<div class="nav-links">
|
|
185
|
+
<Link href="/">Home</Link>
|
|
186
|
+
<Link href="/about">About</Link>
|
|
187
|
+
</div>
|
|
188
|
+
</nav>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
`);
|
|
192
|
+
|
|
193
|
+
// --- src/pages/index.jsx ---
|
|
194
|
+
writeFileSync(join(root, 'src/pages/index.jsx'), `import { useState } from 'what-framework';
|
|
195
|
+
|
|
196
|
+
export function Home() {
|
|
197
|
+
const [count, setCount] = useState(0);
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div class="page home">
|
|
201
|
+
<h1>Welcome to What</h1>
|
|
202
|
+
<p>The closest framework to vanilla JS.</p>
|
|
203
|
+
<div class="counter">
|
|
204
|
+
<button onClick={() => setCount(c => c - 1)}>-</button>
|
|
205
|
+
<span class="count">{count}</span>
|
|
206
|
+
<button onClick={() => setCount(c => c + 1)}>+</button>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export default Home;
|
|
213
|
+
`);
|
|
214
|
+
|
|
215
|
+
// --- src/pages/about.jsx ---
|
|
216
|
+
writeFileSync(join(root, 'src/pages/about.jsx'), `export function About() {
|
|
217
|
+
return (
|
|
218
|
+
<div class="page about">
|
|
219
|
+
<h1>About What</h1>
|
|
220
|
+
<p>What is a vanilla JS framework that gives you:</p>
|
|
221
|
+
<ul>
|
|
222
|
+
<li>Fine-grained reactivity (signals)</li>
|
|
223
|
+
<li>Surgical DOM updates (no virtual DOM diffing)</li>
|
|
224
|
+
<li>Islands architecture (ship zero JS by default)</li>
|
|
225
|
+
<li>File-based routing</li>
|
|
226
|
+
<li>SSR + SSG + client rendering</li>
|
|
227
|
+
<li>React-familiar hooks API</li>
|
|
228
|
+
</ul>
|
|
229
|
+
</div>
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export default About;
|
|
234
|
+
`);
|
|
235
|
+
|
|
236
|
+
} else {
|
|
237
|
+
// ==========================================================================
|
|
238
|
+
// Vanilla h() templates
|
|
239
|
+
// ==========================================================================
|
|
240
|
+
|
|
82
241
|
// --- src/app.js ---
|
|
83
|
-
writeFileSync(join(root, 'src/app.js'), `import { h, mount, signal } from 'what';
|
|
84
|
-
import { Router, Link, defineRoutes } from 'what/router';
|
|
242
|
+
writeFileSync(join(root, 'src/app.js'), `import { h, mount, signal } from 'what-framework';
|
|
243
|
+
import { Router, Link, defineRoutes } from 'what-framework/router';
|
|
85
244
|
import { Layout } from './layouts/main.js';
|
|
86
245
|
import { Home } from './pages/index.js';
|
|
87
246
|
import { About } from './pages/about.js';
|
|
@@ -107,8 +266,8 @@ mount(h(App), '#app');
|
|
|
107
266
|
`);
|
|
108
267
|
|
|
109
268
|
// --- src/layouts/main.js ---
|
|
110
|
-
writeFileSync(join(root, 'src/layouts/main.js'), `import { h } from 'what';
|
|
111
|
-
import { Link } from 'what/router';
|
|
269
|
+
writeFileSync(join(root, 'src/layouts/main.js'), `import { h } from 'what-framework';
|
|
270
|
+
import { Link } from 'what-framework/router';
|
|
112
271
|
import { Nav } from '../components/nav.js';
|
|
113
272
|
|
|
114
273
|
export function Layout({ children }) {
|
|
@@ -123,8 +282,8 @@ export function Layout({ children }) {
|
|
|
123
282
|
`);
|
|
124
283
|
|
|
125
284
|
// --- src/components/nav.js ---
|
|
126
|
-
writeFileSync(join(root, 'src/components/nav.js'), `import { h } from 'what';
|
|
127
|
-
import { Link } from 'what/router';
|
|
285
|
+
writeFileSync(join(root, 'src/components/nav.js'), `import { h } from 'what-framework';
|
|
286
|
+
import { Link } from 'what-framework/router';
|
|
128
287
|
|
|
129
288
|
export function Nav() {
|
|
130
289
|
return h('nav', { class: 'nav' },
|
|
@@ -138,7 +297,7 @@ export function Nav() {
|
|
|
138
297
|
`);
|
|
139
298
|
|
|
140
299
|
// --- src/pages/index.js ---
|
|
141
|
-
writeFileSync(join(root, 'src/pages/index.js'), `import { h, useState } from 'what';
|
|
300
|
+
writeFileSync(join(root, 'src/pages/index.js'), `import { h, useState } from 'what-framework';
|
|
142
301
|
|
|
143
302
|
export function Home() {
|
|
144
303
|
const [count, setCount] = useState(0);
|
|
@@ -158,7 +317,7 @@ export default Home;
|
|
|
158
317
|
`);
|
|
159
318
|
|
|
160
319
|
// --- src/pages/about.js ---
|
|
161
|
-
writeFileSync(join(root, 'src/pages/about.js'), `import { h } from 'what';
|
|
320
|
+
writeFileSync(join(root, 'src/pages/about.js'), `import { h } from 'what-framework';
|
|
162
321
|
|
|
163
322
|
export function About() {
|
|
164
323
|
return h('div', { class: 'page about' },
|
|
@@ -178,6 +337,8 @@ export function About() {
|
|
|
178
337
|
export default About;
|
|
179
338
|
`);
|
|
180
339
|
|
|
340
|
+
} // end vanilla mode
|
|
341
|
+
|
|
181
342
|
// --- public/styles.css ---
|
|
182
343
|
writeFileSync(join(root, 'public/styles.css'), `* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
183
344
|
|
|
@@ -222,7 +383,78 @@ li { margin-bottom: 0.25rem; }
|
|
|
222
383
|
.not-found h1 { font-size: 6rem; color: #ddd; }
|
|
223
384
|
`);
|
|
224
385
|
|
|
386
|
+
// --- README.md ---
|
|
387
|
+
const jsxNote = useJSX
|
|
388
|
+
? `This project uses **JSX** syntax, compiled by \`what-compiler\` via the Vite plugin.
|
|
389
|
+
|
|
390
|
+
To switch to vanilla \`h()\` calls instead, re-create with:
|
|
391
|
+
\`\`\`
|
|
392
|
+
npm create what@latest ${name} --vanilla
|
|
393
|
+
\`\`\``
|
|
394
|
+
: `This project uses the vanilla **h()** API for building components.
|
|
395
|
+
|
|
396
|
+
To use JSX syntax instead (recommended), re-create with:
|
|
397
|
+
\`\`\`
|
|
398
|
+
npm create what@latest ${name}
|
|
399
|
+
\`\`\``;
|
|
400
|
+
|
|
401
|
+
writeFileSync(join(root, 'README.md'), `# ${name}
|
|
402
|
+
|
|
403
|
+
A [What Framework](https://github.com/aspect/what-fw) project.
|
|
404
|
+
|
|
405
|
+
## Authoring Mode
|
|
406
|
+
|
|
407
|
+
${jsxNote}
|
|
408
|
+
|
|
409
|
+
## Getting Started
|
|
410
|
+
|
|
411
|
+
\`\`\`bash
|
|
412
|
+
cd ${name}
|
|
413
|
+
npm install
|
|
414
|
+
npm run dev
|
|
415
|
+
\`\`\`
|
|
416
|
+
|
|
417
|
+
## Scripts
|
|
418
|
+
|
|
419
|
+
| Command | Description |
|
|
420
|
+
| --------------- | ------------------------------------ |
|
|
421
|
+
| \`npm run dev\` | Start development server |
|
|
422
|
+
| \`npm run build\` | Build for production |
|
|
423
|
+
| \`npm run preview\`| Preview production build |
|
|
424
|
+
| \`npm run generate\`| Static site generation (SSG) |
|
|
425
|
+
|
|
426
|
+
## Project Structure
|
|
427
|
+
|
|
428
|
+
\`\`\`
|
|
429
|
+
${name}/
|
|
430
|
+
src/
|
|
431
|
+
pages/ # File-based routes
|
|
432
|
+
components/ # Shared components
|
|
433
|
+
layouts/ # Page layouts
|
|
434
|
+
islands/ # Hydrated interactive islands
|
|
435
|
+
${useJSX ? ' app.jsx # App entry point (JSX)' : ' app.js # App entry point'}
|
|
436
|
+
index.html # HTML shell
|
|
437
|
+
public/ # Static assets
|
|
438
|
+
what.config.js # Framework configuration
|
|
439
|
+
${useJSX ? ' vite.config.js # Vite + what-compiler plugin\n' : ''} package.json
|
|
440
|
+
\`\`\`
|
|
441
|
+
|
|
442
|
+
## Learn More
|
|
443
|
+
|
|
444
|
+
- [What Framework docs](https://github.com/aspect/what-fw)
|
|
445
|
+
- JSX authoring: uses \`what-compiler\` to transform JSX to optimized DOM calls
|
|
446
|
+
- Vanilla authoring: use \`h(tag, props, ...children)\` directly -- zero build step needed
|
|
447
|
+
`);
|
|
448
|
+
|
|
449
|
+
// --- Done ---
|
|
225
450
|
console.log(` Done! Next steps:\n`);
|
|
226
451
|
console.log(` cd ${name}`);
|
|
227
452
|
console.log(` npm install`);
|
|
228
453
|
console.log(` npm run dev\n`);
|
|
454
|
+
|
|
455
|
+
if (useJSX) {
|
|
456
|
+
console.log(` JSX mode enabled. Components use .jsx extensions.`);
|
|
457
|
+
console.log(` The what-compiler Vite plugin handles JSX transformation.\n`);
|
|
458
|
+
} else {
|
|
459
|
+
console.log(` Vanilla mode. Components use h() calls -- no compiler needed.\n`);
|
|
460
|
+
}
|