@plaudit/webpack-extensions 2.34.1 → 2.35.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.
@@ -2,10 +2,13 @@ import { type Compilation, type Compiler, type WebpackPluginInstance } from "web
2
2
  export default class BlockJSONManagingPlugin implements WebpackPluginInstance {
3
3
  private readonly standaloneBlocks;
4
4
  private readonly processingModules;
5
+ static readonly mappableModuleKeys: readonly ["viewScriptModule", "scriptModule"];
6
+ static readonly mappableNonModuleKeys: readonly ["editorStyle", "style", "viewStyle", "editorScript", "script", "viewScript"];
5
7
  private static readonly mappableKeys;
6
8
  private static readonly blockJsonToEntrypointsMap;
7
9
  private static readonly blockJsonRawDependenciesMap;
8
10
  private static readonly blockJSONAssetSourceDirs;
11
+ private static readonly blockJsonAssetKeyMapping;
9
12
  constructor(standaloneBlocks: boolean, processingModules: boolean);
10
13
  static recordRawDependency(entrypoint: string, dependency: string): void;
11
14
  static recordBlockJSONAssetSourceDir(entrypoint: string, source: string): void;
@@ -16,6 +19,9 @@ export default class BlockJSONManagingPlugin implements WebpackPluginInstance {
16
19
  private static remapReferencedPHPFilesOnKey;
17
20
  private static hashThingForAsset;
18
21
  private static stripFilePrefix;
19
- private static incorporateRemappedValue;
20
- private static deriveAdditionalFilesMappableKey;
22
+ private static buildFakeCompilationAssets;
23
+ private static incorporateRemappedAsset;
24
+ private static remapReferencedAssetFile;
25
+ private static getReferencedFileSlot;
26
+ private static addAssetToBlockJsonKey;
21
27
  }
@@ -11,12 +11,13 @@ const php_serializer_1 = __importDefault(require("./php-serializer"));
11
11
  class BlockJSONManagingPlugin {
12
12
  standaloneBlocks;
13
13
  processingModules;
14
- static mappableKeys = [
15
- "editorStyle", "style", "viewStyle", "editorScript", "script", "viewScript", "viewScriptModule", "scriptModule"
16
- ];
14
+ static mappableModuleKeys = ["viewScriptModule", "scriptModule"];
15
+ static mappableNonModuleKeys = ["editorStyle", "style", "viewStyle", "editorScript", "script", "viewScript"];
16
+ static mappableKeys = [...BlockJSONManagingPlugin.mappableNonModuleKeys, ...BlockJSONManagingPlugin.mappableModuleKeys];
17
17
  static blockJsonToEntrypointsMap = new Map();
18
18
  static blockJsonRawDependenciesMap = new Map();
19
19
  static blockJSONAssetSourceDirs = new Map();
20
+ static blockJsonAssetKeyMapping = new Map();
20
21
  constructor(standaloneBlocks, processingModules) {
21
22
  this.standaloneBlocks = standaloneBlocks;
22
23
  this.processingModules = processingModules;
@@ -34,8 +35,9 @@ class BlockJSONManagingPlugin {
34
35
  apply(compiler) {
35
36
  compiler.hooks.compilation.tap(this.constructor.name, compilation => {
36
37
  compilation.hooks.afterProcessAssets.tap(`${this.constructor.name}_ProcessBlockJSONFiles`, compilationAssets => {
38
+ const testableCompilationAssets = this.processingModules ? BlockJSONManagingPlugin.buildFakeCompilationAssets(compilation) : compilationAssets;
37
39
  const currentBlockJSONAssets = BlockJSONManagingPlugin.blockJSONAssetSourceDirs.entries()
38
- .filter(([name]) => name in compilationAssets)
40
+ .filter(([name]) => name in testableCompilationAssets)
39
41
  .toArray();
40
42
  for (const [name] of currentBlockJSONAssets) {
41
43
  const dependencies = BlockJSONManagingPlugin.blockJsonRawDependenciesMap.get(name);
@@ -71,57 +73,65 @@ class BlockJSONManagingPlugin {
71
73
  }
72
74
  }
73
75
  }
74
- if (this.processingModules) {
75
- // We perform the processing in the non-modules half ONLY because we don't necessarily have all the information we need during the modules half.
76
- for (const [name] of currentBlockJSONAssets) {
77
- compilation.deleteAsset(name); // While the method is called, "deleteAsset", it doesn't actually delete it - just halts emission.
78
- }
79
- return;
80
- }
81
76
  const blockDirConfigData = {};
82
- const remapValue = (value, name) => {
83
- if (value.startsWith("file:")) {
84
- const sourceDir = BlockJSONManagingPlugin.blockJSONAssetSourceDirs.get(name) ?? node_path_1.default.dirname(name);
85
- const inputPath = node_path_1.default.normalize(node_path_1.default.join(sourceDir, value.substring(5)));
86
- const outputAndAdditionalFiles = BlockJSONManagingPlugin.blockJsonToEntrypointsMap.get(name)?.get(inputPath);
87
- if (outputAndAdditionalFiles !== undefined) {
88
- const [output, additionalFiles] = outputAndAdditionalFiles;
89
- const prefix = value.startsWith("./", 5) ? "./" : "";
90
- const relativePath = node_path_1.default.relative(node_path_1.default.dirname(name), output.path);
91
- const res = [`file:${prefix}${relativePath}`, output.hash];
92
- return [res, additionalFiles.map(additionalFile => `file:./${node_path_1.default.relative(node_path_1.default.dirname(name), additionalFile)}`)];
93
- }
94
- }
95
- return [[value, ""], []];
96
- };
97
77
  for (const [name, sourceDir] of currentBlockJSONAssets) {
98
- const assetContents = compilation.assets[name]?.buffer().toString();
78
+ const assetContents = this.processingModules ? node_fs_1.default.readFileSync(testableCompilationAssets[name], 'utf8') : compilation.assets[name]?.buffer().toString();
99
79
  if (!assetContents) {
100
80
  continue;
101
81
  }
102
82
  blockDirConfigData[name] = true;
103
83
  const json = JSON.parse(assetContents);
104
- let compositeHash = "";
105
- const tempMappedKeys = {};
106
- for (const mappableKey of BlockJSONManagingPlugin.mappableKeys) {
84
+ const currentAssetKeyMappings = { directMappings: {}, referencedFiles: {}, compositeHash: "" };
85
+ for (const mappableKey of BlockJSONManagingPlugin[this.processingModules ? 'mappableModuleKeys' : 'mappableNonModuleKeys']) {
107
86
  if (mappableKey in json) {
108
87
  const unmappedValue = json[mappableKey];
109
88
  if (Array.isArray(unmappedValue)) {
110
89
  for (const uv of unmappedValue) {
111
- const [remappedValue, additionalValues] = remapValue(uv, name);
112
- BlockJSONManagingPlugin.incorporateRemappedValue(tempMappedKeys, mappableKey, remappedValue[0], additionalValues);
113
- compositeHash += "~" + remappedValue[1];
90
+ BlockJSONManagingPlugin.incorporateRemappedAsset(currentAssetKeyMappings, mappableKey, ...BlockJSONManagingPlugin.remapReferencedAssetFile(uv, name));
114
91
  }
115
92
  }
116
93
  else if (typeof unmappedValue === 'string') {
117
- const [remappedValue, additionalValues] = remapValue(unmappedValue, name);
118
- BlockJSONManagingPlugin.incorporateRemappedValue(tempMappedKeys, mappableKey, remappedValue[0], additionalValues);
119
- compositeHash += "~" + remappedValue[1];
94
+ BlockJSONManagingPlugin.incorporateRemappedAsset(currentAssetKeyMappings, mappableKey, ...BlockJSONManagingPlugin.remapReferencedAssetFile(unmappedValue, name));
120
95
  }
121
96
  }
122
97
  }
123
- for (const [mappableKey, mappedValue] of Object.entries(tempMappedKeys)) {
124
- json[mappableKey] = mappedValue;
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
+ }
125
135
  }
126
136
  if (json["version"]) {
127
137
  json["version"] = `${json["version"]}-${BlockJSONManagingPlugin.hashThingForAsset(compositeHash)}`;
@@ -279,47 +289,88 @@ class BlockJSONManagingPlugin {
279
289
  static stripFilePrefix(file) {
280
290
  return file.startsWith("file:./") ? file.substring(7) : file;
281
291
  }
282
- static incorporateRemappedValue(mappedKeys, mappableKey, remappedValue, additionalValues) {
283
- if (typeof mappedKeys[mappableKey] === 'string') {
284
- mappedKeys[mappableKey] = [mappedKeys[mappableKey], remappedValue];
292
+ static buildFakeCompilationAssets(compilation) {
293
+ const res = {};
294
+ for (const filePath of compilation.fileDependencies.values()) {
295
+ if (filePath.endsWith("/block.json")) {
296
+ const directory = node_path_1.default.dirname(node_path_1.default.normalize(filePath));
297
+ res[node_path_1.default.join(node_path_1.default.basename(directory), "block.json")] = filePath;
298
+ }
285
299
  }
286
- else if (Array.isArray(mappedKeys[mappableKey])) {
287
- mappedKeys[mappableKey].push(remappedValue);
300
+ return res;
301
+ }
302
+ static incorporateRemappedAsset(cacheableMappedKeys, mappableKey, remappedValue, additionalValues) {
303
+ if (additionalValues.length > 0) {
304
+ const referencedFilesSlot = BlockJSONManagingPlugin.getReferencedFileSlot(mappableKey);
305
+ if (!cacheableMappedKeys.referencedFiles[referencedFilesSlot]) {
306
+ cacheableMappedKeys.referencedFiles[referencedFilesSlot] = [...additionalValues];
307
+ }
308
+ else {
309
+ cacheableMappedKeys.referencedFiles[referencedFilesSlot].push(...additionalValues);
310
+ }
311
+ }
312
+ if (Array.isArray(cacheableMappedKeys.directMappings[mappableKey])) {
313
+ cacheableMappedKeys.directMappings[mappableKey].push(remappedValue[0]);
314
+ }
315
+ else if (typeof cacheableMappedKeys.directMappings[mappableKey] === 'string') {
316
+ cacheableMappedKeys.directMappings[mappableKey] = [cacheableMappedKeys.directMappings[mappableKey], remappedValue[0]];
288
317
  }
289
318
  else {
290
- mappedKeys[mappableKey] = remappedValue;
319
+ cacheableMappedKeys.directMappings[mappableKey] = remappedValue[0];
291
320
  }
292
- if (additionalValues.length) {
293
- const additionalValuesMappableKey = BlockJSONManagingPlugin.deriveAdditionalFilesMappableKey(mappableKey);
294
- if (typeof mappedKeys[additionalValuesMappableKey] === 'string') {
295
- mappedKeys[additionalValuesMappableKey] = [mappedKeys[additionalValuesMappableKey], ...additionalValues];
296
- }
297
- else if (Array.isArray(mappedKeys[additionalValuesMappableKey])) {
298
- mappedKeys[additionalValuesMappableKey].push(...additionalValues);
299
- }
300
- else {
301
- mappedKeys[additionalValuesMappableKey] = additionalValues;
321
+ cacheableMappedKeys.compositeHash += "~" + remappedValue[1];
322
+ }
323
+ static remapReferencedAssetFile(value, name) {
324
+ if (value.startsWith("file:")) {
325
+ const sourceDir = BlockJSONManagingPlugin.blockJSONAssetSourceDirs.get(name) ?? node_path_1.default.dirname(name);
326
+ const inputPath = node_path_1.default.normalize(node_path_1.default.join(sourceDir, value.substring(5)));
327
+ const outputAndAdditionalFiles = BlockJSONManagingPlugin.blockJsonToEntrypointsMap.get(name)?.get(inputPath);
328
+ if (outputAndAdditionalFiles !== undefined) {
329
+ const [output, additionalFiles] = outputAndAdditionalFiles;
330
+ const prefix = value.startsWith("./", 5) ? "./" : "";
331
+ const relativePath = node_path_1.default.relative(node_path_1.default.dirname(name), output.path);
332
+ const res = [`file:${prefix}${relativePath}`, output.hash];
333
+ return [res, additionalFiles.map(additionalFile => `file:./${node_path_1.default.relative(node_path_1.default.dirname(name), additionalFile)}`)];
302
334
  }
303
335
  }
336
+ return [[value, ""], []];
304
337
  }
305
- static deriveAdditionalFilesMappableKey(mappableKey) {
306
- let value;
307
- if (mappableKey.endsWith("tyle")) { // If the original file was a stylesheet, then any additional files will be imported via the script tags
308
- value = this.mappableKeys[this.mappableKeys.indexOf(mappableKey) + 3];
338
+ static getReferencedFileSlot(mappableKey) {
339
+ if (mappableKey.startsWith("editor")) {
340
+ return "editor";
309
341
  }
310
- else if (mappableKey.endsWith("cript")) { // If the original file was a script, then any additional files will be imported via the style tags
311
- value = this.mappableKeys[this.mappableKeys.indexOf(mappableKey) - 3];
342
+ else if (mappableKey.startsWith("view")) {
343
+ return "view";
312
344
  }
313
- else if (mappableKey === "viewScriptModule") {
314
- return "viewStyle";
345
+ else {
346
+ return "both";
347
+ }
348
+ }
349
+ static addAssetToBlockJsonKey(json, mappableKey, asset) {
350
+ if (json[mappableKey] === undefined) {
351
+ if (Array.isArray(asset)) {
352
+ json[mappableKey] = [...asset];
353
+ }
354
+ else {
355
+ json[mappableKey] = asset;
356
+ }
315
357
  }
316
- else if (mappableKey === "scriptModule") {
317
- return "style";
358
+ else if (typeof json[mappableKey] === 'string') {
359
+ if (Array.isArray(asset)) {
360
+ json[mappableKey] = [json[mappableKey], ...asset];
361
+ }
362
+ else {
363
+ json[mappableKey] = [json[mappableKey], asset];
364
+ }
318
365
  }
319
- if (value === undefined) {
320
- throw new webpack_1.WebpackError(`Encountered a mappable key (${mappableKey}) that has additional files but no valid mapping for them`);
366
+ else {
367
+ if (Array.isArray(asset)) {
368
+ json[mappableKey].push(...asset);
369
+ }
370
+ else {
371
+ json[mappableKey].push(asset);
372
+ }
321
373
  }
322
- return value;
323
374
  }
324
375
  }
325
376
  exports.default = BlockJSONManagingPlugin;
@@ -493,7 +493,7 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
493
493
  },
494
494
  stats: config.stats,
495
495
  plugins: copyFiles
496
- ? plugins.map(plugin => plugin.constructor.name === 'CopyPlugin'
496
+ ? plugins.map(plugin => !processingModules && plugin.constructor.name === 'CopyPlugin'
497
497
  ? new copy_webpack_plugin_1.default({ patterns: [{ from: standaloneBlocks ? '**/(block.json|*.(php|twig|svg))' : '**/(block.json|*.(asset\.php|svg))',
498
498
  context: srcRoot, noErrorOnMissing: true }] })
499
499
  : plugin)
@@ -521,7 +521,12 @@ module.exports = function (config, webpackConfig = require("@wordpress/scripts/c
521
521
  const cfg = { currentVariables, postcss, standaloneBlocks, stats, variablesFilePath, verbose, externals };
522
522
  const sources = Array.isArray(config.src) ? config.src.map(s => [s, s]) : Object.entries(config.src);
523
523
  if (Array.isArray(webpackConfig)) {
524
- return webpackConfig.flatMap(wpCfg => processIndividualWebpackConfig(cfg, wpCfg, sources));
524
+ return webpackConfig.toSorted((a, b) => {
525
+ if (a.output?.module) {
526
+ return b.output?.module ? 0 : -1;
527
+ }
528
+ return b.output?.module ? 1 : 0;
529
+ }).flatMap(wpCfg => processIndividualWebpackConfig(cfg, wpCfg, sources));
525
530
  }
526
531
  return processIndividualWebpackConfig(cfg, webpackConfig, sources);
527
532
  };
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@plaudit/webpack-extensions",
3
- "version": "2.34.1",
3
+ "version": "2.35.0",
4
+ "license": "UNLICENSED",
4
5
  "scripts": {
5
6
  "prepublishOnly": "rm -rf build && mkdir build && tsc",
6
7
  "build": "tsc",
@@ -22,31 +23,31 @@
22
23
  "devDependencies": {
23
24
  "@types/browser-sync-webpack-plugin": "^2.2.5",
24
25
  "@types/postcss-functions": "^4.0.4",
25
- "@types/node": "^20.14.11",
26
+ "@types/node": "^22.9.0",
26
27
  "@types/tapable": "^2.2.7",
27
28
  "@types/webpack": "^5.28.5",
28
29
  "@types/webpack-sources": "^3.2.3",
29
30
  "postcss-load-config": "^4.0.2",
30
31
  "postcss-loader": "^7.3.4",
31
32
  "ts-node": "^10.9.2",
32
- "typescript": "^5.6.2"
33
+ "typescript": "^5.6.3"
33
34
  },
34
35
  "dependencies": {
35
36
  "@plaudit/postcss-color-function": "^5.0.0",
36
37
  "@plaudit/postcss-silent-extend": "^3.0.0",
37
38
  "@plaudit/postcss-strip-units": "^3.0.0",
38
39
  "@plaudit/postcss-variables": "^1.0.0",
39
- "@wordpress/dependency-extraction-webpack-plugin": "^6.7.0",
40
- "@wordpress/scripts": "^28.3.0",
40
+ "@wordpress/dependency-extraction-webpack-plugin": "^6.11.0",
41
+ "@wordpress/scripts": "^30.4.0",
41
42
  "autoprefixer": "^10.4.19",
42
- "browser-sync": "^3.0.2",
43
+ "browser-sync": "^3.0.3",
43
44
  "clean-webpack-plugin": "^4.0.0",
44
45
  "copy-webpack-plugin": "^12.0.2",
45
46
  "cssnano": "^6.1.2",
46
47
  "eslint": "^8.57.0",
47
48
  "eslint-plugin-jsdoc": "^48.2.3",
48
49
  "fork-ts-checker-webpack-plugin": "^9.0.2",
49
- "http-proxy-middleware": "^3.0.1-beta.0",
50
+ "http-proxy-middleware": "^3.0.3",
50
51
  "postcss": "^8.4.39",
51
52
  "postcss-calc": "^9.0.1",
52
53
  "postcss-discard-comments": "^6.0.2",
@@ -67,7 +68,7 @@
67
68
  "postcss-url": "^10.1.3",
68
69
  "react": "^18.3.1",
69
70
  "react-dom": "^18.3.1",
70
- "webpack": "^5.92.1",
71
+ "webpack": "^5.96.1",
71
72
  "webpack-remove-empty-scripts": "^1.0.4"
72
73
  }
73
74
  }