@plaudit/webpack-extensions 2.37.0 → 2.39.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.
@@ -1,14 +1,17 @@
1
- import { type Compilation, type Compiler, type WebpackPluginInstance } from "webpack";
1
+ import { Compilation, type Compiler, type WebpackPluginInstance } from "webpack";
2
2
  export default class BlockJSONManagingPlugin implements WebpackPluginInstance {
3
3
  private readonly standaloneBlocks;
4
4
  private readonly processingModules;
5
5
  static readonly mappableModuleKeys: readonly ["viewScriptModule", "scriptModule"];
6
6
  static readonly mappableNonModuleKeys: readonly ["editorStyle", "style", "viewStyle", "editorScript", "script", "viewScript"];
7
+ private static readonly styleExtensionPattern;
8
+ private static readonly scriptExtensionPattern;
7
9
  private static readonly mappableKeys;
8
10
  private static readonly blockJsonToEntrypointsMap;
9
11
  private static readonly blockJsonRawDependenciesMap;
10
12
  private static readonly blockJSONAssetSourceDirs;
11
13
  private static readonly blockJsonAssetKeyMapping;
14
+ private static readonly blockJsonAssetKeyReadinessMapping;
12
15
  constructor(standaloneBlocks: boolean, processingModules: boolean);
13
16
  static recordRawDependency(entrypoint: string, dependency: string): void;
14
17
  static recordBlockJSONAssetSourceDir(entrypoint: string, source: string): void;
@@ -24,4 +27,9 @@ export default class BlockJSONManagingPlugin implements WebpackPluginInstance {
24
27
  private static remapReferencedAssetFile;
25
28
  private static getReferencedFileSlot;
26
29
  private static addAssetToBlockJsonKey;
30
+ private registerAssetProcessor;
31
+ private static populateEntrypointsMap;
32
+ private registerBlockJsonProcessor;
33
+ private static normalizeRenderTemplate;
34
+ private static getSyncs;
27
35
  }
@@ -13,11 +13,14 @@ class BlockJSONManagingPlugin {
13
13
  processingModules;
14
14
  static mappableModuleKeys = ["viewScriptModule", "scriptModule"];
15
15
  static mappableNonModuleKeys = ["editorStyle", "style", "viewStyle", "editorScript", "script", "viewScript"];
16
+ static styleExtensionPattern = /\.(p?c|sa)ss$/i;
17
+ static scriptExtensionPattern = /\.m?[tj]sx?$/i;
16
18
  static mappableKeys = [...BlockJSONManagingPlugin.mappableNonModuleKeys, ...BlockJSONManagingPlugin.mappableModuleKeys];
17
19
  static blockJsonToEntrypointsMap = new Map();
18
20
  static blockJsonRawDependenciesMap = new Map();
19
21
  static blockJSONAssetSourceDirs = new Map();
20
22
  static blockJsonAssetKeyMapping = new Map();
23
+ static blockJsonAssetKeyReadinessMapping = new Map();
21
24
  constructor(standaloneBlocks, processingModules) {
22
25
  this.standaloneBlocks = standaloneBlocks;
23
26
  this.processingModules = processingModules;
@@ -34,171 +37,10 @@ class BlockJSONManagingPlugin {
34
37
  }
35
38
  apply(compiler) {
36
39
  compiler.hooks.compilation.tap(this.constructor.name, compilation => {
37
- compilation.hooks.afterProcessAssets.tap(`${this.constructor.name}_ProcessBlockJSONFiles`, compilationAssets => {
38
- const testableCompilationAssets = this.processingModules ? BlockJSONManagingPlugin.buildFakeCompilationAssets(compilation) : compilationAssets;
39
- const currentBlockJSONAssets = BlockJSONManagingPlugin.blockJSONAssetSourceDirs.entries()
40
- .filter(([name]) => name in testableCompilationAssets)
41
- .toArray();
42
- for (const [name] of currentBlockJSONAssets) {
43
- const dependencies = BlockJSONManagingPlugin.blockJsonRawDependenciesMap.get(name);
44
- if (dependencies) {
45
- for (const dependency of dependencies) {
46
- const entrypoint = compilation.entrypoints.get(dependency);
47
- if (!entrypoint) {
48
- continue;
49
- }
50
- const srcPath = entrypoint.origins.map(origin => origin.request)[0];
51
- if (!srcPath) {
52
- continue;
53
- }
54
- const destPath = BlockJSONManagingPlugin.resolveDestinationBySourceExtension(srcPath, entrypoint);
55
- if (!destPath) {
56
- continue;
57
- }
58
- const entrypointChunk = entrypoint.getEntrypointChunk();
59
- const additionalFiles = [];
60
- for (const entrypointChunkFile of entrypointChunk.files) {
61
- if (!entrypointChunkFile.endsWith(".asset.php") && entrypointChunkFile !== destPath) {
62
- additionalFiles.push(entrypointChunkFile);
63
- }
64
- }
65
- const entryMeta = { hash: entrypointChunk.hash ?? destPath, path: destPath };
66
- const currentEntrypoints = BlockJSONManagingPlugin.blockJsonToEntrypointsMap.get(name);
67
- if (currentEntrypoints) {
68
- currentEntrypoints.set(srcPath, [entryMeta, additionalFiles]);
69
- }
70
- else {
71
- BlockJSONManagingPlugin.blockJsonToEntrypointsMap.set(name, new Map([[srcPath, [entryMeta, additionalFiles]]]));
72
- }
73
- }
74
- }
75
- }
76
- //TODO: Fix modules support when running in non-dev mode
77
- const blockDirConfigData = {};
78
- for (const [name, sourceDir] of currentBlockJSONAssets) {
79
- const assetContents = this.processingModules ? node_fs_1.default.readFileSync(testableCompilationAssets[name], 'utf8') : compilation.assets[name]?.buffer().toString();
80
- if (!assetContents) {
81
- continue;
82
- }
83
- const json = JSON.parse(assetContents);
84
- const currentAssetKeyMappings = { directMappings: {}, referencedFiles: {}, compositeHash: "" };
85
- for (const mappableKey of BlockJSONManagingPlugin[this.processingModules ? 'mappableModuleKeys' : 'mappableNonModuleKeys']) {
86
- if (mappableKey in json) {
87
- const unmappedValue = json[mappableKey];
88
- if (Array.isArray(unmappedValue)) {
89
- for (const uv of unmappedValue) {
90
- BlockJSONManagingPlugin.incorporateRemappedAsset(currentAssetKeyMappings, mappableKey, ...BlockJSONManagingPlugin.remapReferencedAssetFile(uv, name));
91
- }
92
- }
93
- else if (typeof unmappedValue === 'string') {
94
- BlockJSONManagingPlugin.incorporateRemappedAsset(currentAssetKeyMappings, mappableKey, ...BlockJSONManagingPlugin.remapReferencedAssetFile(unmappedValue, name));
95
- }
96
- }
97
- }
98
- const assetKeyMappings = { ...BlockJSONManagingPlugin.blockJsonAssetKeyMapping.get(name), [this.processingModules ? 'module' : 'nonModule']: currentAssetKeyMappings };
99
- BlockJSONManagingPlugin.blockJsonAssetKeyMapping.set(name, assetKeyMappings);
100
- let compositeHash = "";
101
- const condensedBlockJsonAssetKeyMappings = {};
102
- for (const subType of ['nonModule', 'module']) {
103
- const mappings = assetKeyMappings[subType];
104
- if (mappings) {
105
- compositeHash += mappings.compositeHash;
106
- for (const mappableKey of BlockJSONManagingPlugin.mappableKeys) {
107
- if (mappings.directMappings[mappableKey]) {
108
- BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, mappableKey, mappings.directMappings[mappableKey]);
109
- }
110
- }
111
- for (const [referenceLocation, prefix] of [["editor", "editorS"], ["both", "s"], ["view", "viewS"]]) {
112
- if (mappings.referencedFiles[referenceLocation]) {
113
- for (const referencedFile of mappings.referencedFiles[referenceLocation]) {
114
- if (referencedFile.endsWith(".css")) {
115
- BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}tyle`, referencedFile);
116
- }
117
- else if (referencedFile.endsWith(".js")) {
118
- BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}cript`, referencedFile);
119
- }
120
- else if (referencedFile.endsWith(".mjs")) {
121
- BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}criptModule`, referencedFile);
122
- }
123
- }
124
- }
125
- }
126
- }
127
- }
128
- for (const mappableKey of BlockJSONManagingPlugin.mappableKeys) {
129
- if (mappableKey in condensedBlockJsonAssetKeyMappings) {
130
- json[mappableKey] = condensedBlockJsonAssetKeyMappings[mappableKey];
131
- }
132
- else {
133
- delete json[mappableKey];
134
- }
135
- }
136
- if (json["version"]) {
137
- json["version"] = `${json["version"]}-${BlockJSONManagingPlugin.hashThingForAsset(compositeHash)}`;
138
- }
139
- else {
140
- json["version"] = BlockJSONManagingPlugin.hashThingForAsset(compositeHash);
141
- }
142
- const outputDir = node_path_1.default.join(compiler.outputPath, node_path_1.default.dirname(name));
143
- const pathsNeedRemapping = !this.standaloneBlocks && json["plaudit"] !== "simple";
144
- BlockJSONManagingPlugin.remapReferencedPHPFilesOnKey(json, "setup", pathsNeedRemapping, sourceDir, outputDir, compilation, true);
145
- BlockJSONManagingPlugin.remapReferencedPHPFilesOnKey(json, "variations", pathsNeedRemapping, sourceDir, outputDir, compilation, false);
146
- if (json["acf"]) {
147
- if (json["acf"]["renderTemplate"]) {
148
- json["render_template"] = json["acf"]["renderTemplate"];
149
- delete json["acf"]["renderTemplate"];
150
- }
151
- else if (json["acf"]["render_template"]) {
152
- json["render_template"] = json["acf"]["render_template"];
153
- delete json["acf"]["render_template"];
154
- }
155
- }
156
- const blockName = json["name"]?.toString() || "non-existent/block-name";
157
- let rawRenderTemplate = json["render"] ?? json["render_template"];
158
- rawRenderTemplate = (rawRenderTemplate
159
- ? (typeof rawRenderTemplate === 'string' ? [rawRenderTemplate] : rawRenderTemplate)
160
- : [`${blockName.substring(blockName.indexOf('/') + 1)}.php`, "template.php", "template.twig"]);
161
- const renderTemplate = pathsNeedRemapping
162
- ? rawRenderTemplate
163
- .map(p => node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p))))
164
- .filter(p => node_fs_1.default.existsSync(p))
165
- .map(p => `file:./${BlockJSONManagingPlugin.findRelativeRouteBetween(outputDir, p)}`)
166
- : rawRenderTemplate
167
- .filter(p => node_fs_1.default.existsSync(node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p)))));
168
- if (renderTemplate.length === 0) {
169
- delete json["render_template"];
170
- delete json["render"];
171
- }
172
- else {
173
- let validTemplateLocation, invalidTemplateLocation;
174
- if (json["acf"] || (json["plaudit"] && (json["plaudit"] !== "native" && (typeof json["plaudit"] !== 'object' || json["plaudit"]?.["type"] !== "native")))) {
175
- // ACF-like blocks need to have the template stored in render_template.
176
- // Because we can statically detect ACF-like blocks, we can make the move here instead of at run-time.
177
- validTemplateLocation = "render_template";
178
- invalidTemplateLocation = "render";
179
- }
180
- else {
181
- validTemplateLocation = "render";
182
- invalidTemplateLocation = "render_template";
183
- }
184
- delete json[invalidTemplateLocation];
185
- if (renderTemplate.length > 1) {
186
- const error = new webpack_1.WebpackError("Encountered a block with multiple possible render files");
187
- error.file = node_path_1.default.join(sourceDir, 'block.json');
188
- compilation.warnings.push(error);
189
- json[validTemplateLocation] = renderTemplate.find(p => p.endsWith(".php")) ?? renderTemplate[0];
190
- }
191
- else {
192
- json[validTemplateLocation] = renderTemplate[0];
193
- }
194
- }
195
- compilation[name in compilation.assets ? 'updateAsset' : 'emitAsset'](name, new webpack_1.sources.RawSource(JSON.stringify(json, undefined, " ")));
196
- blockDirConfigData[node_path_1.default.dirname(name)] = json;
197
- }
198
- const sortedBlockDirConfigData = Object.fromEntries(Object.entries(blockDirConfigData)
199
- .sort(([a], [b]) => a.localeCompare(b)));
200
- compilation.emitAsset("blockdir.config", new webpack_1.sources.RawSource((0, php_serializer_1.default)(sortedBlockDirConfigData, { excludedKeys: ["$schema"] })));
201
- });
40
+ this.registerAssetProcessor(compilation);
41
+ if (!this.processingModules) {
42
+ this.registerBlockJsonProcessor(compilation);
43
+ }
202
44
  });
203
45
  }
204
46
  static resolveDestinationBySourceExtension(srcPath, entrypoint) {
@@ -331,7 +173,15 @@ class BlockJSONManagingPlugin {
331
173
  const prefix = value.startsWith("./", 5) ? "./" : "";
332
174
  const relativePath = node_path_1.default.relative(node_path_1.default.dirname(name), output.path);
333
175
  const res = [`file:${prefix}${relativePath}`, output.hash];
334
- return [res, additionalFiles.map(additionalFile => `file:./${node_path_1.default.relative(node_path_1.default.dirname(name), additionalFile)}`)];
176
+ if (BlockJSONManagingPlugin.styleExtensionPattern.test(output.path)) {
177
+ return [res,
178
+ additionalFiles.filter(additionalFile => !BlockJSONManagingPlugin.scriptExtensionPattern.test(additionalFile))
179
+ .map(additionalFile => `file:./${node_path_1.default.relative(node_path_1.default.dirname(name), additionalFile)}`)
180
+ ];
181
+ }
182
+ else {
183
+ return [res, additionalFiles.map(additionalFile => `file:./${node_path_1.default.relative(node_path_1.default.dirname(name), additionalFile)}`)];
184
+ }
335
185
  }
336
186
  }
337
187
  return [[value, ""], []];
@@ -373,5 +223,227 @@ class BlockJSONManagingPlugin {
373
223
  }
374
224
  }
375
225
  }
226
+ registerAssetProcessor(compilation) {
227
+ const tapName = { name: `${this.constructor.name}_ProcessBlockJSONFiles`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_DERIVED };
228
+ compilation.hooks.processAssets.tapPromise(tapName, async (compilationAssets) => {
229
+ const testableCompilationAssets = this.processingModules ? BlockJSONManagingPlugin.buildFakeCompilationAssets(compilation) : compilationAssets;
230
+ const currentBlockJSONAssets = BlockJSONManagingPlugin.blockJSONAssetSourceDirs.entries()
231
+ .filter(([name]) => name in testableCompilationAssets)
232
+ .toArray();
233
+ BlockJSONManagingPlugin.populateEntrypointsMap(currentBlockJSONAssets, compilation);
234
+ await Promise.all(currentBlockJSONAssets.map(async ([name]) => {
235
+ const assetContents = this.processingModules ? node_fs_1.default.readFileSync(testableCompilationAssets[name], 'utf8') : compilation.assets[name]?.buffer().toString();
236
+ if (!assetContents) {
237
+ return;
238
+ }
239
+ const json = JSON.parse(assetContents);
240
+ const currentAssetKeyMappings = { directMappings: {}, referencedFiles: {}, compositeHash: "" };
241
+ for (const mappableKey of BlockJSONManagingPlugin[this.processingModules ? 'mappableModuleKeys' : 'mappableNonModuleKeys']) {
242
+ if (mappableKey in json) {
243
+ const unmappedValue = json[mappableKey];
244
+ if (Array.isArray(unmappedValue)) {
245
+ for (const uv of unmappedValue) {
246
+ BlockJSONManagingPlugin.incorporateRemappedAsset(currentAssetKeyMappings, mappableKey, ...BlockJSONManagingPlugin.remapReferencedAssetFile(uv, name));
247
+ }
248
+ }
249
+ else if (typeof unmappedValue === 'string') {
250
+ BlockJSONManagingPlugin.incorporateRemappedAsset(currentAssetKeyMappings, mappableKey, ...BlockJSONManagingPlugin.remapReferencedAssetFile(unmappedValue, name));
251
+ }
252
+ }
253
+ }
254
+ const syncs = BlockJSONManagingPlugin.getSyncs(name);
255
+ let assetKeyMappings = BlockJSONManagingPlugin.blockJsonAssetKeyMapping.get(name);
256
+ if (!assetKeyMappings) {
257
+ BlockJSONManagingPlugin.blockJsonAssetKeyMapping.set(name, assetKeyMappings = {});
258
+ }
259
+ assetKeyMappings[this.processingModules ? 'module' : 'nonModule'] = currentAssetKeyMappings;
260
+ if (this.processingModules) {
261
+ syncs.module.resolve();
262
+ if (!BlockJSONManagingPlugin.mappableNonModuleKeys.some(key => key in json)) {
263
+ syncs.nonModule.resolve();
264
+ }
265
+ await syncs.nonModule.sync;
266
+ }
267
+ else {
268
+ syncs.nonModule.resolve();
269
+ if (!BlockJSONManagingPlugin.mappableModuleKeys.some(key => key in json)) {
270
+ syncs.module.resolve();
271
+ }
272
+ await syncs.module.sync;
273
+ }
274
+ }));
275
+ });
276
+ }
277
+ static populateEntrypointsMap(currentBlockJSONAssets, compilation) {
278
+ for (const [name] of currentBlockJSONAssets) {
279
+ const dependencies = BlockJSONManagingPlugin.blockJsonRawDependenciesMap.get(name);
280
+ if (dependencies) {
281
+ for (const dependency of dependencies) {
282
+ const entrypoint = compilation.entrypoints.get(dependency);
283
+ if (!entrypoint) {
284
+ continue;
285
+ }
286
+ const srcPath = entrypoint.origins.map(origin => origin.request)[0];
287
+ if (!srcPath) {
288
+ continue;
289
+ }
290
+ const destPath = BlockJSONManagingPlugin.resolveDestinationBySourceExtension(srcPath, entrypoint);
291
+ if (!destPath) {
292
+ continue;
293
+ }
294
+ const entrypointChunk = entrypoint.getEntrypointChunk();
295
+ const additionalFiles = [];
296
+ for (const entrypointChunkFile of entrypointChunk.files) {
297
+ if (!entrypointChunkFile.endsWith(".asset.php") && entrypointChunkFile !== destPath) {
298
+ additionalFiles.push(entrypointChunkFile);
299
+ }
300
+ }
301
+ const entryMeta = { hash: entrypointChunk.hash ?? destPath, path: destPath };
302
+ const currentEntrypoints = BlockJSONManagingPlugin.blockJsonToEntrypointsMap.get(name);
303
+ if (currentEntrypoints) {
304
+ currentEntrypoints.set(srcPath, [entryMeta, additionalFiles]);
305
+ }
306
+ else {
307
+ BlockJSONManagingPlugin.blockJsonToEntrypointsMap.set(name, new Map([[srcPath, [entryMeta, additionalFiles]]]));
308
+ }
309
+ }
310
+ }
311
+ }
312
+ }
313
+ registerBlockJsonProcessor(compilation) {
314
+ const blockDirConfigData = {};
315
+ compilation.hooks.afterProcessAssets.tap(`${this.constructor.name}_GenerateMetadata`, compilationAssets => {
316
+ const currentBlockJSONAssets = BlockJSONManagingPlugin.blockJSONAssetSourceDirs.entries()
317
+ .filter(([name]) => name in compilationAssets)
318
+ .toArray();
319
+ for (const [name, sourceDir] of currentBlockJSONAssets) {
320
+ const assetKeyMappings = BlockJSONManagingPlugin.blockJsonAssetKeyMapping.get(name);
321
+ let compositeHash = "";
322
+ const condensedBlockJsonAssetKeyMappings = {};
323
+ for (const subType of ['nonModule', 'module']) {
324
+ const mappings = assetKeyMappings[subType];
325
+ if (mappings) {
326
+ compositeHash += mappings.compositeHash;
327
+ for (const mappableKey of BlockJSONManagingPlugin.mappableKeys) {
328
+ if (mappings.directMappings[mappableKey]) {
329
+ BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, mappableKey, mappings.directMappings[mappableKey]);
330
+ }
331
+ }
332
+ for (const [referenceLocation, prefix] of [["editor", "editorS"], ["both", "s"], ["view", "viewS"]]) {
333
+ if (mappings.referencedFiles[referenceLocation]) {
334
+ for (const referencedFile of mappings.referencedFiles[referenceLocation]) {
335
+ if (referencedFile.endsWith(".css")) {
336
+ BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}tyle`, referencedFile);
337
+ }
338
+ else if (referencedFile.endsWith(".js")) {
339
+ BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}cript`, referencedFile);
340
+ }
341
+ else if (referencedFile.endsWith(".mjs")) {
342
+ BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}criptModule`, referencedFile);
343
+ }
344
+ }
345
+ }
346
+ }
347
+ }
348
+ }
349
+ const assetContents = compilation.assets[name]?.buffer().toString();
350
+ if (!assetContents) {
351
+ continue;
352
+ }
353
+ const json = JSON.parse(assetContents);
354
+ for (const mappableKey of BlockJSONManagingPlugin.mappableKeys) {
355
+ if (mappableKey in condensedBlockJsonAssetKeyMappings) {
356
+ json[mappableKey] = condensedBlockJsonAssetKeyMappings[mappableKey];
357
+ }
358
+ else {
359
+ delete json[mappableKey];
360
+ }
361
+ }
362
+ if (json["version"]) {
363
+ json["version"] = `${json["version"]}-${BlockJSONManagingPlugin.hashThingForAsset(compositeHash)}`;
364
+ }
365
+ else {
366
+ json["version"] = BlockJSONManagingPlugin.hashThingForAsset(compositeHash);
367
+ }
368
+ const outputDir = node_path_1.default.join(compilation.compiler.outputPath, node_path_1.default.dirname(name));
369
+ const pathsNeedRemapping = !this.standaloneBlocks && json["plaudit"] !== "simple";
370
+ BlockJSONManagingPlugin.remapReferencedPHPFilesOnKey(json, "setup", pathsNeedRemapping, sourceDir, outputDir, compilation, true);
371
+ BlockJSONManagingPlugin.remapReferencedPHPFilesOnKey(json, "variations", pathsNeedRemapping, sourceDir, outputDir, compilation, false);
372
+ BlockJSONManagingPlugin.normalizeRenderTemplate(json, pathsNeedRemapping, sourceDir, outputDir, compilation);
373
+ compilation[name in compilation.assets ? 'updateAsset' : 'emitAsset'](name, new webpack_1.sources.RawSource(JSON.stringify(json, undefined, " ")));
374
+ blockDirConfigData[node_path_1.default.dirname(name)] = json;
375
+ }
376
+ const sortedBlockDirConfigData = Object.fromEntries([["__metadata", { version: 1 }], ...Object.entries(blockDirConfigData)
377
+ .sort(([a], [b]) => a.localeCompare(b))]);
378
+ compilation.emitAsset("blockdir.config", new webpack_1.sources.RawSource((0, php_serializer_1.default)(sortedBlockDirConfigData, { excludedKeys: ["$schema"] })));
379
+ });
380
+ }
381
+ static normalizeRenderTemplate(json, pathsNeedRemapping, sourceDir, outputDir, compilation) {
382
+ if (json["acf"]) {
383
+ if (json["acf"]["renderTemplate"]) {
384
+ json["render_template"] = json["acf"]["renderTemplate"];
385
+ delete json["acf"]["renderTemplate"];
386
+ }
387
+ else if (json["acf"]["render_template"]) {
388
+ json["render_template"] = json["acf"]["render_template"];
389
+ delete json["acf"]["render_template"];
390
+ }
391
+ }
392
+ const blockName = json["name"]?.toString() || "non-existent/block-name";
393
+ let rawRenderTemplate = json["render"] ?? json["render_template"];
394
+ rawRenderTemplate = (rawRenderTemplate
395
+ ? (typeof rawRenderTemplate === 'string' ? [rawRenderTemplate] : rawRenderTemplate)
396
+ : [`${blockName.substring(blockName.indexOf('/') + 1)}.php`, "template.php", "template.twig"]);
397
+ const renderTemplate = pathsNeedRemapping
398
+ ? rawRenderTemplate
399
+ .map(p => node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p))))
400
+ .filter(p => node_fs_1.default.existsSync(p))
401
+ .map(p => `file:./${BlockJSONManagingPlugin.findRelativeRouteBetween(outputDir, p)}`)
402
+ : rawRenderTemplate
403
+ .filter(p => node_fs_1.default.existsSync(node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p)))));
404
+ if (renderTemplate.length === 0) {
405
+ delete json["render_template"];
406
+ delete json["render"];
407
+ }
408
+ else {
409
+ let validTemplateLocation, invalidTemplateLocation;
410
+ if (json["acf"] || (json["plaudit"] && (json["plaudit"] !== "native" && (typeof json["plaudit"] !== 'object' || json["plaudit"]?.["type"] !== "native")))) {
411
+ // ACF-like blocks need to have the template stored in render_template.
412
+ // Because we can statically detect ACF-like blocks, we can make the move here instead of at run-time.
413
+ validTemplateLocation = "render_template";
414
+ invalidTemplateLocation = "render";
415
+ }
416
+ else {
417
+ validTemplateLocation = "render";
418
+ invalidTemplateLocation = "render_template";
419
+ }
420
+ delete json[invalidTemplateLocation];
421
+ if (renderTemplate.length > 1) {
422
+ const error = new webpack_1.WebpackError("Encountered a block with multiple possible render files");
423
+ error.file = node_path_1.default.join(sourceDir, 'block.json');
424
+ compilation.warnings.push(error);
425
+ json[validTemplateLocation] = renderTemplate.find(p => p.endsWith(".php")) ?? renderTemplate[0];
426
+ }
427
+ else {
428
+ json[validTemplateLocation] = renderTemplate[0];
429
+ }
430
+ }
431
+ }
432
+ static getSyncs(name) {
433
+ const res = BlockJSONManagingPlugin.blockJsonAssetKeyReadinessMapping.get(name);
434
+ if (res) {
435
+ return res;
436
+ }
437
+ BlockJSONManagingPlugin.blockJsonAssetKeyReadinessMapping.set(name, { nonModule: makeSync(), module: makeSync() });
438
+ return BlockJSONManagingPlugin.blockJsonAssetKeyReadinessMapping.get(name);
439
+ }
376
440
  }
