@stratawp/cli 0.2.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/dist/create.d.ts +2 -0
- package/dist/create.js +386 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +983 -0
- package/package.json +67 -0
package/dist/create.d.ts
ADDED
package/dist/create.js
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/create.ts
|
|
4
|
+
import prompts from "prompts";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import ora from "ora";
|
|
7
|
+
import { execa } from "execa";
|
|
8
|
+
import fs from "fs-extra";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import validatePackageName from "validate-npm-package-name";
|
|
11
|
+
async function main() {
|
|
12
|
+
console.log(chalk.bold.cyan("\n\u26A1 Create StrataWP Theme\n"));
|
|
13
|
+
const response = await prompts([
|
|
14
|
+
{
|
|
15
|
+
type: "text",
|
|
16
|
+
name: "name",
|
|
17
|
+
message: "Theme name:",
|
|
18
|
+
initial: "My Awesome Theme"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: "text",
|
|
22
|
+
name: "slug",
|
|
23
|
+
message: "Theme slug (directory name):",
|
|
24
|
+
initial: (prev) => prev.toLowerCase().replace(/\s+/g, "-"),
|
|
25
|
+
validate: (value) => {
|
|
26
|
+
const validation = validatePackageName(value);
|
|
27
|
+
if (!validation.validForNewPackages) {
|
|
28
|
+
return validation.errors?.[0] || "Invalid package name";
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
type: "text",
|
|
35
|
+
name: "description",
|
|
36
|
+
message: "Description:",
|
|
37
|
+
initial: "A theme built with StrataWP"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
name: "author",
|
|
42
|
+
message: "Author name:"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: "select",
|
|
46
|
+
name: "cssFramework",
|
|
47
|
+
message: "CSS Framework:",
|
|
48
|
+
choices: [
|
|
49
|
+
{ title: "Vanilla CSS (Custom Properties)", value: "vanilla" },
|
|
50
|
+
{ title: "Tailwind CSS", value: "tailwind" },
|
|
51
|
+
{ title: "UnoCSS (Recommended)", value: "unocss" },
|
|
52
|
+
{ title: "Panda CSS (Type-safe)", value: "panda" }
|
|
53
|
+
],
|
|
54
|
+
initial: 2
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "confirm",
|
|
58
|
+
name: "typescript",
|
|
59
|
+
message: "Use TypeScript?",
|
|
60
|
+
initial: true
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
type: "confirm",
|
|
64
|
+
name: "testing",
|
|
65
|
+
message: "Include testing setup?",
|
|
66
|
+
initial: true
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
type: "confirm",
|
|
70
|
+
name: "ai",
|
|
71
|
+
message: "Enable AI-powered features?",
|
|
72
|
+
initial: false
|
|
73
|
+
}
|
|
74
|
+
]);
|
|
75
|
+
if (!response.slug) {
|
|
76
|
+
console.log(chalk.red("\n\u2716 Theme creation cancelled\n"));
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
const config = response;
|
|
80
|
+
await createTheme(config);
|
|
81
|
+
}
|
|
82
|
+
async function createTheme(config) {
|
|
83
|
+
const spinner = ora("Creating theme...").start();
|
|
84
|
+
try {
|
|
85
|
+
const themePath = path.resolve(process.cwd(), config.slug);
|
|
86
|
+
if (await fs.pathExists(themePath)) {
|
|
87
|
+
spinner.fail(`Directory ${config.slug} already exists`);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
await fs.ensureDir(themePath);
|
|
91
|
+
spinner.text = "Copying template files...";
|
|
92
|
+
await createBasicStructure(themePath, config);
|
|
93
|
+
spinner.text = "Installing dependencies...";
|
|
94
|
+
await execa("pnpm", ["install"], { cwd: themePath });
|
|
95
|
+
spinner.succeed(chalk.green("Theme created successfully!"));
|
|
96
|
+
console.log(chalk.cyan("\n\u{1F4E6} Next steps:\n"));
|
|
97
|
+
console.log(` cd ${config.slug}`);
|
|
98
|
+
console.log(" pnpm dev");
|
|
99
|
+
console.log();
|
|
100
|
+
} catch (error) {
|
|
101
|
+
spinner.fail("Failed to create theme");
|
|
102
|
+
console.error(error);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async function createBasicStructure(themePath, config) {
|
|
107
|
+
const packageJson = {
|
|
108
|
+
name: config.slug,
|
|
109
|
+
version: "1.0.0",
|
|
110
|
+
description: config.description,
|
|
111
|
+
author: config.author,
|
|
112
|
+
license: "GPL-3.0-or-later",
|
|
113
|
+
type: "module",
|
|
114
|
+
scripts: {
|
|
115
|
+
dev: "vite",
|
|
116
|
+
build: "vite build",
|
|
117
|
+
preview: "vite preview"
|
|
118
|
+
},
|
|
119
|
+
dependencies: {
|
|
120
|
+
"@wordpress/block-editor": "^12.19.0",
|
|
121
|
+
"@wordpress/blocks": "^12.28.0",
|
|
122
|
+
"@wordpress/components": "^27.0.0",
|
|
123
|
+
"@wordpress/element": "^5.28.0",
|
|
124
|
+
"@wordpress/i18n": "^4.51.0"
|
|
125
|
+
},
|
|
126
|
+
devDependencies: {
|
|
127
|
+
"@stratawp/cli": "^0.2.0",
|
|
128
|
+
"@stratawp/vite-plugin": "^0.2.0",
|
|
129
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
130
|
+
vite: "^5.0.10",
|
|
131
|
+
typescript: config.typescript ? "^5.3.3" : void 0
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
await fs.writeJson(path.join(themePath, "package.json"), packageJson, { spaces: 2 });
|
|
135
|
+
const styleCSS = `/*
|
|
136
|
+
Theme Name: ${config.name}
|
|
137
|
+
Theme URI: https://example.com
|
|
138
|
+
Author: ${config.author}
|
|
139
|
+
Description: ${config.description}
|
|
140
|
+
Version: 1.0.0
|
|
141
|
+
License: GPL-3.0-or-later
|
|
142
|
+
Text Domain: ${config.slug}
|
|
143
|
+
|
|
144
|
+
Built with \u26A1 StrataWP
|
|
145
|
+
*/`;
|
|
146
|
+
await fs.writeFile(path.join(themePath, "style.css"), styleCSS);
|
|
147
|
+
const readme = `# ${config.name}
|
|
148
|
+
|
|
149
|
+
${config.description}
|
|
150
|
+
|
|
151
|
+
## Development
|
|
152
|
+
|
|
153
|
+
\`\`\`bash
|
|
154
|
+
pnpm dev
|
|
155
|
+
\`\`\`
|
|
156
|
+
|
|
157
|
+
## Build
|
|
158
|
+
|
|
159
|
+
\`\`\`bash
|
|
160
|
+
pnpm build
|
|
161
|
+
\`\`\`
|
|
162
|
+
|
|
163
|
+
Built with [StrataWP](https://github.com/JonImmsWordpressDev/StrataWP)
|
|
164
|
+
`;
|
|
165
|
+
await fs.writeFile(path.join(themePath, "README.md"), readme);
|
|
166
|
+
const viteConfig = `import { defineConfig } from 'vite'
|
|
167
|
+
import react from '@vitejs/plugin-react'
|
|
168
|
+
import { strataWP } from '@stratawp/vite-plugin'
|
|
169
|
+
|
|
170
|
+
export default defineConfig({
|
|
171
|
+
plugins: [
|
|
172
|
+
react(),
|
|
173
|
+
strataWP({
|
|
174
|
+
blocks: {
|
|
175
|
+
dir: 'src/blocks',
|
|
176
|
+
autoRegister: true,
|
|
177
|
+
namespace: '${config.slug}',
|
|
178
|
+
},
|
|
179
|
+
${config.cssFramework !== "vanilla" ? `designSystem: {
|
|
180
|
+
enabled: true,
|
|
181
|
+
framework: '${config.cssFramework === "unocss" ? "unocss" : config.cssFramework === "tailwind" ? "tailwind" : "none"}',
|
|
182
|
+
wordpressPresets: true,
|
|
183
|
+
},` : ""}
|
|
184
|
+
performance: {
|
|
185
|
+
criticalCSS: { enabled: true },
|
|
186
|
+
lazyLoading: { enabled: true },
|
|
187
|
+
preload: { enabled: true },
|
|
188
|
+
},
|
|
189
|
+
phpHmr: {
|
|
190
|
+
enabled: true,
|
|
191
|
+
watch: ['**/*.php', 'theme.json', 'templates/**/*'],
|
|
192
|
+
},
|
|
193
|
+
manifest: {
|
|
194
|
+
enabled: true,
|
|
195
|
+
wordpress: true,
|
|
196
|
+
},
|
|
197
|
+
}),
|
|
198
|
+
],
|
|
199
|
+
build: {
|
|
200
|
+
rollupOptions: {
|
|
201
|
+
input: {
|
|
202
|
+
main: './src/js/main.ts',
|
|
203
|
+
editor: './src/js/editor.ts',
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
})`;
|
|
208
|
+
await fs.writeFile(path.join(themePath, "vite.config.ts"), viteConfig);
|
|
209
|
+
const functionsPhp = `<?php
|
|
210
|
+
/**
|
|
211
|
+
* Theme functions
|
|
212
|
+
*/
|
|
213
|
+
|
|
214
|
+
if (!defined('ABSPATH')) {
|
|
215
|
+
exit;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Load Vite assets
|
|
219
|
+
require_once get_template_directory() . '/inc/vite-assets.php';
|
|
220
|
+
`;
|
|
221
|
+
await fs.writeFile(path.join(themePath, "functions.php"), functionsPhp);
|
|
222
|
+
const themeJson = {
|
|
223
|
+
$schema: "https://schemas.wp.org/trunk/theme.json",
|
|
224
|
+
version: 2,
|
|
225
|
+
settings: {
|
|
226
|
+
appearanceTools: true,
|
|
227
|
+
layout: {
|
|
228
|
+
contentSize: "800px",
|
|
229
|
+
wideSize: "1200px"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
await fs.writeJson(path.join(themePath, "theme.json"), themeJson, { spaces: 2 });
|
|
234
|
+
await fs.ensureDir(path.join(themePath, "src"));
|
|
235
|
+
await fs.ensureDir(path.join(themePath, "src/css"));
|
|
236
|
+
await fs.ensureDir(path.join(themePath, "src/js"));
|
|
237
|
+
await fs.ensureDir(path.join(themePath, "src/blocks"));
|
|
238
|
+
await fs.ensureDir(path.join(themePath, "inc"));
|
|
239
|
+
await fs.ensureDir(path.join(themePath, "templates"));
|
|
240
|
+
await fs.ensureDir(path.join(themePath, "parts"));
|
|
241
|
+
await fs.writeFile(
|
|
242
|
+
path.join(themePath, "src/js/main.ts"),
|
|
243
|
+
`import '../css/main.css'
|
|
244
|
+
|
|
245
|
+
console.log('${config.name} loaded')
|
|
246
|
+
`
|
|
247
|
+
);
|
|
248
|
+
await fs.writeFile(
|
|
249
|
+
path.join(themePath, "src/js/editor.ts"),
|
|
250
|
+
`import '../css/editor.css'
|
|
251
|
+
`
|
|
252
|
+
);
|
|
253
|
+
await fs.writeFile(
|
|
254
|
+
path.join(themePath, "src/css/main.css"),
|
|
255
|
+
`/* Main stylesheet for ${config.name} */
|
|
256
|
+
|
|
257
|
+
body {
|
|
258
|
+
font-family: system-ui, sans-serif;
|
|
259
|
+
}
|
|
260
|
+
`
|
|
261
|
+
);
|
|
262
|
+
await fs.writeFile(
|
|
263
|
+
path.join(themePath, "src/css/editor.css"),
|
|
264
|
+
`/* Editor stylesheet */
|
|
265
|
+
`
|
|
266
|
+
);
|
|
267
|
+
const viteAssetsPhp = `<?php
|
|
268
|
+
/**
|
|
269
|
+
* Vite asset loading helper
|
|
270
|
+
*/
|
|
271
|
+
|
|
272
|
+
function load_vite_assets() {
|
|
273
|
+
$manifest_path = get_template_directory() . '/dist/.vite/manifest.json';
|
|
274
|
+
|
|
275
|
+
if (!file_exists($manifest_path)) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
$manifest = json_decode(file_get_contents($manifest_path), true);
|
|
280
|
+
|
|
281
|
+
if (isset($manifest['src/js/main.ts'])) {
|
|
282
|
+
wp_enqueue_script(
|
|
283
|
+
'${config.slug}-main',
|
|
284
|
+
get_template_directory_uri() . '/dist/' . $manifest['src/js/main.ts']['file'],
|
|
285
|
+
[],
|
|
286
|
+
null,
|
|
287
|
+
true
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
if (isset($manifest['src/js/main.ts']['css'])) {
|
|
291
|
+
foreach ($manifest['src/js/main.ts']['css'] as $css) {
|
|
292
|
+
wp_enqueue_style(
|
|
293
|
+
'${config.slug}-main-css',
|
|
294
|
+
get_template_directory_uri() . '/dist/' . $css,
|
|
295
|
+
[],
|
|
296
|
+
null
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
add_action('wp_enqueue_scripts', 'load_vite_assets');
|
|
304
|
+
`;
|
|
305
|
+
await fs.writeFile(path.join(themePath, "inc/vite-assets.php"), viteAssetsPhp);
|
|
306
|
+
const indexTemplate = `<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
|
|
307
|
+
|
|
308
|
+
<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
|
|
309
|
+
<main class="wp-block-group">
|
|
310
|
+
<!-- wp:query {"queryId":0,"query":{"perPage":10,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true}} -->
|
|
311
|
+
<div class="wp-block-query">
|
|
312
|
+
<!-- wp:post-template -->
|
|
313
|
+
<!-- wp:post-title {"isLink":true} /-->
|
|
314
|
+
<!-- wp:post-date /-->
|
|
315
|
+
<!-- wp:post-excerpt /-->
|
|
316
|
+
<!-- /wp:post-template -->
|
|
317
|
+
|
|
318
|
+
<!-- wp:query-pagination -->
|
|
319
|
+
<!-- wp:query-pagination-previous /-->
|
|
320
|
+
<!-- wp:query-pagination-numbers /-->
|
|
321
|
+
<!-- wp:query-pagination-next /-->
|
|
322
|
+
<!-- /wp:query-pagination -->
|
|
323
|
+
|
|
324
|
+
<!-- wp:query-no-results -->
|
|
325
|
+
<!-- wp:paragraph -->
|
|
326
|
+
<p>No posts found.</p>
|
|
327
|
+
<!-- /wp:paragraph -->
|
|
328
|
+
<!-- /wp:query-no-results -->
|
|
329
|
+
</div>
|
|
330
|
+
<!-- /wp:query -->
|
|
331
|
+
</main>
|
|
332
|
+
<!-- /wp:group -->
|
|
333
|
+
|
|
334
|
+
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->`;
|
|
335
|
+
await fs.writeFile(path.join(themePath, "templates/index.html"), indexTemplate);
|
|
336
|
+
const headerTemplate = `<!-- wp:group {"tagName":"header","style":{"spacing":{"padding":{"top":"2rem","bottom":"2rem"}}},"layout":{"type":"constrained"}} -->
|
|
337
|
+
<header class="wp-block-group" style="padding-top:2rem;padding-bottom:2rem">
|
|
338
|
+
<!-- wp:group {"layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"space-between"}} -->
|
|
339
|
+
<div class="wp-block-group">
|
|
340
|
+
<!-- wp:site-title /-->
|
|
341
|
+
<!-- wp:navigation /-->
|
|
342
|
+
</div>
|
|
343
|
+
<!-- /wp:group -->
|
|
344
|
+
</header>
|
|
345
|
+
<!-- /wp:group -->`;
|
|
346
|
+
await fs.writeFile(path.join(themePath, "parts/header.html"), headerTemplate);
|
|
347
|
+
const footerTemplate = `<!-- wp:group {"tagName":"footer","style":{"spacing":{"padding":{"top":"2rem","bottom":"2rem"}}},"layout":{"type":"constrained"}} -->
|
|
348
|
+
<footer class="wp-block-group" style="padding-top:2rem;padding-bottom:2rem">
|
|
349
|
+
<!-- wp:group {"layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"center"}} -->
|
|
350
|
+
<div class="wp-block-group">
|
|
351
|
+
<!-- wp:paragraph -->
|
|
352
|
+
<p>Built with StrataWP</p>
|
|
353
|
+
<!-- /wp:paragraph -->
|
|
354
|
+
</div>
|
|
355
|
+
<!-- /wp:group -->
|
|
356
|
+
</footer>
|
|
357
|
+
<!-- /wp:group -->`;
|
|
358
|
+
await fs.writeFile(path.join(themePath, "parts/footer.html"), footerTemplate);
|
|
359
|
+
const singleTemplate = `<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
|
|
360
|
+
|
|
361
|
+
<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
|
|
362
|
+
<main class="wp-block-group">
|
|
363
|
+
<!-- wp:post-title /-->
|
|
364
|
+
<!-- wp:post-featured-image /-->
|
|
365
|
+
<!-- wp:post-content /-->
|
|
366
|
+
</main>
|
|
367
|
+
<!-- /wp:group -->
|
|
368
|
+
|
|
369
|
+
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->`;
|
|
370
|
+
await fs.writeFile(path.join(themePath, "templates/single.html"), singleTemplate);
|
|
371
|
+
const pageTemplate = `<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
|
|
372
|
+
|
|
373
|
+
<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
|
|
374
|
+
<main class="wp-block-group">
|
|
375
|
+
<!-- wp:post-title /-->
|
|
376
|
+
<!-- wp:post-content /-->
|
|
377
|
+
</main>
|
|
378
|
+
<!-- /wp:group -->
|
|
379
|
+
|
|
380
|
+
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->`;
|
|
381
|
+
await fs.writeFile(path.join(themePath, "templates/page.html"), pageTemplate);
|
|
382
|
+
}
|
|
383
|
+
main().catch((error) => {
|
|
384
|
+
console.error(chalk.red("Error:"), error);
|
|
385
|
+
process.exit(1);
|
|
386
|
+
});
|
package/dist/index.d.ts
ADDED