@plaudit/webpack-extensions 2.58.1 → 2.58.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -321,13 +321,16 @@ class BlockJSONManagingPlugin {
321
321
  registerBlockJsonProcessor(compilation) {
322
322
  const blockDirConfigData = {};
323
323
  compilation.hooks.processAssets.tap({ name: `${this.constructor.name}_UnifiedLoaderGeneratorIntegration`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_DERIVED }, () => {
324
- UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, ['block.json', writer => {
324
+ UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, {
325
+ group: 'block.json',
326
+ action: writer => {
325
327
  writer
326
328
  .use("Plaudit\\Common\\ACF\\BlockManager")
327
329
  .action("init", writer => {
328
330
  writer.call("BlockManager::autoloadSubfolders", [new php_writer_1.Expr(`__DIR__.${php_writer_1.Expr.convertJsonToPHP("/" + this.blocksDest)}`)]);
329
331
  });
330
- }]);
332
+ }
333
+ });
331
334
  });
332
335
  compilation.hooks.afterProcessAssets.tap(`${this.constructor.name}_GenerateMetadata`, compilationAssets => {
333
336
  const currentBlockJSONAssets = BlockJSONManagingPlugin.blockJSONAssetSourceDirs.entries()
@@ -1,14 +1,15 @@
1
+ import { VerifiedPlauditWordpressWebpackConfig } from "../utils/common-config-helpers";
1
2
  import { type Compiler, type WebpackPluginInstance } from "webpack";
2
3
  export declare class ExtensionsConfigFileGeneratorPlugin implements WebpackPluginInstance {
4
+ private readonly config;
3
5
  private readonly extensionsPath;
4
- private readonly version;
5
6
  private readonly extensionsDest;
6
- private readonly handlePrefix;
7
7
  private static readonly semaphore;
8
- private static cache;
8
+ private static phaseTwoAttached;
9
9
  private readonly id;
10
- constructor(extensionsPath: string, version: 1 | 2, extensionsDest: string, handlePrefix: string);
10
+ constructor(config: VerifiedPlauditWordpressWebpackConfig, extensionsPath: string, extensionsDest: string);
11
11
  apply(compiler: Compiler): void;
12
+ private generateVersionTwoConfigFile;
12
13
  private makeVersionOneAfterProcessAssets;
13
14
  private stripExtensionsDest;
14
15
  }
@@ -6,25 +6,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ExtensionsConfigFileGeneratorPlugin = void 0;
7
7
  const promises_1 = __importDefault(require("node:fs/promises"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
+ const UnifiedLoaderGenerator_1 = require("./UnifiedLoaderGenerator");
9
10
  const shared_1 = require("../shared");
10
11
  const php_serializer_1 = require("../utils/php-serializer");
12
+ const php_writer_1 = require("../utils/php-writer");
11
13
  const pseduo_semaphore_1 = require("../utils/pseduo-semaphore");
12
14
  const webpack_1 = require("webpack");
13
- const UnifiedLoaderGenerator_1 = require("./UnifiedLoaderGenerator");
14
- const php_writer_1 = require("../utils/php-writer");
15
15
  class ExtensionsConfigFileGeneratorPlugin {
16
+ config;
16
17
  extensionsPath;
17
- version;
18
18
  extensionsDest;
19
- handlePrefix;
20
19
  static semaphore = new pseduo_semaphore_1.PseudoSemaphore({ assets: [], setupFiles: [] }, "Extensions");
21
- static cache = undefined;
20
+ static phaseTwoAttached = false;
22
21
  id;
23
- constructor(extensionsPath, version, extensionsDest, handlePrefix) {
22
+ constructor(config, extensionsPath, extensionsDest) {
23
+ this.config = config;
24
24
  this.extensionsPath = extensionsPath;
25
- this.version = version;
26
25
  this.extensionsDest = extensionsDest;
27
- this.handlePrefix = handlePrefix;
28
26
  this.id = Math.random().toString();
29
27
  ExtensionsConfigFileGeneratorPlugin.semaphore.register(this.id);
30
28
  UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.register(this.id);
@@ -46,86 +44,60 @@ class ExtensionsConfigFileGeneratorPlugin {
46
44
  }
47
45
  await Promise.all(emissionPromises);
48
46
  });
49
- if (this.version === 2) {
50
- const tapName = { name: `${this.constructor.name}_ProcessBlockJSONFiles`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_REPORT };
47
+ if (this.config.extensionsVersion === 2) {
51
48
  compiler.hooks.compilation.tap(this.constructor.name, compilation => {
52
- ExtensionsConfigFileGeneratorPlugin.cache = undefined;
49
+ ExtensionsConfigFileGeneratorPlugin.phaseTwoAttached = false;
53
50
  ExtensionsConfigFileGeneratorPlugin.semaphore.reset(this.id);
54
51
  UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.reset(this.id);
55
- compilation.hooks.processAssets.tap({ name: `${this.constructor.name}_UnifiedLoaderGeneratorIntegration`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_DERIVED }, () => {
56
- UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, ['extensions-config-v2', writer => {
57
- let finalExtensionsDest = this.extensionsDest.endsWith("/") ? this.extensionsDest : this.extensionsDest + "/";
58
- if (!finalExtensionsDest.startsWith("/")) {
59
- finalExtensionsDest = "/" + finalExtensionsDest;
52
+ compilation.hooks.beforeChunkIds.tap(this.constructor.name, () => {
53
+ if (!ExtensionsConfigFileGeneratorPlugin.phaseTwoAttached) {
54
+ ExtensionsConfigFileGeneratorPlugin.phaseTwoAttached = true;
55
+ compilation.hooks.processAssets.tapPromise({ name: `${this.constructor.name}_GenerateConfigFile`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_REPORT }, async () => {
56
+ const combinedExtensionData = (await ExtensionsConfigFileGeneratorPlugin.semaphore.wait())
57
+ .reduce((main, { assets, setupFiles }) => {
58
+ main.assets.push(...assets);
59
+ main.setupFiles.push(...setupFiles);
60
+ return main;
61
+ }, { assets: [], setupFiles: [] });
62
+ if (combinedExtensionData.assets.length > 0 || combinedExtensionData.setupFiles.length > 0) {
63
+ UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, {
64
+ group: 'extensions-config-v2',
65
+ action: writer => {
66
+ let finalExtensionsDest = this.extensionsDest.endsWith("/") ? this.extensionsDest : this.extensionsDest + "/";
67
+ if (!finalExtensionsDest.startsWith("/")) {
68
+ finalExtensionsDest = "/" + finalExtensionsDest;
69
+ }
70
+ writer
71
+ .use("Plaudit\\Base\\API\\ThemeUtils")
72
+ .withScope(writer => writer
73
+ .assign("$filePathPrefix", new php_writer_1.Expr(`__DIR__.${php_writer_1.Expr.convertJsonToPHP(finalExtensionsDest)}`))
74
+ .call("plaudit_webpack_extensions__resolve_base_uri", [new php_writer_1.Expr("$filePathPrefix")], { assignTo: "$fileUriPrefix" })
75
+ .call("ThemeUtils::loadExtensionsV2", [
76
+ new php_writer_1.Expr(`__DIR__.${php_writer_1.Expr.convertJsonToPHP(finalExtensionsDest + "mapping.config.php")}`),
77
+ new php_writer_1.Expr(`$filePathPrefix`), new php_writer_1.Expr("$fileUriPrefix"),
78
+ `${this.config.plainEntrypointsHandlePrefix || node_path_1.default.basename(process.cwd())}_extension_`
79
+ ]));
80
+ }
81
+ });
82
+ this.generateVersionTwoConfigFile(compilation, combinedExtensionData);
60
83
  }
61
- writer
62
- .use("Plaudit\\Base\\API\\ThemeUtils")
63
- .withScope(writer => writer
64
- .assign("$filePathPrefix", new php_writer_1.Expr(`__DIR__.${php_writer_1.Expr.convertJsonToPHP(finalExtensionsDest)}`))
65
- .call("plaudit_webpack_extensions__resolve_base_uri", [new php_writer_1.Expr("$filePathPrefix")], { assignTo: "$fileUriPrefix" })
66
- .call("ThemeUtils::loadExtensionsV2", [
67
- new php_writer_1.Expr(`__DIR__.${php_writer_1.Expr.convertJsonToPHP(finalExtensionsDest + "mapping.config.php")}`),
68
- new php_writer_1.Expr(`$filePathPrefix`), new php_writer_1.Expr("$fileUriPrefix"),
69
- `${this.handlePrefix ? this.handlePrefix : node_path_1.default.basename(process.cwd())}_extension_`
70
- ]));
71
- }]);
84
+ else {
85
+ if (!this.config.useUnifiedLoader) {
86
+ this.generateVersionTwoConfigFile(compilation, combinedExtensionData);
87
+ }
88
+ UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, undefined);
89
+ }
90
+ });
91
+ }
72
92
  });
73
- compilation.hooks.processAssets.tapPromise(tapName, async (assets) => {
93
+ compilation.hooks.processAssets.tapPromise({ name: this.constructor.name, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_ANALYSE, additionalAssets: true }, async (assets) => {
94
+ if (!("assets.json" in assets)) {
95
+ return;
96
+ }
74
97
  try {
75
- //TODO: Add handling of extracted CSS from JS
76
98
  //TODO: It should be possible to use EntryPoints to determine the "original" file
77
- //TODO: Use the version hash of the original file, but not its dependencies for the additional file's "rest" parameter (see BlockJSONManagingPlugin.ts for how to do so)
78
99
  //TODO: There is no reason to not use basically the exact same logic to implement support for this in plain file contexts
79
100
  //TODO: BlockJSONManagingPlugin should be rewritten from scratch to use this method instead of its 15 layers of tracking + syncing
80
- if (ExtensionsConfigFileGeneratorPlugin.cache === undefined) {
81
- ExtensionsConfigFileGeneratorPlugin.cache = { assets: [], setupFiles: [] };
82
- compilation.hooks.afterProcessAssets.tap(`${this.constructor.name}_GenerateConfigFile`, () => {
83
- const regex = /^(.+?)-((?:editor-|view-|)(?:style|script|script-module))\.(?:css|m?js)$/i;
84
- const blockExtensionsConfig = { metadata: { version: this.version }, scriptHandles: {}, styleHandles: {}, blocks: {}, setupFiles: {} };
85
- for (const assetDataSource of ExtensionsConfigFileGeneratorPlugin.cache?.assets ?? []) {
86
- const normalizedAssetData = Object.entries(assetDataSource)
87
- .map(entry => {
88
- const assetPath = this.extensionsDest && entry[0].startsWith(this.extensionsDest + "/")
89
- ? entry[0].substring(this.extensionsDest.length + 1) : entry[0];
90
- return [assetPath, entry[1]];
91
- });
92
- for (const [assetPath, assetData] of normalizedAssetData) {
93
- const match = regex.exec(assetPath);
94
- if (!match) {
95
- continue;
96
- }
97
- const blockSlug = match[1], assetType = match[2];
98
- if (blockSlug && assetType) {
99
- const key = assetType.replace(/-[sm]/gi, chars => chars.substring(1).toUpperCase());
100
- const handle = `plaudit_block-extension_${blockSlug}-${assetType}`;
101
- const isCss = assetType.endsWith("tyle");
102
- blockExtensionsConfig[isCss ? 'styleHandles' : 'scriptHandles'][handle] = {
103
- src: isCss ? assetPath.replace(/\.js$/, ".css") : assetPath,
104
- rest: isCss || key.startsWith("editor")
105
- ? [assetData.dependencies, assetData.version]
106
- : [assetData.dependencies, assetData.version, { strategy: 'defer' }]
107
- };
108
- (blockExtensionsConfig.blocks[blockSlug] ?? (blockExtensionsConfig.blocks[blockSlug] = {}))[key] = handle;
109
- }
110
- }
111
- for (const [blockSlug, asset] of ExtensionsConfigFileGeneratorPlugin.cache?.setupFiles ?? []) {
112
- blockExtensionsConfig.setupFiles[blockSlug] = asset;
113
- }
114
- }
115
- blockExtensionsConfig.scriptHandles = Object.fromEntries(Object.entries(blockExtensionsConfig.scriptHandles)
116
- .toSorted(([a], [b]) => a.localeCompare(b)));
117
- blockExtensionsConfig.styleHandles = Object.fromEntries(Object.entries(blockExtensionsConfig.styleHandles)
118
- .toSorted(([a], [b]) => a.localeCompare(b)));
119
- blockExtensionsConfig.setupFiles = Object.fromEntries(Object.entries(blockExtensionsConfig.setupFiles)
120
- .toSorted(([a], [b]) => a.localeCompare(b)));
121
- blockExtensionsConfig.blocks = Object.fromEntries(Object.entries(blockExtensionsConfig.blocks)
122
- .map(block => {
123
- return [block[0], Object.fromEntries(Object.entries(block[1]).toSorted(([a], [b]) => a.localeCompare(b)))];
124
- })
125
- .toSorted(([a], [b]) => a.localeCompare(b)));
126
- compilation.emitAsset(node_path_1.default.join(this.extensionsDest, "mapping.config.php"), new webpack_1.sources.RawSource((0, shared_1.makeEmittableConfigPHP)(blockExtensionsConfig)));
127
- });
128
- }
129
101
  const myCacheData = { assets: [], setupFiles: [] };
130
102
  for (const asset of Object.keys(compilation.assets).map(asset => this.stripExtensionsDest(asset))) {
131
103
  const blockSlug = /^(.+?)-setup.php$/i.exec(asset)?.[1];
@@ -148,12 +120,6 @@ class ExtensionsConfigFileGeneratorPlugin {
148
120
  myCacheData.assets.push(assetDataSource);
149
121
  compilation.deleteAsset("assets.json");
150
122
  ExtensionsConfigFileGeneratorPlugin.semaphore.resolve(this.id, myCacheData);
151
- ExtensionsConfigFileGeneratorPlugin.cache = (await ExtensionsConfigFileGeneratorPlugin.semaphore.wait())
152
- .reduce((main, { assets, setupFiles }) => {
153
- main.assets.push(...assets);
154
- main.setupFiles.push(...setupFiles);
155
- return main;
156
- }, { assets: [], setupFiles: [] });
157
123
  }
158
124
  catch (e) {
159
125
  ExtensionsConfigFileGeneratorPlugin.semaphore.reject(this.id);
@@ -170,16 +136,62 @@ class ExtensionsConfigFileGeneratorPlugin {
170
136
  compiler.hooks.thisCompilation.tap(this.constructor.name, compilation => {
171
137
  UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.reset(this.id);
172
138
  compilation.hooks.processAssets.tap({ name: `${this.constructor.name}_UnifiedLoaderGeneratorIntegration`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_DERIVED }, () => {
173
- UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, ['extensions-config-v1', writer => {
139
+ UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, { group: 'extensions-config-v1', action: writer => {
174
140
  writer
175
141
  .use("Plaudit\\Base\\API\\ThemeUtils")
176
142
  .call("ThemeUtils::installExtensionSupport", [new php_writer_1.Expr(`__DIR__.${php_writer_1.Expr.convertJsonToPHP(this.extensionsDest)}`)]);
177
- }]);
143
+ } });
178
144
  });
179
145
  compilation.hooks.afterProcessAssets.tap(`${this.constructor.name}_AfterProcessAssets`, this.makeVersionOneAfterProcessAssets(compilation));
180
146
  });
181
147
  }
182
148
  }
149
+ generateVersionTwoConfigFile(compilation, combinedExtensionData) {
150
+ const regex = /^(.+?)-((?:editor-|view-|)(?:style|script|script-module))\.(?:css|m?js)$/i;
151
+ const blockExtensionsConfig = { metadata: { version: this.config.extensionsVersion }, scriptHandles: {}, styleHandles: {}, blocks: {}, setupFiles: {} };
152
+ for (const assetDataSource of combinedExtensionData.assets) {
153
+ const normalizedAssetData = Object.entries(assetDataSource)
154
+ .map(entry => {
155
+ const assetPath = this.extensionsDest && entry[0].startsWith(this.extensionsDest + "/")
156
+ ? entry[0].substring(this.extensionsDest.length + 1) : entry[0];
157
+ return [assetPath, entry[1]];
158
+ });
159
+ for (const [assetPath, assetData] of normalizedAssetData) {
160
+ const match = regex.exec(assetPath);
161
+ if (!match) {
162
+ continue;
163
+ }
164
+ const blockSlug = match[1], assetType = match[2];
165
+ if (blockSlug && assetType) {
166
+ const key = assetType.replace(/-[sm]/gi, chars => chars.substring(1).toUpperCase());
167
+ const handle = `plaudit_block-extension_${blockSlug}-${assetType}`;
168
+ const isCss = assetType.endsWith("tyle");
169
+ blockExtensionsConfig[isCss ? 'styleHandles' : 'scriptHandles'][handle] = {
170
+ src: isCss ? assetPath.replace(/\.js$/, ".css") : assetPath,
171
+ rest: isCss || key.startsWith("editor")
172
+ ? [assetData.dependencies, assetData.version]
173
+ : [assetData.dependencies, assetData.version, { strategy: 'defer' }]
174
+ };
175
+ (blockExtensionsConfig.blocks[blockSlug] ?? (blockExtensionsConfig.blocks[blockSlug] = {}))[key] = handle;
176
+ }
177
+ }
178
+ for (const [blockSlug, asset] of combinedExtensionData.setupFiles) {
179
+ blockExtensionsConfig.setupFiles[blockSlug] = asset;
180
+ }
181
+ }
182
+ blockExtensionsConfig.scriptHandles = Object.fromEntries(Object.entries(blockExtensionsConfig.scriptHandles)
183
+ .toSorted(([a], [b]) => a.localeCompare(b)));
184
+ blockExtensionsConfig.styleHandles = Object.fromEntries(Object.entries(blockExtensionsConfig.styleHandles)
185
+ .toSorted(([a], [b]) => a.localeCompare(b)));
186
+ blockExtensionsConfig.setupFiles = Object.fromEntries(Object.entries(blockExtensionsConfig.setupFiles)
187
+ .toSorted(([a], [b]) => a.localeCompare(b)));
188
+ blockExtensionsConfig.blocks = Object.fromEntries(Object.entries(blockExtensionsConfig.blocks)
189
+ .map(block => {
190
+ return [block[0], Object.fromEntries(Object.entries(block[1]).toSorted(([a], [b]) => a.localeCompare(b)))];
191
+ })
192
+ .toSorted(([a], [b]) => a.localeCompare(b)));
193
+ compilation.emitAsset(node_path_1.default.join(this.extensionsDest, "mapping.config.php"), new webpack_1.sources.RawSource((0, shared_1.makeEmittableConfigPHP)(blockExtensionsConfig)));
194
+ }
183
195
  makeVersionOneAfterProcessAssets(compilation) {
184
196
  return compilationAssets => {
185
197
  const regex = /^(.+?)-((?:editor-|view-|)(?:style|script|script-module))\.(?:css|m?js)$/i;
@@ -8,7 +8,7 @@ export declare class PlainEntrypointsConfigFileGeneratorPlugin implements Webpac
8
8
  private readonly handlePrefix;
9
9
  private readonly useUnifiedLoader;
10
10
  private static readonly semaphore;
11
- private static cache?;
11
+ private static phaseTwoAttached;
12
12
  private readonly id;
13
13
  constructor(buildRoot: string, outputDir: string, usageLocations: UsageLocations, handlePrefix: string, useUnifiedLoader: boolean);
14
14
  apply(compiler: Compiler): void;
@@ -17,7 +17,7 @@ class PlainEntrypointsConfigFileGeneratorPlugin {
17
17
  handlePrefix;
18
18
  useUnifiedLoader;
19
19
  static semaphore = new pseduo_semaphore_1.PseudoSemaphore([], "Plain");
20
- static cache = undefined;
20
+ static phaseTwoAttached = false;
21
21
  id;
22
22
  constructor(buildRoot, outputDir, usageLocations, handlePrefix, useUnifiedLoader) {
23
23
  this.buildRoot = buildRoot;
@@ -30,24 +30,23 @@ class PlainEntrypointsConfigFileGeneratorPlugin {
30
30
  UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.register(this.id);
31
31
  }
32
32
  apply(compiler) {
33
- const tapName = { name: `${this.constructor.name}_ProcessPlainEntrypointFiles`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_REPORT };
34
33
  compiler.hooks.compilation.tap(this.constructor.name, compilation => {
35
- PlainEntrypointsConfigFileGeneratorPlugin.cache = undefined;
34
+ PlainEntrypointsConfigFileGeneratorPlugin.phaseTwoAttached = false;
36
35
  PlainEntrypointsConfigFileGeneratorPlugin.semaphore.reset(this.id);
37
36
  UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.reset(this.id);
38
- compilation.hooks.processAssets.tap({ name: `${this.constructor.name}_UnifiedLoaderGeneratorIntegration`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_DERIVED }, () => {
39
- UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, ['plain-entrypoints-v2', writer => {
40
- writer.append("require_once __DIR__.'/plain-entrypoints-loader.php';");
41
- }]);
37
+ compilation.hooks.beforeChunkIds.tap(this.constructor.name, () => {
38
+ if (!PlainEntrypointsConfigFileGeneratorPlugin.phaseTwoAttached) {
39
+ PlainEntrypointsConfigFileGeneratorPlugin.phaseTwoAttached = true;
40
+ compilation.hooks.processAssets.tapPromise({ name: `${this.constructor.name}_CompileLoader`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_REPORT }, async () => {
41
+ this.afterProcessAssets(compilation, (await PlainEntrypointsConfigFileGeneratorPlugin.semaphore.wait()).flat());
42
+ });
43
+ }
42
44
  });
43
- compilation.hooks.processAssets.tapPromise(tapName, async (assets) => {
45
+ compilation.hooks.processAssets.tapPromise({ name: this.constructor.name, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_ANALYSE, additionalAssets: true }, async (assets) => {
46
+ if (!("assets.json" in assets)) {
47
+ return;
48
+ }
44
49
  try {
45
- if (PlainEntrypointsConfigFileGeneratorPlugin.cache === undefined) {
46
- PlainEntrypointsConfigFileGeneratorPlugin.cache = { assets: [] };
47
- compilation.hooks.afterProcessAssets.tap(`${this.constructor.name}_CompileLoader`, () => {
48
- this.afterProcessAssets(compilation);
49
- });
50
- }
51
50
  const rawAssetDataSource = assets["assets.json"]?.source();
52
51
  if (typeof rawAssetDataSource !== 'string') {
53
52
  PlainEntrypointsConfigFileGeneratorPlugin.semaphore.reject(this.id);
@@ -104,7 +103,9 @@ class PlainEntrypointsConfigFileGeneratorPlugin {
104
103
  }
105
104
  compilation.deleteAsset("assets.json");
106
105
  PlainEntrypointsConfigFileGeneratorPlugin.semaphore.resolve(this.id, myAssetHandles);
107
- PlainEntrypointsConfigFileGeneratorPlugin.cache.assets = (await PlainEntrypointsConfigFileGeneratorPlugin.semaphore.wait()).flat();
106
+ UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, myAssetHandles.length
107
+ ? { group: 'plain-entrypoints-v2', action: writer => writer.append("require_once __DIR__.'/plain-entrypoints-loader.php';") }
108
+ : undefined);
108
109
  }
109
110
  catch (e) {
110
111
  PlainEntrypointsConfigFileGeneratorPlugin.semaphore.reject(this.id);
@@ -114,9 +115,8 @@ class PlainEntrypointsConfigFileGeneratorPlugin {
114
115
  });
115
116
  });
116
117
  }
117
- afterProcessAssets(compilation) {
118
+ afterProcessAssets(compilation, assets) {
118
119
  const emitDir = node_path_1.default.join(this.buildRoot, this.outputDir);
119
- //TODO: Add support for editorStyles via the 'block_editor_settings_all' filter
120
120
  const handleLists = {
121
121
  register: [],
122
122
  clientView: [],
@@ -126,7 +126,7 @@ class PlainEntrypointsConfigFileGeneratorPlugin {
126
126
  customizer: [],
127
127
  analytics: []
128
128
  };
129
- const allNamedHandles = (PlainEntrypointsConfigFileGeneratorPlugin.cache?.assets ?? [])
129
+ const allNamedHandles = assets
130
130
  .flatMap(({ handles }) => handles)
131
131
  .filter((handle) => !!handle.handleName)
132
132
  .sort((a, b) => a.src.localeCompare(b.src));
@@ -137,7 +137,7 @@ class PlainEntrypointsConfigFileGeneratorPlugin {
137
137
  .filter(handle => !handle.isScript)
138
138
  .map(handle => [handle.handleName, handle.src]));
139
139
  const plainEntrypointsConfig = { scriptHandles: {}, styleHandles: {} };
140
- for (const { handles, handlePrefix } of PlainEntrypointsConfigFileGeneratorPlugin.cache?.assets ?? []) {
140
+ for (const { handles, handlePrefix } of assets) {
141
141
  for (const { src, rest, locations, isScript, handleName } of handles) {
142
142
  let finalHandleName;
143
143
  if (handleName) {
@@ -29,12 +29,13 @@ class SpecialAssetHandlingPlugin {
29
29
  SpecialAssetHandlingPlugin.hasAttachedAssetCollatorForCurrentBatch = false;
30
30
  SpecialAssetHandlingPlugin.semaphore.reset(this.id);
31
31
  UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.reset(this.id);
32
- compilation.hooks.processAssets.tap({ name: `${this.constructor.name}_UnifiedLoaderGeneratorIntegration`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_DERIVED }, () => {
33
- UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, ['special-assets', writer => {
34
- writer.append("require_once __DIR__.'/special-assets.php';");
35
- }]);
32
+ compilation.hooks.beforeChunkIds.tap(this.constructor.name, () => {
33
+ if (!SpecialAssetHandlingPlugin.hasAttachedAssetCollatorForCurrentBatch) {
34
+ SpecialAssetHandlingPlugin.hasAttachedAssetCollatorForCurrentBatch = true;
35
+ compilation.hooks.processAssets.tapPromise({ name: `${this.constructor.name}_CompileLoader`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_REPORT }, () => this.collateAssets(compilation));
36
+ }
36
37
  });
37
- compilation.hooks.processAssets.tapPromise(this.constructor.name, async (assets) => {
38
+ compilation.hooks.processAssets.tapPromise({ name: this.constructor.name, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_ANALYSE }, async (assets) => {
38
39
  try {
39
40
  const specialAssetData = {};
40
41
  for (const pathname of Object.keys(assets)) {
@@ -63,12 +64,9 @@ class SpecialAssetHandlingPlugin {
63
64
  }
64
65
  }
65
66
  SpecialAssetHandlingPlugin.semaphore.resolve(this.id, specialAssetData);
66
- if (!SpecialAssetHandlingPlugin.hasAttachedAssetCollatorForCurrentBatch) {
67
- SpecialAssetHandlingPlugin.hasAttachedAssetCollatorForCurrentBatch = true;
68
- const collatedSpecialAssetData = (await SpecialAssetHandlingPlugin.semaphore.wait())
69
- .reduce((collector, current) => ({ ...collector, ...current }), {});
70
- this.collateAssets(compilation, collatedSpecialAssetData);
71
- }
67
+ UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, Object.keys(specialAssetData).length > 0
68
+ ? { group: 'special-assets', action: writer => writer.append("require_once __DIR__.'/special-assets.php';") }
69
+ : undefined);
72
70
  }
73
71
  catch (e) {
74
72
  SpecialAssetHandlingPlugin.semaphore.reject(this.id);
@@ -77,14 +75,18 @@ class SpecialAssetHandlingPlugin {
77
75
  });
78
76
  });
79
77
  }
80
- collateAssets(compilation, collatedSpecialAssetData) {
78
+ async collateAssets(compilation) {
79
+ const collatedSpecialAssetData = (await SpecialAssetHandlingPlugin.semaphore.wait())
80
+ .reduce((collector, current) => ({ ...collector, ...current }), {});
81
81
  const preloadedAssets = Object.entries(collatedSpecialAssetData)
82
82
  .filter(([_, { preload }]) => preload)
83
83
  .sort(([a], [b]) => a.localeCompare(b));
84
84
  const outputFile = this.outputDir ? "special-assets.php" : node_path_1.default.join(node_path_1.default.dirname(node_path_1.default.dirname(SpecialAssetHandlingPlugin.validPathname)), "special-assets.php");
85
85
  const writer = new php_writer_1.PHPWriter();
86
86
  if (!preloadedAssets.length) {
87
- writer.emitAsset(compilation, outputFile);
87
+ if (!this.useUnifiedLoader) {
88
+ writer.emitAsset(compilation, outputFile);
89
+ }
88
90
  return;
89
91
  }
90
92
  if (!this.useUnifiedLoader) {
@@ -1,10 +1,16 @@
1
1
  import { PseudoSemaphore } from "../utils/pseduo-semaphore";
2
2
  import { PHPWriter } from "../utils/php-writer";
3
3
  import { Compiler, WebpackPluginInstance } from "webpack";
4
+ type LoaderInfo = {
5
+ group: string;
6
+ action(writer: PHPWriter): void;
7
+ priority?: number;
8
+ };
4
9
  export declare class UnifiedLoaderGenerator implements WebpackPluginInstance {
5
- static readonly semaphore: PseudoSemaphore<[string, (writer: PHPWriter) => void] | undefined>;
10
+ static readonly semaphore: PseudoSemaphore<LoaderInfo | undefined>;
6
11
  private static attached;
7
12
  private readonly id;
8
13
  constructor();
9
14
  apply(compiler: Compiler): void;
10
15
  }
16
+ export {};
@@ -23,8 +23,15 @@ class UnifiedLoaderGenerator {
23
23
  UnifiedLoaderGenerator.semaphore.resolve(this.id, undefined);
24
24
  if (!UnifiedLoaderGenerator.attached) {
25
25
  UnifiedLoaderGenerator.attached = true;
26
- const writerCallbacks = Object.values(Object.fromEntries((await UnifiedLoaderGenerator.semaphore.wait())
27
- .filter(a => a !== undefined))); // A simple deduplication trick
26
+ const alreadyAllocatedGroups = new Set();
27
+ const writerCallbacks = (await UnifiedLoaderGenerator.semaphore.wait())
28
+ .filter((a) => a !== undefined)
29
+ .sort((a, b) => {
30
+ const ap = a.priority ?? 0, bp = b.priority ?? 0;
31
+ return ap === bp ? a.group.localeCompare(b.group) : bp - ap;
32
+ })
33
+ .filter(a => !alreadyAllocatedGroups.has(a.group) && alreadyAllocatedGroups.add(a.group))
34
+ .map(a => a.action);
28
35
  if (writerCallbacks.length > 0) {
29
36
  compilation.hooks.afterProcessAssets.tap(this.constructor.name, () => {
30
37
  const writer = new php_writer_1.PHPWriter();
@@ -115,6 +115,7 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
115
115
  if (!dirent.isDirectory()) {
116
116
  continue;
117
117
  }
118
+ //TODO: Instead of doing all of this in a precalc phase, add block.json "entrypoints" with their library type set to "block-json"
118
119
  const dir = joinPossiblyAbsolutePaths(srcRoot, dirent.name);
119
120
  loadingEntrypoints.push(new Promise(async (resolve) => {
120
121
  const rawEntrypoints = [];
@@ -497,7 +497,7 @@ function makeBlocksWebpackConfig(config, commonConfig, webpackConfig, dest, src,
497
497
  return (0, common_config_helpers_1.commonMakeWebpackConfig)(config, commonConfig, webpackConfig, true, dest, src, srcRoot, (0, common_config_helpers_1.resolveEntryFromDirectory)(commonConfig, srcRoot, dest), plugins);
498
498
  }
499
499
  function makeExtensionsWebpackConfig(config, commonConfig, webpackConfig, dest, src, srcRoot, plugins) {
500
- plugins.push(new ExtensionsConfigFileGeneratorPlugin_1.ExtensionsConfigFileGeneratorPlugin(srcRoot, config.extensionsVersion, dest.destination, config.plainEntrypointsHandlePrefix));
500
+ plugins.push(new ExtensionsConfigFileGeneratorPlugin_1.ExtensionsConfigFileGeneratorPlugin(config, srcRoot, dest.destination));
501
501
  const entry = async () => {
502
502
  const rawEntrypoints = [];
503
503
  for await (const dirent of await promises_1.default.opendir(srcRoot)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plaudit/webpack-extensions",
3
- "version": "2.58.1",
3
+ "version": "2.58.2",
4
4
  "license": "UNLICENSED",
5
5
  "files": [
6
6
  "/build"
@@ -18,7 +18,7 @@
18
18
  "devDependencies": {
19
19
  "@plaudit/gutenberg-api-extensions": "^2.75.0",
20
20
  "@types/browser-sync-webpack-plugin": "^2.2.5",
21
- "@types/node": "^22.17.1",
21
+ "@types/node": "^24.3.0",
22
22
  "@types/postcss-functions": "^4.0.4",
23
23
  "@types/tapable": "^2.2.7",
24
24
  "@types/webpack": "^5.28.5",