377
441
  exports.default = BlockJSONManagingPlugin;
442
+ function makeSync() {
443
+ const res = { done: false };
444
+ res.sync = new Promise((resolve, reject) => {
445
+ res.resolve = (v) => resolve(v);
446
+ res.reject = () => reject();
447
+ });
448
+ return res;
449
+ }
@@ -0,0 +1,9 @@
1
+ import DependencyExtractionWebpackPlugin from "@wordpress/dependency-extraction-webpack-plugin";
2
+ export type IndividualExternalDepConfig = string | {
3
+ import?: string | [string, ...string[]];
4
+ handle: string;
5
+ };
6
+ export type Externals = {
7
+ [dep: string]: IndividualExternalDepConfig;
8
+ };
9
+ export declare function makeDependencyExtractionPlugin(externals: Externals | undefined, assumeGlobalizedPlauditLibraries: boolean): false | DependencyExtractionWebpackPlugin;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.makeDependencyExtractionPlugin = makeDependencyExtractionPlugin;
7
+ const dependency_extraction_webpack_plugin_1 = __importDefault(require("@wordpress/dependency-extraction-webpack-plugin"));
8
+ function makeDependencyExtractionPlugin(externals, assumeGlobalizedPlauditLibraries) {
9
+ if (!externals) {
10
+ if (assumeGlobalizedPlauditLibraries) {
11
+ return new dependency_extraction_webpack_plugin_1.default({
12
+ requestToExternal: plauditRequestToExternal,
13
+ requestToHandle: plauditRequestToHandle
14
+ });
15
+ }
16
+ return false;
17
+ }
18
+ const exactExternals = {};
19
+ const suffixExternals = [];
20
+ for (const [key, value] of Object.entries(externals)) {
21
+ const normalizedValue = typeof value !== 'string' && value.import === undefined ? { ...value, import: key } : value;
22
+ if (key.startsWith("*/")) {
23
+ suffixExternals.push([key.substring(1), typeof normalizedValue === 'string' ? { import: normalizedValue, handle: key.substring(2) } : normalizedValue]);
24
+ }
25
+ else {
26
+ exactExternals[key] = normalizedValue;
27
+ }
28
+ }
29
+ const resolvePossibleExternal = (request) => {
30
+ if (request in exactExternals) {
31
+ return exactExternals[request];
32
+ }
33
+ for (const [key, value] of suffixExternals) {
34
+ if (request.endsWith(key)) {
35
+ return value;
36
+ }
37
+ }
38
+ return undefined;
39
+ };
40
+ const baselineRequestToExternal = request => {
41
+ const possibleExternal = resolvePossibleExternal(request);
42
+ if (typeof possibleExternal === 'string') {
43
+ return possibleExternal;
44
+ }
45
+ else if (possibleExternal !== undefined) {
46
+ return possibleExternal['import'];
47
+ }
48
+ return undefined;
49
+ };
50
+ const baselineRequestToHandle = request => {
51
+ const possibleExternal = resolvePossibleExternal(request);
52
+ if (possibleExternal !== undefined && typeof possibleExternal !== 'string') {
53
+ return possibleExternal.handle;
54
+ }
55
+ return undefined;
56
+ };
57
+ return assumeGlobalizedPlauditLibraries
58
+ ? new dependency_extraction_webpack_plugin_1.default({
59
+ requestToExternal: curryRequestHandlers(baselineRequestToExternal, plauditRequestToExternal),
60
+ requestToHandle: curryRequestHandlers(baselineRequestToHandle, plauditRequestToHandle),
61
+ })
62
+ : new dependency_extraction_webpack_plugin_1.default({
63
+ requestToExternal: baselineRequestToExternal,
64
+ requestToHandle: baselineRequestToHandle,
65
+ });
66
+ }
67
+ const PLAUDIT_NAMESPACE = '@plaudit/';
68
+ const EXTERNALIZABLE_PLAUDIT_LIBRARIES = ['@plaudit/library-extensions'];
69
+ function plauditRequestToExternal(request) {
70
+ if (EXTERNALIZABLE_PLAUDIT_LIBRARIES.includes(request)) {
71
+ return ['plaudit', camelCaseDash(request.substring(PLAUDIT_NAMESPACE.length))];
72
+ }
73
+ else if (request.startsWith('@plaudit/gutenberg-api-extensions')) {
74
+ return ['plaudit', 'gutenbergApiExtensions'];
75
+ }
76
+ return undefined;
77
+ }
78
+ function plauditRequestToHandle(request) {
79
+ if (EXTERNALIZABLE_PLAUDIT_LIBRARIES.includes(request)) {
80
+ return 'plaudit-' + request.substring(PLAUDIT_NAMESPACE.length);
81
+ }
82
+ else if (request.startsWith('@plaudit/gutenberg-api-extensions')) {
83
+ return 'plaudit-gutenberg-api-extensions';
84
+ }
85
+ return undefined;
86
+ }
87
+ function curryRequestHandlers(primary, secondary) {
88
+ return (...args) => primary(...args) ?? secondary(...args);
89
+ }
90
+ /**
91
+ * Copied from @wordpress/dependency-extraction-webpack-plugin for consistency
92
+ */
93
+ function camelCaseDash(string) {
94
+ return string.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
95
+ }
@@ -1,3 +1,4 @@
1
+ import { type Externals } from "./wordpress-scripts-wrapper/dependency-extraction-webpack-plugin-config-builder";
1
2
  import type { Options as PostcssFunctionsOptions } from "postcss-functions";
