@stratawp/vite-plugin 0.2.0
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/README.md +114 -0
- package/dist/index.d.ts +356 -0
- package/dist/index.js +1075 -0
- package/package.json +58 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1075 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/plugins/blocks.ts
|
|
9
|
+
import fg from "fast-glob";
|
|
10
|
+
import { readFile, writeFile } from "fs/promises";
|
|
11
|
+
import { join, dirname, relative } from "path";
|
|
12
|
+
import pc from "picocolors";
|
|
13
|
+
function strataWPBlocks(options = {}) {
|
|
14
|
+
const {
|
|
15
|
+
dir = "src/blocks",
|
|
16
|
+
autoRegister = true,
|
|
17
|
+
namespace = "stratawp",
|
|
18
|
+
pattern = "**/block.json"
|
|
19
|
+
} = options;
|
|
20
|
+
let blocks = [];
|
|
21
|
+
let rootDir;
|
|
22
|
+
return {
|
|
23
|
+
name: "stratawp:blocks",
|
|
24
|
+
async configResolved(config) {
|
|
25
|
+
rootDir = config.root;
|
|
26
|
+
},
|
|
27
|
+
async buildStart() {
|
|
28
|
+
const blockJsonFiles = await fg(join(dir, pattern), {
|
|
29
|
+
cwd: rootDir,
|
|
30
|
+
absolute: true
|
|
31
|
+
});
|
|
32
|
+
blocks = [];
|
|
33
|
+
for (const blockJsonPath of blockJsonFiles) {
|
|
34
|
+
try {
|
|
35
|
+
const content = await readFile(blockJsonPath, "utf-8");
|
|
36
|
+
const blockMeta = JSON.parse(content);
|
|
37
|
+
blocks.push({
|
|
38
|
+
...blockMeta,
|
|
39
|
+
_path: relative(rootDir, blockJsonPath),
|
|
40
|
+
_dir: relative(rootDir, dirname(blockJsonPath))
|
|
41
|
+
});
|
|
42
|
+
this.addWatchFile(blockJsonPath);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
this.warn(`Failed to parse block.json at ${blockJsonPath}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (blocks.length > 0) {
|
|
48
|
+
console.log(pc.cyan(`
|
|
49
|
+
\u2692\uFE0F Found ${blocks.length} block(s):`));
|
|
50
|
+
blocks.forEach((block) => {
|
|
51
|
+
console.log(pc.dim(` \u2022 ${block.name}`));
|
|
52
|
+
});
|
|
53
|
+
console.log();
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
async generateBundle() {
|
|
57
|
+
if (!autoRegister || blocks.length === 0) return;
|
|
58
|
+
const phpCode = generateBlockRegistration(blocks, namespace);
|
|
59
|
+
const outputPath = join(rootDir, "inc/blocks-generated.php");
|
|
60
|
+
await writeFile(outputPath, phpCode, "utf-8");
|
|
61
|
+
console.log(pc.green(` \u2713 Generated block registration: inc/blocks-generated.php`));
|
|
62
|
+
},
|
|
63
|
+
// Hot reload blocks during development
|
|
64
|
+
configureServer(server) {
|
|
65
|
+
server.watcher.add(join(rootDir, dir, "**/*.json"));
|
|
66
|
+
server.watcher.on("change", async (file) => {
|
|
67
|
+
if (file.includes("block.json")) {
|
|
68
|
+
console.log(pc.cyan(" \u2692\uFE0F Block configuration changed, reloading..."));
|
|
69
|
+
server.ws.send({ type: "full-reload" });
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function generateBlockRegistration(blocks, _namespace) {
|
|
76
|
+
const blockDirs = blocks.map((block) => {
|
|
77
|
+
const blockData = block;
|
|
78
|
+
return blockData._dir;
|
|
79
|
+
});
|
|
80
|
+
return `<?php
|
|
81
|
+
/**
|
|
82
|
+
* Auto-generated block registration
|
|
83
|
+
*
|
|
84
|
+
* Generated by StrataWP Vite Plugin
|
|
85
|
+
* Do not edit this file manually
|
|
86
|
+
*
|
|
87
|
+
* @package stratawp
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
namespace StrataWP\\Blocks;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Register all blocks
|
|
94
|
+
*/
|
|
95
|
+
function register_blocks() {
|
|
96
|
+
${blockDirs.map((dir) => `register_block_type( get_template_directory() . '/${dir}' );`).join("\n ")}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
add_action( 'init', __NAMESPACE__ . '\\register_blocks' );
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// src/plugins/manifest.ts
|
|
104
|
+
import { writeFile as writeFile2 } from "fs/promises";
|
|
105
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
106
|
+
import { mkdir } from "fs/promises";
|
|
107
|
+
function strataWPManifest(options = {}) {
|
|
108
|
+
const {
|
|
109
|
+
enabled = true,
|
|
110
|
+
output = "dist/.vite/manifest.json",
|
|
111
|
+
wordpress = true
|
|
112
|
+
} = options;
|
|
113
|
+
let rootDir;
|
|
114
|
+
return {
|
|
115
|
+
name: "stratawp:manifest",
|
|
116
|
+
configResolved(config) {
|
|
117
|
+
rootDir = config.root;
|
|
118
|
+
},
|
|
119
|
+
async generateBundle(_, bundle) {
|
|
120
|
+
if (!enabled) return;
|
|
121
|
+
const manifest = {};
|
|
122
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
123
|
+
if (chunk.type === "chunk") {
|
|
124
|
+
const entry = {
|
|
125
|
+
file: fileName,
|
|
126
|
+
src: chunk.facadeModuleId || fileName,
|
|
127
|
+
isEntry: chunk.isEntry
|
|
128
|
+
};
|
|
129
|
+
if (chunk.viteMetadata?.importedCss?.size) {
|
|
130
|
+
entry.css = Array.from(chunk.viteMetadata.importedCss);
|
|
131
|
+
}
|
|
132
|
+
if (wordpress) {
|
|
133
|
+
const wpDeps = extractWordPressDependencies(chunk.code);
|
|
134
|
+
if (wpDeps.length > 0) {
|
|
135
|
+
entry.dependencies = wpDeps;
|
|
136
|
+
}
|
|
137
|
+
entry.version = chunk.fileName.match(/\.([a-f0-9]{8})\./)?.[1] || "1.0.0";
|
|
138
|
+
}
|
|
139
|
+
manifest[chunk.name || fileName] = entry;
|
|
140
|
+
}
|
|
141
|
+
if (chunk.type === "asset") {
|
|
142
|
+
manifest[fileName] = {
|
|
143
|
+
file: fileName
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const outputPath = join2(rootDir, output);
|
|
148
|
+
await mkdir(dirname2(outputPath), { recursive: true });
|
|
149
|
+
await writeFile2(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
150
|
+
console.log(` \u2713 Generated WordPress manifest: ${output}`);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function extractWordPressDependencies(code) {
|
|
155
|
+
const deps = /* @__PURE__ */ new Set();
|
|
156
|
+
const wpPackagePattern = /@wordpress\/([\w-]+)/g;
|
|
157
|
+
let match;
|
|
158
|
+
while ((match = wpPackagePattern.exec(code)) !== null) {
|
|
159
|
+
deps.add(`wp-${match[1]}`);
|
|
160
|
+
}
|
|
161
|
+
if (code.includes("wp.")) {
|
|
162
|
+
if (code.includes("wp.element")) deps.add("wp-element");
|
|
163
|
+
if (code.includes("wp.blocks")) deps.add("wp-blocks");
|
|
164
|
+
if (code.includes("wp.blockEditor")) deps.add("wp-block-editor");
|
|
165
|
+
if (code.includes("wp.components")) deps.add("wp-components");
|
|
166
|
+
if (code.includes("wp.data")) deps.add("wp-data");
|
|
167
|
+
if (code.includes("wp.i18n")) deps.add("wp-i18n");
|
|
168
|
+
}
|
|
169
|
+
return Array.from(deps);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/plugins/php-hmr.ts
|
|
173
|
+
import { watch } from "chokidar";
|
|
174
|
+
import pc2 from "picocolors";
|
|
175
|
+
function strataWPPhpHmr(options = {}) {
|
|
176
|
+
const {
|
|
177
|
+
enabled = true,
|
|
178
|
+
watch: patterns = ["**/*.php", "theme.json"],
|
|
179
|
+
debounce = 100
|
|
180
|
+
} = options;
|
|
181
|
+
let server;
|
|
182
|
+
let watcher = null;
|
|
183
|
+
let timeout = null;
|
|
184
|
+
return {
|
|
185
|
+
name: "stratawp:php-hmr",
|
|
186
|
+
configureServer(devServer) {
|
|
187
|
+
if (!enabled) return;
|
|
188
|
+
server = devServer;
|
|
189
|
+
watcher = watch(patterns, {
|
|
190
|
+
ignored: ["**/node_modules/**", "**/vendor/**", "**/dist/**"],
|
|
191
|
+
persistent: true,
|
|
192
|
+
ignoreInitial: true
|
|
193
|
+
});
|
|
194
|
+
watcher.on("change", (path5) => {
|
|
195
|
+
if (timeout) clearTimeout(timeout);
|
|
196
|
+
timeout = setTimeout(() => {
|
|
197
|
+
console.log(pc2.cyan(`
|
|
198
|
+
\u2692\uFE0F PHP file changed: ${pc2.dim(path5)}`));
|
|
199
|
+
console.log(pc2.cyan(" Reloading page...\n"));
|
|
200
|
+
server.ws.send({
|
|
201
|
+
type: "full-reload",
|
|
202
|
+
path: "*"
|
|
203
|
+
});
|
|
204
|
+
}, debounce);
|
|
205
|
+
});
|
|
206
|
+
watcher.on("add", (path5) => {
|
|
207
|
+
console.log(pc2.green(`
|
|
208
|
+
\u2692\uFE0F New PHP file: ${pc2.dim(path5)}
|
|
209
|
+
`));
|
|
210
|
+
});
|
|
211
|
+
watcher.on("unlink", (path5) => {
|
|
212
|
+
console.log(pc2.yellow(`
|
|
213
|
+
\u2692\uFE0F PHP file removed: ${pc2.dim(path5)}
|
|
214
|
+
`));
|
|
215
|
+
});
|
|
216
|
+
server.httpServer?.once("listening", () => {
|
|
217
|
+
setTimeout(() => {
|
|
218
|
+
console.log(pc2.dim(" \u{1F4DD} Watching PHP files for changes..."));
|
|
219
|
+
}, 150);
|
|
220
|
+
});
|
|
221
|
+
},
|
|
222
|
+
async closeBundle() {
|
|
223
|
+
if (watcher) {
|
|
224
|
+
await watcher.close();
|
|
225
|
+
watcher = null;
|
|
226
|
+
}
|
|
227
|
+
if (timeout) {
|
|
228
|
+
clearTimeout(timeout);
|
|
229
|
+
timeout = null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/plugins/assets.ts
|
|
236
|
+
function strataWPAssets(options = {}) {
|
|
237
|
+
const {
|
|
238
|
+
publicDir = "dist",
|
|
239
|
+
baseUrl
|
|
240
|
+
} = options;
|
|
241
|
+
return {
|
|
242
|
+
name: "stratawp:assets",
|
|
243
|
+
config() {
|
|
244
|
+
return {
|
|
245
|
+
publicDir,
|
|
246
|
+
base: baseUrl || "./",
|
|
247
|
+
build: {
|
|
248
|
+
// Output to WordPress theme structure
|
|
249
|
+
outDir: publicDir,
|
|
250
|
+
emptyOutDir: false,
|
|
251
|
+
// Don't delete PHP files
|
|
252
|
+
// Asset handling
|
|
253
|
+
assetsDir: "",
|
|
254
|
+
assetsInlineLimit: 0,
|
|
255
|
+
// Don't inline assets
|
|
256
|
+
// Sourcemaps for debugging
|
|
257
|
+
sourcemap: true
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/plugins/design-system.ts
|
|
265
|
+
import path from "path";
|
|
266
|
+
import fs from "fs";
|
|
267
|
+
function strataWPDesignSystem(options = {}) {
|
|
268
|
+
const {
|
|
269
|
+
enabled = false,
|
|
270
|
+
framework = "none",
|
|
271
|
+
wordpressPresets = true
|
|
272
|
+
} = options;
|
|
273
|
+
if (!enabled || framework === "none") {
|
|
274
|
+
return {
|
|
275
|
+
name: "stratawp:design-system",
|
|
276
|
+
apply: () => false
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
let config;
|
|
280
|
+
return {
|
|
281
|
+
name: "stratawp:design-system",
|
|
282
|
+
configResolved(resolvedConfig) {
|
|
283
|
+
config = resolvedConfig;
|
|
284
|
+
},
|
|
285
|
+
async config() {
|
|
286
|
+
const root = process.cwd();
|
|
287
|
+
const tailwindConfig = path.join(root, "tailwind.config.js");
|
|
288
|
+
const tailwindConfigTs = path.join(root, "tailwind.config.ts");
|
|
289
|
+
const unoConfig = path.join(root, "uno.config.ts");
|
|
290
|
+
const hasTailwindConfig = fs.existsSync(tailwindConfig) || fs.existsSync(tailwindConfigTs);
|
|
291
|
+
const hasUnoConfig = fs.existsSync(unoConfig);
|
|
292
|
+
if (framework === "tailwind" && !hasTailwindConfig) {
|
|
293
|
+
console.warn(
|
|
294
|
+
"\u26A0\uFE0F Tailwind CSS enabled but no config file found. Run: stratawp design-system:setup tailwind"
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
if (framework === "unocss" && !hasUnoConfig) {
|
|
298
|
+
console.warn(
|
|
299
|
+
"\u26A0\uFE0F UnoCSS enabled but no config file found. Run: stratawp design-system:setup unocss"
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
if (framework === "tailwind") {
|
|
303
|
+
try {
|
|
304
|
+
const tailwindcss = __require("tailwindcss");
|
|
305
|
+
const autoprefixer = __require("autoprefixer");
|
|
306
|
+
return {
|
|
307
|
+
css: {
|
|
308
|
+
postcss: {
|
|
309
|
+
plugins: [tailwindcss, autoprefixer]
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
} catch {
|
|
314
|
+
console.warn("\u26A0\uFE0F Tailwind CSS dependencies not found");
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return {};
|
|
318
|
+
},
|
|
319
|
+
configureServer(server) {
|
|
320
|
+
const { logger } = config;
|
|
321
|
+
server.httpServer?.once("listening", () => {
|
|
322
|
+
setTimeout(() => {
|
|
323
|
+
if (framework === "tailwind") {
|
|
324
|
+
logger.info(" \u{1F3A8} Tailwind CSS integration active");
|
|
325
|
+
if (wordpressPresets) {
|
|
326
|
+
logger.info(" \u{1F4DD} WordPress preset mappings enabled");
|
|
327
|
+
}
|
|
328
|
+
} else if (framework === "unocss") {
|
|
329
|
+
logger.info(" \u{1F3A8} UnoCSS integration active");
|
|
330
|
+
if (wordpressPresets) {
|
|
331
|
+
logger.info(" \u{1F4DD} WordPress preset mappings enabled");
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}, 150);
|
|
335
|
+
});
|
|
336
|
+
},
|
|
337
|
+
async transform(code, id) {
|
|
338
|
+
if (wordpressPresets && id.endsWith(".css") && (framework === "tailwind" || framework === "unocss")) {
|
|
339
|
+
const themeJsonPath = path.join(process.cwd(), "theme.json");
|
|
340
|
+
if (fs.existsSync(themeJsonPath)) {
|
|
341
|
+
try {
|
|
342
|
+
const themeJson = JSON.parse(fs.readFileSync(themeJsonPath, "utf-8"));
|
|
343
|
+
if (themeJson.settings?.color?.palette) {
|
|
344
|
+
let injectedVars = "\n/* WordPress Color Variables */\n:root {\n";
|
|
345
|
+
themeJson.settings.color.palette.forEach((color) => {
|
|
346
|
+
injectedVars += ` --wp--preset--color--${color.slug}: ${color.color};
|
|
347
|
+
`;
|
|
348
|
+
});
|
|
349
|
+
injectedVars += "}\n";
|
|
350
|
+
code = injectedVars + code;
|
|
351
|
+
}
|
|
352
|
+
} catch {
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return code;
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/plugins/critical-css.ts
|
|
362
|
+
import path2 from "path";
|
|
363
|
+
import fs2 from "fs";
|
|
364
|
+
function strataWPCriticalCSS(options = {}) {
|
|
365
|
+
const {
|
|
366
|
+
enabled = true,
|
|
367
|
+
templates = ["index", "single", "page", "archive"],
|
|
368
|
+
dimensions = { width: 1300, height: 900 },
|
|
369
|
+
inline = true,
|
|
370
|
+
output = "dist/critical",
|
|
371
|
+
minSize = 0
|
|
372
|
+
} = options;
|
|
373
|
+
if (!enabled) {
|
|
374
|
+
return {
|
|
375
|
+
name: "stratawp:critical-css",
|
|
376
|
+
apply: () => false
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
return {
|
|
380
|
+
name: "stratawp:critical-css",
|
|
381
|
+
apply: "build",
|
|
382
|
+
async closeBundle() {
|
|
383
|
+
const root = process.cwd();
|
|
384
|
+
const distDir = path2.join(root, "dist");
|
|
385
|
+
const templatesDir = path2.join(root, "templates");
|
|
386
|
+
const outputDir = path2.join(root, output);
|
|
387
|
+
let critical;
|
|
388
|
+
try {
|
|
389
|
+
critical = __require("critical");
|
|
390
|
+
} catch {
|
|
391
|
+
console.warn(
|
|
392
|
+
'\u26A0\uFE0F Critical CSS extraction requires the "critical" package. Install it with: npm install --save-dev critical'
|
|
393
|
+
);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (!fs2.existsSync(outputDir)) {
|
|
397
|
+
fs2.mkdirSync(outputDir, { recursive: true });
|
|
398
|
+
}
|
|
399
|
+
console.log("\u{1F4E6} Extracting critical CSS...");
|
|
400
|
+
const cssFiles = fs2.readdirSync(path2.join(distDir, "css")).filter((f) => f.endsWith(".css")).map((f) => path2.join(distDir, "css", f));
|
|
401
|
+
if (cssFiles.length === 0) {
|
|
402
|
+
console.warn(" No CSS files found to extract critical CSS from");
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const mainCss = cssFiles[0];
|
|
406
|
+
const criticalResults = {};
|
|
407
|
+
for (const template of templates) {
|
|
408
|
+
const templatePath = path2.join(templatesDir, `${template}.html`);
|
|
409
|
+
if (!fs2.existsSync(templatePath)) {
|
|
410
|
+
console.warn(` Template ${template}.html not found, skipping`);
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
try {
|
|
414
|
+
const result = await critical.generate({
|
|
415
|
+
inline: false,
|
|
416
|
+
src: templatePath,
|
|
417
|
+
css: [mainCss],
|
|
418
|
+
dimensions: [dimensions],
|
|
419
|
+
penthouse: {
|
|
420
|
+
timeout: 3e4
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
if (result.css && result.css.length > minSize) {
|
|
424
|
+
criticalResults[template] = result.css;
|
|
425
|
+
const criticalPath = path2.join(outputDir, `${template}-critical.css`);
|
|
426
|
+
fs2.writeFileSync(criticalPath, result.css);
|
|
427
|
+
console.log(` \u2713 ${template}: ${(result.css.length / 1024).toFixed(2)}KB`);
|
|
428
|
+
}
|
|
429
|
+
} catch (error) {
|
|
430
|
+
console.warn(` \u2717 ${template}: Failed to extract critical CSS`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
await generatePHPLoader(root, criticalResults, inline);
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
async function generatePHPLoader(root, criticalResults, inline) {
|
|
438
|
+
const incDir = path2.join(root, "inc");
|
|
439
|
+
if (!fs2.existsSync(incDir)) {
|
|
440
|
+
fs2.mkdirSync(incDir, { recursive: true });
|
|
441
|
+
}
|
|
442
|
+
let phpContent = `<?php
|
|
443
|
+
/**
|
|
444
|
+
* Critical CSS Loader
|
|
445
|
+
*
|
|
446
|
+
* Auto-generated by StrataWP
|
|
447
|
+
* DO NOT EDIT MANUALLY
|
|
448
|
+
*/
|
|
449
|
+
|
|
450
|
+
namespace StrataWP;
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Load critical CSS for template
|
|
454
|
+
*/
|
|
455
|
+
function load_critical_css(): void {
|
|
456
|
+
$template = get_page_template_slug();
|
|
457
|
+
|
|
458
|
+
// Normalize template name
|
|
459
|
+
$template_name = basename($template, '.html');
|
|
460
|
+
if (empty($template_name)) {
|
|
461
|
+
$template_name = is_singular() ? 'single' : 'index';
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
$critical_css_map = array(
|
|
465
|
+
`;
|
|
466
|
+
Object.keys(criticalResults).forEach((template) => {
|
|
467
|
+
phpContent += ` '${template}' => '${template}-critical.css',
|
|
468
|
+
`;
|
|
469
|
+
});
|
|
470
|
+
phpContent += ` );
|
|
471
|
+
|
|
472
|
+
if (isset($critical_css_map[$template_name])) {
|
|
473
|
+
$critical_file = get_template_directory() . '/dist/critical/' . $critical_css_map[$template_name];
|
|
474
|
+
|
|
475
|
+
if (file_exists($critical_file)) {
|
|
476
|
+
`;
|
|
477
|
+
if (inline) {
|
|
478
|
+
phpContent += ` // Inline critical CSS
|
|
479
|
+
echo '<style id="critical-css">';
|
|
480
|
+
echo file_get_contents($critical_file);
|
|
481
|
+
echo '</style>';
|
|
482
|
+
`;
|
|
483
|
+
} else {
|
|
484
|
+
phpContent += ` // Link to critical CSS
|
|
485
|
+
$critical_url = get_template_directory_uri() . '/dist/critical/' . $critical_css_map[$template_name];
|
|
486
|
+
printf(
|
|
487
|
+
'<link rel="stylesheet" href="%s" id="critical-css">',
|
|
488
|
+
esc_url($critical_url)
|
|
489
|
+
);
|
|
490
|
+
`;
|
|
491
|
+
}
|
|
492
|
+
phpContent += ` }
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// Hook into wp_head with high priority
|
|
497
|
+
add_action('wp_head', __NAMESPACE__ . '\\load_critical_css', 1);
|
|
498
|
+
`;
|
|
499
|
+
fs2.writeFileSync(path2.join(incDir, "critical-css-generated.php"), phpContent);
|
|
500
|
+
console.log(" \u2713 Generated inc/critical-css-generated.php");
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// src/plugins/lazy-loading.ts
|
|
504
|
+
import path3 from "path";
|
|
505
|
+
import fs3 from "fs";
|
|
506
|
+
function strataWPLazyLoading(options = {}) {
|
|
507
|
+
const {
|
|
508
|
+
enabled = true,
|
|
509
|
+
images = "native",
|
|
510
|
+
css = true,
|
|
511
|
+
chunks = true
|
|
512
|
+
} = options;
|
|
513
|
+
if (!enabled) {
|
|
514
|
+
return {
|
|
515
|
+
name: "stratawp:lazy-loading",
|
|
516
|
+
apply: () => false
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
return {
|
|
520
|
+
name: "stratawp:lazy-loading",
|
|
521
|
+
apply: "build",
|
|
522
|
+
config() {
|
|
523
|
+
if (chunks) {
|
|
524
|
+
return {
|
|
525
|
+
build: {
|
|
526
|
+
rollupOptions: {
|
|
527
|
+
output: {
|
|
528
|
+
manualChunks: (id) => {
|
|
529
|
+
if (id.includes("node_modules")) {
|
|
530
|
+
return "vendor";
|
|
531
|
+
}
|
|
532
|
+
if (id.includes("@wordpress/")) {
|
|
533
|
+
return "wordpress";
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
return {};
|
|
542
|
+
},
|
|
543
|
+
async closeBundle() {
|
|
544
|
+
const root = process.cwd();
|
|
545
|
+
await generatePHPUtilities(root, images, css);
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
async function generatePHPUtilities(root, images, css) {
|
|
550
|
+
const incDir = path3.join(root, "inc");
|
|
551
|
+
if (!fs3.existsSync(incDir)) {
|
|
552
|
+
fs3.mkdirSync(incDir, { recursive: true });
|
|
553
|
+
}
|
|
554
|
+
let phpContent = `<?php
|
|
555
|
+
/**
|
|
556
|
+
* Lazy Loading Utilities
|
|
557
|
+
*
|
|
558
|
+
* Auto-generated by StrataWP
|
|
559
|
+
* DO NOT EDIT MANUALLY
|
|
560
|
+
*/
|
|
561
|
+
|
|
562
|
+
namespace StrataWP;
|
|
563
|
+
|
|
564
|
+
`;
|
|
565
|
+
if (images !== "none") {
|
|
566
|
+
phpContent += `/**
|
|
567
|
+
* Add loading="lazy" to images
|
|
568
|
+
*/
|
|
569
|
+
function add_lazy_loading_to_images( $content ) {
|
|
570
|
+
if ( is_admin() || is_feed() ) {
|
|
571
|
+
return $content;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Add loading="lazy" to img tags that don't have it
|
|
575
|
+
$content = preg_replace(
|
|
576
|
+
'/<img(?![^>]*loading=)([^>]*)>/i',
|
|
577
|
+
'<img loading="lazy"$1>',
|
|
578
|
+
$content
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
return $content;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
add_filter( 'the_content', __NAMESPACE__ . '\\add_lazy_loading_to_images', 20 );
|
|
585
|
+
add_filter( 'post_thumbnail_html', __NAMESPACE__ . '\\add_lazy_loading_to_images', 20 );
|
|
586
|
+
|
|
587
|
+
`;
|
|
588
|
+
}
|
|
589
|
+
if (css) {
|
|
590
|
+
phpContent += `/**
|
|
591
|
+
* Lazy load non-critical CSS
|
|
592
|
+
*/
|
|
593
|
+
function lazy_load_css( $html, $handle, $href, $media ) {
|
|
594
|
+
// Skip critical CSS
|
|
595
|
+
if ( strpos( $handle, 'critical' ) !== false ) {
|
|
596
|
+
return $html;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// Change media to "print" and add onload to switch to "all"
|
|
600
|
+
$html = str_replace(
|
|
601
|
+
"media='{$media}'",
|
|
602
|
+
"media='print' onload=\\"this.media='all'; this.onload=null;\\"",
|
|
603
|
+
$html
|
|
604
|
+
);
|
|
605
|
+
|
|
606
|
+
// Add noscript fallback
|
|
607
|
+
$noscript = sprintf(
|
|
608
|
+
'<noscript><link rel="stylesheet" href="%s" media="%s"></noscript>',
|
|
609
|
+
esc_url( $href ),
|
|
610
|
+
esc_attr( $media )
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
return $html . $noscript;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Uncomment to enable CSS lazy loading
|
|
617
|
+
// add_filter( 'style_loader_tag', __NAMESPACE__ . '\\lazy_load_css', 10, 4 );
|
|
618
|
+
|
|
619
|
+
`;
|
|
620
|
+
}
|
|
621
|
+
phpContent += `/**
|
|
622
|
+
* Preconnect to external domains
|
|
623
|
+
*/
|
|
624
|
+
function add_resource_hints( $urls, $relation_type ) {
|
|
625
|
+
if ( 'preconnect' === $relation_type ) {
|
|
626
|
+
$urls[] = array(
|
|
627
|
+
'href' => 'https://fonts.googleapis.com',
|
|
628
|
+
'crossorigin',
|
|
629
|
+
);
|
|
630
|
+
$urls[] = array(
|
|
631
|
+
'href' => 'https://fonts.gstatic.com',
|
|
632
|
+
'crossorigin',
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return $urls;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
add_filter( 'wp_resource_hints', __NAMESPACE__ . '\\add_resource_hints', 10, 2 );
|
|
640
|
+
`;
|
|
641
|
+
fs3.writeFileSync(path3.join(incDir, "lazy-loading-generated.php"), phpContent);
|
|
642
|
+
console.log(" \u2713 Generated inc/lazy-loading-generated.php");
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// src/plugins/preload.ts
|
|
646
|
+
import path4 from "path";
|
|
647
|
+
import fs4 from "fs";
|
|
648
|
+
function strataWPPreload(options = {}) {
|
|
649
|
+
const {
|
|
650
|
+
enabled = true,
|
|
651
|
+
assets = ["fonts", "critical-css"],
|
|
652
|
+
strategy = "link-tag"
|
|
653
|
+
} = options;
|
|
654
|
+
if (!enabled) {
|
|
655
|
+
return {
|
|
656
|
+
name: "stratawp:preload",
|
|
657
|
+
apply: () => false
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
name: "stratawp:preload",
|
|
662
|
+
apply: "build",
|
|
663
|
+
async closeBundle() {
|
|
664
|
+
const root = process.cwd();
|
|
665
|
+
await generatePHPPreloader(root, assets, strategy);
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
async function generatePHPPreloader(root, assets, strategy) {
|
|
670
|
+
const incDir = path4.join(root, "inc");
|
|
671
|
+
if (!fs4.existsSync(incDir)) {
|
|
672
|
+
fs4.mkdirSync(incDir, { recursive: true });
|
|
673
|
+
}
|
|
674
|
+
let phpContent = `<?php
|
|
675
|
+
/**
|
|
676
|
+
* Asset Preloader
|
|
677
|
+
*
|
|
678
|
+
* Auto-generated by StrataWP
|
|
679
|
+
* DO NOT EDIT MANUALLY
|
|
680
|
+
*/
|
|
681
|
+
|
|
682
|
+
namespace StrataWP;
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Preload critical assets
|
|
686
|
+
*/
|
|
687
|
+
function preload_assets(): void {
|
|
688
|
+
$preloads = array();
|
|
689
|
+
|
|
690
|
+
`;
|
|
691
|
+
if (assets.includes("fonts")) {
|
|
692
|
+
phpContent += ` // Preload fonts
|
|
693
|
+
$font_dir = get_template_directory() . '/dist/fonts';
|
|
694
|
+
$font_url = get_template_directory_uri() . '/dist/fonts';
|
|
695
|
+
|
|
696
|
+
if ( is_dir( $font_dir ) ) {
|
|
697
|
+
$fonts = glob( $font_dir . '/*.{woff2,woff}', GLOB_BRACE );
|
|
698
|
+
foreach ( $fonts as $font ) {
|
|
699
|
+
$font_name = basename( $font );
|
|
700
|
+
$preloads[] = sprintf(
|
|
701
|
+
'<link rel="preload" href="%s/%s" as="font" type="font/%s" crossorigin>',
|
|
702
|
+
esc_url( $font_url ),
|
|
703
|
+
esc_attr( $font_name ),
|
|
704
|
+
esc_attr( pathinfo( $font, PATHINFO_EXTENSION ) )
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
`;
|
|
710
|
+
}
|
|
711
|
+
if (assets.includes("critical-css")) {
|
|
712
|
+
phpContent += ` // Preload critical CSS
|
|
713
|
+
$critical_dir = get_template_directory() . '/dist/critical';
|
|
714
|
+
$critical_url = get_template_directory_uri() . '/dist/critical';
|
|
715
|
+
|
|
716
|
+
if ( is_dir( $critical_dir ) ) {
|
|
717
|
+
$template_name = is_singular() ? 'single' : 'index';
|
|
718
|
+
$critical_file = $critical_dir . '/' . $template_name . '-critical.css';
|
|
719
|
+
|
|
720
|
+
if ( file_exists( $critical_file ) ) {
|
|
721
|
+
$preloads[] = sprintf(
|
|
722
|
+
'<link rel="preload" href="%s/%s-critical.css" as="style">',
|
|
723
|
+
esc_url( $critical_url ),
|
|
724
|
+
esc_attr( $template_name )
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
`;
|
|
730
|
+
}
|
|
731
|
+
if (assets.includes("critical-js")) {
|
|
732
|
+
phpContent += ` // Preload critical JavaScript
|
|
733
|
+
$manifest_file = get_template_directory() . '/dist/.vite/manifest.json';
|
|
734
|
+
|
|
735
|
+
if ( file_exists( $manifest_file ) ) {
|
|
736
|
+
$manifest = json_decode( file_get_contents( $manifest_file ), true );
|
|
737
|
+
|
|
738
|
+
foreach ( $manifest as $entry ) {
|
|
739
|
+
if ( isset( $entry['isEntry'] ) && $entry['isEntry'] ) {
|
|
740
|
+
$preloads[] = sprintf(
|
|
741
|
+
'<link rel="modulepreload" href="%s/%s">',
|
|
742
|
+
esc_url( get_template_directory_uri() . '/dist' ),
|
|
743
|
+
esc_attr( $entry['file'] )
|
|
744
|
+
);
|
|
745
|
+
break; // Only preload main entry
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
`;
|
|
751
|
+
}
|
|
752
|
+
phpContent += ` // Output preload tags
|
|
753
|
+
foreach ( $preloads as $preload ) {
|
|
754
|
+
echo $preload . "
|
|
755
|
+
";
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
add_action( 'wp_head', __NAMESPACE__ . '\\preload_assets', 2 );
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* DNS prefetch for external resources
|
|
763
|
+
*/
|
|
764
|
+
function dns_prefetch(): void {
|
|
765
|
+
$domains = array(
|
|
766
|
+
'//fonts.googleapis.com',
|
|
767
|
+
'//fonts.gstatic.com',
|
|
768
|
+
);
|
|
769
|
+
|
|
770
|
+
foreach ( $domains as $domain ) {
|
|
771
|
+
printf(
|
|
772
|
+
'<link rel="dns-prefetch" href="%s">' . "
|
|
773
|
+
",
|
|
774
|
+
esc_url( $domain )
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
add_action( 'wp_head', __NAMESPACE__ . '\\dns_prefetch', 1 );
|
|
780
|
+
`;
|
|
781
|
+
fs4.writeFileSync(path4.join(incDir, "preload-generated.php"), phpContent);
|
|
782
|
+
console.log(" \u2713 Generated inc/preload-generated.php");
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// src/plugins/performance.ts
|
|
786
|
+
function strataWPPerformance(options = {}) {
|
|
787
|
+
const plugins = [];
|
|
788
|
+
if (options.criticalCSS !== false) {
|
|
789
|
+
const criticalOptions = typeof options.criticalCSS === "object" ? options.criticalCSS : { enabled: true };
|
|
790
|
+
plugins.push(strataWPCriticalCSS(criticalOptions));
|
|
791
|
+
}
|
|
792
|
+
if (options.lazyLoading !== false) {
|
|
793
|
+
const lazyOptions = typeof options.lazyLoading === "object" ? options.lazyLoading : { enabled: true };
|
|
794
|
+
plugins.push(strataWPLazyLoading(lazyOptions));
|
|
795
|
+
}
|
|
796
|
+
if (options.preload !== false) {
|
|
797
|
+
const preloadOptions = typeof options.preload === "object" ? options.preload : { enabled: true };
|
|
798
|
+
plugins.push(strataWPPreload(preloadOptions));
|
|
799
|
+
}
|
|
800
|
+
return plugins;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// src/integrations/tailwind-preset.ts
|
|
804
|
+
var strataWPTailwindPreset = {
|
|
805
|
+
theme: {
|
|
806
|
+
extend: {
|
|
807
|
+
colors: {
|
|
808
|
+
// WordPress color palette mappings
|
|
809
|
+
"wp-primary": "var(--wp--preset--color--primary)",
|
|
810
|
+
"wp-secondary": "var(--wp--preset--color--secondary)",
|
|
811
|
+
"wp-accent": "var(--wp--preset--color--accent)",
|
|
812
|
+
"wp-text": "var(--wp--preset--color--text)",
|
|
813
|
+
"wp-text-muted": "var(--wp--preset--color--text-muted)",
|
|
814
|
+
"wp-background": "var(--wp--preset--color--background)",
|
|
815
|
+
"wp-background-secondary": "var(--wp--preset--color--background-secondary)",
|
|
816
|
+
"wp-border": "var(--wp--preset--color--border)",
|
|
817
|
+
"wp-success": "var(--wp--preset--color--success)",
|
|
818
|
+
"wp-warning": "var(--wp--preset--color--warning)",
|
|
819
|
+
"wp-error": "var(--wp--preset--color--error)"
|
|
820
|
+
},
|
|
821
|
+
spacing: {
|
|
822
|
+
// WordPress spacing scale mappings
|
|
823
|
+
"wp-xs": "var(--wp--preset--spacing--xs)",
|
|
824
|
+
"wp-sm": "var(--wp--preset--spacing--sm)",
|
|
825
|
+
"wp-md": "var(--wp--preset--spacing--md)",
|
|
826
|
+
"wp-lg": "var(--wp--preset--spacing--lg)",
|
|
827
|
+
"wp-xl": "var(--wp--preset--spacing--xl)",
|
|
828
|
+
"wp-2xl": "var(--wp--preset--spacing--2xl)"
|
|
829
|
+
},
|
|
830
|
+
fontFamily: {
|
|
831
|
+
// WordPress font family mappings
|
|
832
|
+
"wp-sans": "var(--wp--preset--font-family--sans)",
|
|
833
|
+
"wp-serif": "var(--wp--preset--font-family--serif)",
|
|
834
|
+
"wp-mono": "var(--wp--preset--font-family--mono)"
|
|
835
|
+
},
|
|
836
|
+
fontSize: {
|
|
837
|
+
// WordPress font size mappings
|
|
838
|
+
"wp-xs": "var(--wp--preset--font-size--xs)",
|
|
839
|
+
"wp-sm": "var(--wp--preset--font-size--sm)",
|
|
840
|
+
"wp-base": "var(--wp--preset--font-size--base)",
|
|
841
|
+
"wp-lg": "var(--wp--preset--font-size--lg)",
|
|
842
|
+
"wp-xl": "var(--wp--preset--font-size--xl)",
|
|
843
|
+
"wp-2xl": "var(--wp--preset--font-size--2xl)",
|
|
844
|
+
"wp-3xl": "var(--wp--preset--font-size--3xl)",
|
|
845
|
+
"wp-4xl": "var(--wp--preset--font-size--4xl)"
|
|
846
|
+
},
|
|
847
|
+
borderRadius: {
|
|
848
|
+
// WordPress border radius mappings
|
|
849
|
+
"wp-sm": "var(--wp--preset--border-radius--sm)",
|
|
850
|
+
"wp-md": "var(--wp--preset--border-radius--md)",
|
|
851
|
+
"wp-lg": "var(--wp--preset--border-radius--lg)"
|
|
852
|
+
},
|
|
853
|
+
maxWidth: {
|
|
854
|
+
// WordPress content width
|
|
855
|
+
"wp-container": "var(--wp--style--global--content-size)",
|
|
856
|
+
"wp-wide": "var(--wp--style--global--wide-size)"
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
},
|
|
860
|
+
content: [
|
|
861
|
+
"./src/**/*.{js,jsx,ts,tsx}",
|
|
862
|
+
"./inc/**/*.php",
|
|
863
|
+
"./templates/**/*.html",
|
|
864
|
+
"./parts/**/*.{php,html}",
|
|
865
|
+
"./blocks/**/*.{js,jsx,ts,tsx,php}"
|
|
866
|
+
],
|
|
867
|
+
safelist: [
|
|
868
|
+
// Safelist common WordPress block classes
|
|
869
|
+
{ pattern: /^wp-block-.+/ },
|
|
870
|
+
{ pattern: /^has-.+-color$/ },
|
|
871
|
+
{ pattern: /^has-.+-background-color$/ },
|
|
872
|
+
{ pattern: /^has-.+-border-color$/ },
|
|
873
|
+
{ pattern: /^has-.+-font-size$/ },
|
|
874
|
+
{ pattern: /^has-.+-font-family$/ }
|
|
875
|
+
]
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
// src/integrations/unocss-preset.ts
|
|
879
|
+
var strataWPUnoPreset = {
|
|
880
|
+
name: "@stratawp/uno-preset",
|
|
881
|
+
theme: {
|
|
882
|
+
colors: {
|
|
883
|
+
// WordPress color palette mappings
|
|
884
|
+
"wp-primary": "var(--wp--preset--color--primary)",
|
|
885
|
+
"wp-secondary": "var(--wp--preset--color--secondary)",
|
|
886
|
+
"wp-accent": "var(--wp--preset--color--accent)",
|
|
887
|
+
"wp-text": "var(--wp--preset--color--text)",
|
|
888
|
+
"wp-text-muted": "var(--wp--preset--color--text-muted)",
|
|
889
|
+
"wp-background": "var(--wp--preset--color--background)",
|
|
890
|
+
"wp-background-secondary": "var(--wp--preset--color--background-secondary)",
|
|
891
|
+
"wp-border": "var(--wp--preset--color--border)",
|
|
892
|
+
"wp-success": "var(--wp--preset--color--success)",
|
|
893
|
+
"wp-warning": "var(--wp--preset--color--warning)",
|
|
894
|
+
"wp-error": "var(--wp--preset--color--error)"
|
|
895
|
+
},
|
|
896
|
+
spacing: {
|
|
897
|
+
// WordPress spacing scale mappings
|
|
898
|
+
"wp-xs": "var(--wp--preset--spacing--xs)",
|
|
899
|
+
"wp-sm": "var(--wp--preset--spacing--sm)",
|
|
900
|
+
"wp-md": "var(--wp--preset--spacing--md)",
|
|
901
|
+
"wp-lg": "var(--wp--preset--spacing--lg)",
|
|
902
|
+
"wp-xl": "var(--wp--preset--spacing--xl)",
|
|
903
|
+
"wp-2xl": "var(--wp--preset--spacing--2xl)"
|
|
904
|
+
},
|
|
905
|
+
fontFamily: {
|
|
906
|
+
// WordPress font family mappings
|
|
907
|
+
"wp-sans": "var(--wp--preset--font-family--sans)",
|
|
908
|
+
"wp-serif": "var(--wp--preset--font-family--serif)",
|
|
909
|
+
"wp-mono": "var(--wp--preset--font-family--mono)"
|
|
910
|
+
},
|
|
911
|
+
fontSize: {
|
|
912
|
+
// WordPress font size mappings
|
|
913
|
+
"wp-xs": "var(--wp--preset--font-size--xs)",
|
|
914
|
+
"wp-sm": "var(--wp--preset--font-size--sm)",
|
|
915
|
+
"wp-base": "var(--wp--preset--font-size--base)",
|
|
916
|
+
"wp-lg": "var(--wp--preset--font-size--lg)",
|
|
917
|
+
"wp-xl": "var(--wp--preset--font-size--xl)",
|
|
918
|
+
"wp-2xl": "var(--wp--preset--font-size--2xl)",
|
|
919
|
+
"wp-3xl": "var(--wp--preset--font-size--3xl)",
|
|
920
|
+
"wp-4xl": "var(--wp--preset--font-size--4xl)"
|
|
921
|
+
},
|
|
922
|
+
borderRadius: {
|
|
923
|
+
// WordPress border radius mappings
|
|
924
|
+
"wp-sm": "var(--wp--preset--border-radius--sm)",
|
|
925
|
+
"wp-md": "var(--wp--preset--border-radius--md)",
|
|
926
|
+
"wp-lg": "var(--wp--preset--border-radius--lg)"
|
|
927
|
+
},
|
|
928
|
+
maxWidth: {
|
|
929
|
+
// WordPress content width
|
|
930
|
+
"wp-container": "var(--wp--style--global--content-size)",
|
|
931
|
+
"wp-wide": "var(--wp--style--global--wide-size)"
|
|
932
|
+
}
|
|
933
|
+
},
|
|
934
|
+
rules: [
|
|
935
|
+
// Custom WordPress utility rules
|
|
936
|
+
[
|
|
937
|
+
"wp-container",
|
|
938
|
+
{
|
|
939
|
+
"max-width": "var(--wp--style--global--content-size)",
|
|
940
|
+
"margin-left": "auto",
|
|
941
|
+
"margin-right": "auto",
|
|
942
|
+
"padding-left": "1rem",
|
|
943
|
+
"padding-right": "1rem"
|
|
944
|
+
}
|
|
945
|
+
],
|
|
946
|
+
[
|
|
947
|
+
"wp-wide",
|
|
948
|
+
{
|
|
949
|
+
"max-width": "var(--wp--style--global--wide-size)",
|
|
950
|
+
"margin-left": "auto",
|
|
951
|
+
"margin-right": "auto"
|
|
952
|
+
}
|
|
953
|
+
]
|
|
954
|
+
],
|
|
955
|
+
safelist: [
|
|
956
|
+
// Safelist common WordPress block classes
|
|
957
|
+
/^wp-block-.+/,
|
|
958
|
+
/^has-.+-color$/,
|
|
959
|
+
/^has-.+-background-color$/,
|
|
960
|
+
/^has-.+-border-color$/,
|
|
961
|
+
/^has-.+-font-size$/,
|
|
962
|
+
/^has-.+-font-family$/
|
|
963
|
+
]
|
|
964
|
+
};
|
|
965
|
+
|
|
966
|
+
// src/index.ts
|
|
967
|
+
function strataWP(options = {}) {
|
|
968
|
+
const {
|
|
969
|
+
blocks = {
|
|
970
|
+
dir: "src/blocks",
|
|
971
|
+
autoRegister: true
|
|
972
|
+
},
|
|
973
|
+
manifest = {
|
|
974
|
+
enabled: true,
|
|
975
|
+
output: "dist/.vite/manifest.json"
|
|
976
|
+
},
|
|
977
|
+
phpHmr = {
|
|
978
|
+
enabled: true,
|
|
979
|
+
watch: ["**/*.php", "theme.json"]
|
|
980
|
+
},
|
|
981
|
+
assets = {
|
|
982
|
+
publicDir: "dist"
|
|
983
|
+
},
|
|
984
|
+
designSystem = {
|
|
985
|
+
enabled: false,
|
|
986
|
+
framework: "none"
|
|
987
|
+
},
|
|
988
|
+
performance = {
|
|
989
|
+
criticalCSS: true,
|
|
990
|
+
lazyLoading: true,
|
|
991
|
+
preload: true
|
|
992
|
+
}
|
|
993
|
+
} = options;
|
|
994
|
+
const plugins = [
|
|
995
|
+
strataWPCore(options),
|
|
996
|
+
strataWPBlocks(blocks),
|
|
997
|
+
strataWPManifest(manifest),
|
|
998
|
+
strataWPPhpHmr(phpHmr),
|
|
999
|
+
strataWPAssets(assets)
|
|
1000
|
+
];
|
|
1001
|
+
if (designSystem.enabled) {
|
|
1002
|
+
plugins.push(strataWPDesignSystem(designSystem));
|
|
1003
|
+
}
|
|
1004
|
+
plugins.push(...strataWPPerformance(performance));
|
|
1005
|
+
return plugins;
|
|
1006
|
+
}
|
|
1007
|
+
function strataWPCore(_options) {
|
|
1008
|
+
let config;
|
|
1009
|
+
return {
|
|
1010
|
+
name: "stratawp",
|
|
1011
|
+
config() {
|
|
1012
|
+
return {
|
|
1013
|
+
// WordPress-friendly build config
|
|
1014
|
+
build: {
|
|
1015
|
+
manifest: true,
|
|
1016
|
+
rollupOptions: {
|
|
1017
|
+
output: {
|
|
1018
|
+
entryFileNames: "js/[name].[hash].js",
|
|
1019
|
+
chunkFileNames: "js/[name].[hash].js",
|
|
1020
|
+
assetFileNames: (assetInfo) => {
|
|
1021
|
+
const name = assetInfo.name || "";
|
|
1022
|
+
if (/\.(css)$/.test(name)) {
|
|
1023
|
+
return "css/[name].[hash][extname]";
|
|
1024
|
+
}
|
|
1025
|
+
if (/\.(png|jpe?g|svg|gif|webp|avif)$/.test(name)) {
|
|
1026
|
+
return "images/[name].[hash][extname]";
|
|
1027
|
+
}
|
|
1028
|
+
if (/\.(woff2?|eot|ttf|otf)$/.test(name)) {
|
|
1029
|
+
return "fonts/[name].[hash][extname]";
|
|
1030
|
+
}
|
|
1031
|
+
return "assets/[name].[hash][extname]";
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
},
|
|
1036
|
+
// Optimize deps for WordPress
|
|
1037
|
+
optimizeDeps: {
|
|
1038
|
+
include: [
|
|
1039
|
+
"@wordpress/blocks",
|
|
1040
|
+
"@wordpress/block-editor",
|
|
1041
|
+
"@wordpress/components",
|
|
1042
|
+
"@wordpress/data",
|
|
1043
|
+
"@wordpress/element",
|
|
1044
|
+
"@wordpress/i18n"
|
|
1045
|
+
]
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1048
|
+
},
|
|
1049
|
+
configResolved(resolvedConfig) {
|
|
1050
|
+
config = resolvedConfig;
|
|
1051
|
+
},
|
|
1052
|
+
configureServer(server) {
|
|
1053
|
+
server.httpServer?.once("listening", () => {
|
|
1054
|
+
setTimeout(() => {
|
|
1055
|
+
const { logger } = config;
|
|
1056
|
+
logger.info("\n \u26A1 StrataWP Dev Server Ready!\n");
|
|
1057
|
+
logger.info(" WordPress integration active");
|
|
1058
|
+
logger.info(" Block auto-discovery enabled");
|
|
1059
|
+
logger.info(" PHP HMR watching for changes\n");
|
|
1060
|
+
}, 100);
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
export {
|
|
1066
|
+
strataWP,
|
|
1067
|
+
strataWPAssets,
|
|
1068
|
+
strataWPBlocks,
|
|
1069
|
+
strataWPDesignSystem,
|
|
1070
|
+
strataWPManifest,
|
|
1071
|
+
strataWPPerformance,
|
|
1072
|
+
strataWPPhpHmr,
|
|
1073
|
+
strataWPTailwindPreset,
|
|
1074
|
+
strataWPUnoPreset
|
|
1075
|
+
};
|