2
3
  import type { Configuration } from "webpack";
3
4
  interface AdvancedOutputConfig {
@@ -5,14 +6,8 @@ interface AdvancedOutputConfig {
5
6
  withLegacyBlocksIn?: string | undefined;
6
7
  additionalDependencies?: string[];
7
8
  directoryLayout?: 'blocks' | 'extensions';
9
+ assumeGlobalizedPlauditLibraries?: boolean;
8
10
  }
9
- type IndividualExternalDepConfig = string | {
10
- import?: string | [string, ...string[]];
11
- handle: string;
12
- };
13
- type Externals = {
14
- [dep: string]: IndividualExternalDepConfig;
15
- };
16
11
  type PlauditWordpressWebpackConfig = {
17
12
  standaloneBlocks?: boolean;
18
13
  variables?: Record<string, any>;
@@ -23,6 +18,7 @@ type PlauditWordpressWebpackConfig = {
23
18
  functions?: (variables: (name: string) => unknown) => PostcssFunctionsOptions['functions'];
24
19
  };
25
20
  externals?: Externals;
21
+ assumeGlobalizedPlauditLibraries?: boolean;
26
22
  };
27
23
  declare const _default: (config: PlauditWordpressWebpackConfig, webpackConfig?: Configuration[] | Configuration) => Configuration[];
28
24
  export = _default;
@@ -6,6 +6,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
6
6
  const node_path_1 = __importDefault(require("node:path"));
7
7
  const AdditionalDependencyInjectorPlugin_1 = __importDefault(require("./wordpress-scripts-wrapper/AdditionalDependencyInjectorPlugin"));
8
8
  const BlockJSONManagingPlugin_1 = __importDefault(require("./wordpress-scripts-wrapper/BlockJSONManagingPlugin"));
9
+ const dependency_extraction_webpack_plugin_config_builder_1 = require("./wordpress-scripts-wrapper/dependency-extraction-webpack-plugin-config-builder");
9
10
  const ExtensionsConfigFileGeneratorPlugin_1 = __importDefault(require("./wordpress-scripts-wrapper/ExtensionsConfigFileGeneratorPlugin"));
10
11
  const MiniCSSExtractPluginErrorCleaner_1 = __importDefault(require("./wordpress-scripts-wrapper/MiniCSSExtractPluginErrorCleaner"));
11
12
  const VariablesJSMonitorPlugin_1 = __importDefault(require("./wordpress-scripts-wrapper/VariablesJSMonitorPlugin"));
@@ -233,49 +234,6 @@ function parseEntrypointsJSON(dir) {
233
234
  });
234
235
  }
235
236
  }
236
- function makeDependencyExtractionPlugin(externals) {
237
- const exactExternals = {};
238
- const suffixExternals = [];
239
- for (const [key, value] of Object.entries(externals)) {
240
- const normalizedValue = typeof value !== 'string' && value.import === undefined ? { ...value, import: key } : value;
241
- if (key.startsWith("*/")) {
242
- suffixExternals.push([key.substring(1), typeof normalizedValue === 'string' ? { import: normalizedValue, handle: key.substring(2) } : normalizedValue]);
243
- }
244
- else {
245
- exactExternals[key] = normalizedValue;
246
- }
247
- }
248
- const resolvePossibleExternal = (request) => {
249
- if (request in exactExternals) {
250
- return exactExternals[request];
251
- }
252
- for (const [key, value] of suffixExternals) {
253
- if (request.endsWith(key)) {
254
- return value;
255
- }
256
- }
257
- return undefined;
258
- };
259
- return new dependency_extraction_webpack_plugin_1.default({
260
- requestToExternal(request) {
261
- const possibleExternal = resolvePossibleExternal(request);
262
- if (typeof possibleExternal === 'string') {
263
- return possibleExternal;
264
- }
265
- else if (possibleExternal !== undefined) {
266
- return possibleExternal['import'];
267
- }
268
- return undefined;
269
- },
270
- requestToHandle(request) {
271
- const possibleExternal = resolvePossibleExternal(request);
272
- if (possibleExternal !== undefined && typeof possibleExternal !== 'string') {
273
- return possibleExternal.handle;
274
- }
275
- return undefined;
276
- }
277
- });
278
- }
279
237
  function processIndividualWebpackConfig(config, webpackConfig, sources) {
280
238
  let scriptExtension; // This is only used in non-block contexts. It might not actually be necessary, but it is good to have
281
239
  let entrypointFields;
@@ -288,7 +246,7 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
288
246
  scriptExtension = scriptWithoutModuleExtension;
289
247
  entrypointFields = ["editorStyle", "viewStyle", "style", "editorScript", "viewScript", "script"];
290
248
  }
291
- const { standaloneBlocks, variablesFilePath, verbose, externals } = config;
249
+ const { standaloneBlocks, variablesFilePath, verbose, externals, assumeGlobalizedPlauditLibraries } = config;
292
250
  let currentVariables = config.currentVariables;
293
251
  const fixedRules = [
294
252
  replaceDefaultURLProcessing,
@@ -351,13 +309,14 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
351
309
  if (srcIsDirectory && (typeof dest !== 'string' && dest.directoryLayout === 'extensions')) {
352
310
  plugins.push(new ExtensionsConfigFileGeneratorPlugin_1.default(srcRoot));
353
311
  }
354
- if (externals) {
355
- const pluginIndex = plugins.findIndex(plugin => plugin instanceof dependency_extraction_webpack_plugin_1.default);
356
- if (pluginIndex === -1) {
357
- console.error("Cannot apply externals when they have been disabled via CLI flag.");
358
- }
359
- else {
360
- plugins[pluginIndex] = makeDependencyExtractionPlugin(externals);
312
+ const pluginIndex = plugins.findIndex(plugin => plugin instanceof dependency_extraction_webpack_plugin_1.default);
313
+ if (pluginIndex === -1) {
314
+ console.error("Cannot apply externals when they have been disabled via CLI flag. This will greatly increase bundle size and will likely cause the build to file");
315
+ }
316
+ else {
317
+ const builtDependencyExtractionWebpackPlugin = (0, dependency_extraction_webpack_plugin_config_builder_1.makeDependencyExtractionPlugin)(externals, (typeof dest !== 'string' ? dest.assumeGlobalizedPlauditLibraries : undefined) ?? assumeGlobalizedPlauditLibraries);
318
+ if (builtDependencyExtractionWebpackPlugin) {
319
+ plugins[pluginIndex] = builtDependencyExtractionWebpackPlugin;
361
320
  }
362
321
  }
363
322
  if (process.argv.includes('--browser-sync') || process.env['BROWSER_SYNC'] === 'true') {
@@ -510,13 +469,13 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
510
469
  }
511
470
  module.exports = function (config, webpackConfig = require("@wordpress/scripts/config/webpack.config")) {
512
471
  testForDuplicatedEntryPaths(config);
513
- const { standaloneBlocks = false, stats = 'errors-warnings', variables: rawVariables, verbose = process.argv.includes('--verbose') || process.env['VERBOSE'] === 'true', postcss = {}, externals } = config;
472
+ const { standaloneBlocks = false, stats = 'errors-warnings', variables: rawVariables, verbose = process.argv.includes('--verbose') || process.env['VERBOSE'] === 'true', postcss = {}, externals, assumeGlobalizedPlauditLibraries = true } = config;
514
473
  let variablesFilePath = undefined;
515
474
  const currentVariables = rawVariables ?? {};
516
475
  if (!rawVariables) {
517
476
  variablesFilePath = ["variables.js", "src/site/variables.js"].map(p => node_path_1.default.join(process.cwd(), p)).filter(p => node_fs_1.default.existsSync(p))[0];
518
477
  }
519
- const cfg = { currentVariables, postcss, standaloneBlocks, stats, variablesFilePath, verbose, externals };
478
+ const cfg = { currentVariables, postcss, standaloneBlocks, stats, variablesFilePath, verbose, externals, assumeGlobalizedPlauditLibraries };
520
479
  const sources = Array.isArray(config.src) ? config.src.map(s => [s, s]) : Object.entries(config.src);
521
480
  if (Array.isArray(webpackConfig)) {
522
481
  return webpackConfig.toSorted((a, b) => {
package/package.json CHANGED
@@ -1,74 +1,91 @@
1
1
  {
2
- "name": "@plaudit/webpack-extensions",
3
- "version": "2.37.0",
4
- "license": "UNLICENSED",
5
- "scripts": {
6
- "prepublishOnly": "rm -rf build && mkdir build && tsc",
7
- "build": "tsc",
8
- "watch": "tsc -w"
9
- },
10
- "files": [
11
- "/build"
12
- ],
13
- "exports": {
14
- "./wordpress-scripts-wrapper": "./build/wordpress-scripts-wrapper.js"
15
- },
16
- "typesVersions": {
17
- "*": {
18
- "wordpress-scripts-wrapper": [
19
- "build/wordpress-scripts-wrapper.d.ts"
20
- ]
21
- }
22
- },
23
- "devDependencies": {
24
- "@types/browser-sync-webpack-plugin": "^2.2.5",
25
- "@types/postcss-functions": "^4.0.4",
26
- "@types/node": "^22.9.0",
27
- "@types/tapable": "^2.2.7",
28
- "@types/webpack": "^5.28.5",
29
- "@types/webpack-sources": "^3.2.3",
30
- "postcss-load-config": "^4.0.2",
31
- "postcss-loader": "^7.3.4",
32
- "ts-node": "^10.9.2",
33
- "typescript": "^5.6.3"
34
- },
35
- "dependencies": {
36
- "@plaudit/postcss-color-function": "^5.0.0",
37
- "@plaudit/postcss-silent-extend": "^3.0.0",
38
- "@plaudit/postcss-strip-units": "^3.0.0",
39
- "@plaudit/postcss-variables": "^1.0.0",
40
- "@wordpress/dependency-extraction-webpack-plugin": "^6.11.0",
41
- "@wordpress/scripts": "^30.4.0",
42
- "autoprefixer": "^10.4.19",
43
- "browser-sync": "^3.0.3",
44
- "clean-webpack-plugin": "^4.0.0",
45
- "copy-webpack-plugin": "^12.0.2",
46
- "cssnano": "^6.1.2",
47
- "eslint": "^8.57.0",
48
- "eslint-plugin-jsdoc": "^48.2.3",
49
- "fork-ts-checker-webpack-plugin": "^9.0.2",
50
- "http-proxy-middleware": "^3.0.3",
51
- "postcss": "^8.4.39",
52
- "postcss-calc": "^9.0.1",
53
- "postcss-discard-comments": "^6.0.2",
54
- "postcss-fallback": "^0.1.0",
55
- "postcss-functions": "^4.0.2",
56
- "postcss-import": "^16.1.0",
57
- "postcss-inline-svg": "^6.0.0",
58
- "postcss-media-minmax": "^5.0.0",
59
- "postcss-mixins": "6.2.3",
60
- "postcss-nested": "^6.0.1",
61
- "postcss-property-lookup": "^3.0.0",
62
- "postcss-quantity-queries": "^0.5.0",
63
- "postcss-reporter": "^7.1.0",
64
- "postcss-short-position": "^4.0.1",
65
- "postcss-short-size": "^4.0.0",
66
- "postcss-short-spacing": "^4.0.0",
67
- "postcss-simple-vars": "^7.0.1",
68
- "postcss-url": "^10.1.3",
69
- "react": "^18.3.1",
70
- "react-dom": "^18.3.1",
71
- "webpack": "^5.96.1",
72
- "webpack-remove-empty-scripts": "^1.0.4"
73
- }
2
+ "name": "@plaudit/webpack-extensions",
3
+ "version": "2.39.0",
4
+ "license": "UNLICENSED",
5
+ "scripts": {
6
+ "prepublishOnly": "rm -rf build && mkdir build && tsc",
7
+ "build": "tsc",
8
+ "watch": "tsc -w"
9
+ },
10
+ "files": [
11
+ "/build"
12
+ ],
13
+ "exports": {
14
+ "./wordpress-scripts-wrapper": "./build/wordpress-scripts-wrapper.js"
15
+ },
16
+ "typesVersions": {
17
+ "*": {
18
+ "wordpress-scripts-wrapper": [
19
+ "build/wordpress-scripts-wrapper.d.ts"
20
+ ]
21
+ }
22
+ },
23
+ "devDependencies": {
24
+ "@types/browser-sync-webpack-plugin": "^2.2.5",
25
+ "@types/node": "^22.13.10",
26
+ "@types/postcss-functions": "^4.0.4",
27
+ "@types/tapable": "^2.2.7",
28
+ "@types/webpack": "^5.28.5",
29
+ "@types/webpack-sources": "^3.2.3",
30
+ "postcss-load-config": "^4.0.2",
31
+ "postcss-loader": "^7.3.4",
32
+ "ts-node": "^10.9.2",
33
+ "typescript": "^5.8.2"
34
+ },
35
+ "dependencies": {
36
+ "@plaudit/postcss-color-function": "^5.0.0",
37
+ "@plaudit/postcss-silent-extend": "^3.0.0",
38
+ "@plaudit/postcss-strip-units": "^3.0.0",
39
+ "@plaudit/postcss-variables": "^1.1.0",
40
+ "@wordpress/dependency-extraction-webpack-plugin": "^6.20.0",
41
+ "@wordpress/scripts": "^30.13.0",
42
+ "autoprefixer": "^10.4.21",
43
+ "browser-sync": "^3.0.3",
44
+ "clean-webpack-plugin": "^4.0.0",
45
+ "copy-webpack-plugin": "^12.0.2",
46
+ "cssnano": "^6.1.2",
47
+ "eslint": "^8.57.1",
48
+ "eslint-plugin-jsdoc": "^48.11.0",
49
+ "fork-ts-checker-webpack-plugin": "^9.0.2",
50
+ "http-proxy-middleware": "^3.0.3",
51
+ "postcss": "^8.5.3",
52
+ "postcss-calc": "^9.0.1",
53
+ "postcss-discard-comments": "^6.0.2",
54
+ "postcss-fallback": "^0.1.0",
55
+ "postcss-functions": "^4.0.2",
56
+ "postcss-import": "^16.1.0",
57
+ "postcss-inline-svg": "^6.0.0",
58
+ "postcss-media-minmax": "^5.0.0",
59
+ "postcss-mixins": "6.2.3",
60
+ "postcss-nested": "^6.2.0",
61
+ "postcss-property-lookup": "^3.0.0",
62
+ "postcss-quantity-queries": "^0.5.0",
63
+ "postcss-reporter": "^7.1.0",
64
+ "postcss-short-position": "^4.0.1",
65
+ "postcss-short-size": "^4.0.0",
66
+ "postcss-short-spacing": "^4.0.0",
67
+ "postcss-simple-vars": "^7.0.1",
68
+ "postcss-url": "^10.1.3",
69
+ "react": "^18.3.1",
70
+ "react-dom": "^18.3.1",
71
+ "webpack": "^5.98.0",
72
+ "webpack-remove-empty-scripts": "^1.0.4"
73
+ },
74
+ "engines": {
75
+ "node": ">=20"
76
+ },
77
+ "pnpm": {
78
+ "onlyBuiltDependencies": [
79
+ "core-js",
80
+ "core-js-pure"
81
+ ],
82
+ "ignoredBuiltDependencies": [
83
+ "@parcel/watcher"
84
+ ],
85
+ "overrides": {
86
+ "micromatch": "^4",
87
+ "react-autosize-textarea>react": "*",
88
+ "react-autosize-textarea>react-dom": "*"
89
+ }
90
+ }
74
91
  }