@plaudit/webpack-extensions 3.9.4 → 3.10.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/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.10.0] - 2026-06-15
9
+ ### Added
10
+ - Support for emitting namespaced code
11
+
12
+ ### Changed
13
+ - All emitted lazyLoaders to be namespaced
14
+ - This is *technically* a breaking change; however, it's used in a total of three plugins, so I'm just going to update them manually
15
+
16
+ ## [3.9.5] - 2026-06-11
17
+ ### Added
18
+ - Text to the `Error` instances thrown in `pseudo-semaphore.ts`
19
+
8
20
  ## [3.9.4] - 2026-06-10
9
21
  ### Fixed
10
22
  - Libraries externalizing in a way that does not account for the variable potentially being undeclared
@@ -99,7 +99,7 @@ class EnhancedBlockJSONPlugin extends AbstractBiPhasicGroupAndEntryPlugin_1.Abst
99
99
  const lazyLoader = this.dest.lazyLoader;
100
100
  if (lazyLoader) {
101
101
  try {
102
- action = writer => writer.function(lazyLoader, [], generateLoader, { returnType: 'void' });
102
+ action = writer => writer.function(new expressions_1.NamespacedReference(this.config.targetNamespace, lazyLoader, 'function'), [], generateLoader, { returnType: 'void' });
103
103
  }
104
104
  catch (e) {
105
105
  compilation.errors.push((0, shared_1.newWebpackErrorForFile)(["An error occurred while emitting a function for lazily loading blocks", { cause: e }], this.dest.destination));
@@ -168,7 +168,7 @@ class ExtensionsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAndEntryP
168
168
  const lazyLoader = this.dest.lazyLoader;
169
169
  if (lazyLoader) {
170
170
  try {
171
- action = writer => writer.function(lazyLoader, [], generateLoader, { returnType: 'void' });
171
+ action = writer => writer.function(new expressions_1.NamespacedReference(this.config.targetNamespace, lazyLoader, 'function'), [], generateLoader, { returnType: 'void' });
172
172
  }
173
173
  catch (e) {
174
174
  compilation.errors.push((0, shared_1.newWebpackErrorForFile)(["An error occurred while emitting a function for lazily loading extensions", { cause: e }], this.extensionsSrcPath));
@@ -36,10 +36,9 @@ class ExtensionsConfigFileGeneratorPluginV1 extends AbstractBiPhasicGroupAndEntr
36
36
  }
37
37
  }
38
38
  compilation.emitAsset(node_path_1.default.join(this.extensionsDest, "mapping.config"), new webpack_1.sources.RawSource((0, php_writer_1.phpSerialize)(mapping)));
39
- UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, { group: `extensions-config-v1-${this.extensionsDest}`, requiresBaseURI: false, action: writer => {
40
- writer
41
- .use("Plaudit\\Common\\Lib\\GutenbergUtils")
42
- .call("GutenbergUtils::installExtensionsSupport", [expressions_1.Op.concat(expressions_1.Constants.__DIR__, this.extensionsDest)]);
39
+ UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, { group: `extensions-config-v1-${this.extensionsDest}`, requiresBaseURI: false, action: file => {
40
+ file
41
+ .call("Plaudit\\Common\\Lib\\GutenbergUtils::installExtensionsSupport", [expressions_1.Op.concat(expressions_1.Constants.__DIR__, this.extensionsDest)]);
43
42
  } });
44
43
  }
45
44
  }
@@ -68,7 +68,8 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
68
68
  for (const list of Object.values(handleLists)) {
69
69
  list.sort(callItemSorter);
70
70
  }
71
- const writer = new php_writer_1.PHPWriter();
71
+ const file = new php_writer_1.PHPFile();
72
+ const writer = file.getWriter("");
72
73
  if (handleLists.register.length > 0) {
73
74
  if (!this.useUnifiedLoader) {
74
75
  (0, shared_1.emitResolveBaseUriFunction)(writer);
@@ -130,14 +131,14 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
130
131
  return a;
131
132
  }, {}));
132
133
  for (const [lazyLoader, handles] of groupedLazyLoadedHandles) {
133
- writer.function(lazyLoader, [], writer => {
134
+ file.function(new expressions_1.NamespacedReference(this.config.targetNamespace, lazyLoader, 'function'), [], writer => {
134
135
  for (const handle of handles) {
135
136
  writer.call(`wp_enqueue_${handle.type}`, [handle.handle]);
136
137
  }
137
138
  }, { returnType: "void" });
138
139
  }
139
140
  }
140
- (0, shared_1.emitPHPWriterAsAsset)(writer, compilation, "plain-entrypoints-loader.php");
141
+ (0, shared_1.emitPHPWriterAsAsset)(file, compilation, "plain-entrypoints-loader.php");
141
142
  }
142
143
  static addHandlesToHandleLists(type, handles, handleLists) {
143
144
  const defaultPriority = 10;
@@ -49,7 +49,7 @@ class SpecialAssetHandlingPlugin extends AbstractBiPhasicGroupPlugin_1.AbstractB
49
49
  }
50
50
  SpecialAssetHandlingPlugin.semaphore.resolve(this.id, specialAssetData);
51
51
  UnifiedLoaderGenerator_1.UnifiedLoaderGenerator.semaphore.resolve(this.id, Object.keys(specialAssetData).length > 0
52
- ? { group: 'special-assets', requiresBaseURI: true, action: writer => writer.require("/special-assets.php", { dirRelative: true, once: true }) }
52
+ ? { group: 'special-assets', requiresBaseURI: true, action: file => file.require("/special-assets.php", { dirRelative: true, once: true }) }
53
53
  : undefined);
54
54
  }
55
55
  catch (e) {
@@ -1,11 +1,11 @@
1
- import { PHPWriter } from "@plaudit/php-writer";
1
+ import { PHPFile } from "@plaudit/php-writer";
2
2
  import { AbstractBiPhasicGroupPlugin } from "./AbstractBiPhasicGroupPlugin";
3
3
  import type { VerifiedPlauditWordpressWebpackConfig } from "../utils/common-config-helpers";
4
4
  import { PseudoSemaphore } from "../utils/pseduo-semaphore";
5
5
  import { Compilation } from "webpack";
6
6
  export type LoaderInfo = {
7
7
  group: string;
8
- action(writer: PHPWriter): void;
8
+ action(writer: PHPFile): void;
9
9
  requiresBaseURI: boolean;
10
10
  staticallyLoadedEntrypoints?: string[];
11
11
  priority?: number;
@@ -90,36 +90,38 @@ class UnifiedLoaderGenerator extends AbstractBiPhasicGroupPlugin_1.AbstractBiPha
90
90
  }
91
91
  if (this.config.useUnifiedLoader) {
92
92
  compilation.hooks.afterProcessAssets.tap(this.constructor.name, () => {
93
- let writer;
93
+ let phpFile;
94
94
  if (compilation.outputOptions.path?.endsWith("-dev")) {
95
95
  compilation['.gitignore' in compilation.assets ? 'updateAsset' : 'emitAsset']('.gitignore', new webpack_1.sources.RawSource('**'), { size: 2 });
96
96
  this.ensureDistExists(compilation.outputOptions.path);
97
- writer = new php_writer_1.PHPWriter();
97
+ phpFile = new php_writer_1.PHPFile();
98
98
  }
99
99
  else {
100
- writer = this.withDistDevLoader();
100
+ phpFile = this.withDistDevLoader();
101
101
  }
102
102
  if (groupedLoaderInfo.some(wc => wc.requiresBaseURI)) {
103
- (0, shared_1.emitResolveBaseUriFunction)(writer);
103
+ (0, shared_1.emitResolveBaseUriFunction)(phpFile);
104
104
  }
105
105
  for (const { action } of groupedLoaderInfo) {
106
- action(writer);
106
+ action(phpFile);
107
107
  }
108
- (0, shared_1.emitPHPWriterAsAsset)(writer, compilation, "unified-loader.php");
108
+ (0, shared_1.emitPHPWriterAsAsset)(phpFile, compilation, "unified-loader.php");
109
109
  });
110
110
  }
111
111
  });
112
112
  }
113
113
  withDistDevLoader() {
114
114
  if (this.config.omitDistDev) {
115
- return new php_writer_1.PHPWriter();
115
+ return new php_writer_1.PHPFile();
116
116
  }
117
117
  const devLoaderPath = expressions_1.Op.concat(expressions_1.Constants.__DIR__, '-dev/unified-loader.php');
118
- return new php_writer_1.PHPWriter()
118
+ const res = new php_writer_1.PHPFile();
119
+ res.getWriter("")
119
120
  .if(expressions_1.Op.binary(expressions_1.Op.binary(expressions_1.Expr.call('wp_get_environment_type', []), ' === ', 'development'), ' && ', expressions_1.Expr.call('file_exists', [devLoaderPath])))
120
121
  .require(devLoaderPath, { once: true })
121
122
  .append("return;")
122
123
  .endIf();
124
+ return res;
123
125
  }
124
126
  async ensureDistExists(outputPath) {
125
127
  if (outputPath.endsWith("-dev")) {
package/dist/shared.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { PHPWriter } from "@plaudit/php-writer";
1
+ import { PHPFile, PHPWriter } from "@plaudit/php-writer";
2
2
  import type { Options as PostcssFunctionsOptions } from "postcss-functions";
3
3
  import { type AssetInfo, type Compilation, type Configuration, type Entrypoint, WebpackError, type Compiler } from "webpack";
4
4
  import { SourceType } from "./utils/entrypoint-resolution-logic";
@@ -147,6 +147,7 @@ export type PlauditWordpressWebpackConfig = {
147
147
  includePostInitFallback?: boolean;
148
148
  omitDistDev?: boolean;
149
149
  onlyRunPostCSSOnPCSS?: boolean;
150
+ targetNamespace?: string;
150
151
  };
151
152
  export declare function applyStandards(config: PlauditWordpressWebpackConfig): {
152
153
  readonly standard?: "2026-03-13";
@@ -173,6 +174,7 @@ export declare function applyStandards(config: PlauditWordpressWebpackConfig): {
173
174
  readonly includePostInitFallback?: boolean;
174
175
  readonly omitDistDev?: boolean;
175
176
  onlyRunPostCSSOnPCSS?: boolean;
177
+ readonly targetNamespace?: string;
176
178
  };
177
179
  export declare function resolveStandard(standard: PlauditWordpressWebpackConfig['standard']): {
178
180
  readonly useWebpackResourceFiltering: true;
@@ -226,6 +228,7 @@ export type TupleOf<T, N extends number> = N extends N ? number extends N ? T[]
226
228
  type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N ? R : _TupleOf<T, N, [T, ...R]>;
227
229
  export declare function arrayIsLength<T, N extends number>(arr: T[] | null | undefined, length: N): arr is TupleOf<T, N>;
228
230
  export declare function kebabCase(value: string): string;
231
+ export declare function camelCaseForPHPLabels(value: string): string;
229
232
  export declare function loadEnvFile(filePath: string): Promise<Record<string, string>>;
230
233
  export declare function parseEnvFile(contents: string): Record<string, string>;
231
234
  export declare function newCleanWebpackError(error: string | ConstructorParameters<typeof WebpackError>): WebpackError;
@@ -233,7 +236,7 @@ export declare function newWebpackErrorForFile(error: string | ConstructorParame
233
236
  /**
234
237
  * The primary benefit of emitting a function instead of baking its contents into each function that uses it is that it allows us to avoid recomputing the base uri multiple times
235
238
  */
236
- export declare function emitResolveBaseUriFunction(writer: PHPWriter): void;
239
+ export declare function emitResolveBaseUriFunction(writer: PHPFile | PHPWriter): void;
237
240
  export declare function getAssetsJson(compilation: Compilation): ParsedAssetsJson;
238
241
  export type ParsedAssetJsonProvider = (entrypoint: Entrypoint, metadata: MinimumViableMetadata) => {
239
242
  assetName: string;
@@ -243,7 +246,7 @@ export declare function getParsedAssetsJsonDataForEntrypoint(compilation: Compil
243
246
  assetName: string;
244
247
  assetData: ParsedAssetsJson[string];
245
248
  } | undefined;
246
- export declare function emitPHPWriterAsAsset(writer: PHPWriter, compilation: Compilation, file: string, assetInfo?: AssetInfo): void;
249
+ export declare function emitPHPWriterAsAsset(writer: PHPWriter | PHPFile, compilation: Compilation, file: string, assetInfo?: AssetInfo): void;
247
250
  export declare function dedent(text: TemplateStringsArray): string;
248
251
  export declare function resolveLegacyBlockScriptsInFolder(folder: string): string[];
249
252
  /**
package/dist/shared.js CHANGED
@@ -39,6 +39,7 @@ exports.getHandleGroup = getHandleGroup;
39
39
  exports.hasAtLeastOneItem = hasAtLeastOneItem;
40
40
  exports.arrayIsLength = arrayIsLength;
41
41
  exports.kebabCase = kebabCase;
42
+ exports.camelCaseForPHPLabels = camelCaseForPHPLabels;
42
43
  exports.loadEnvFile = loadEnvFile;
43
44
  exports.parseEnvFile = parseEnvFile;
44
45
  exports.newCleanWebpackError = newCleanWebpackError;
@@ -222,6 +223,18 @@ function kebabCase(value) {
222
223
  const kebabCaseRegexes = [[/([a-z])([A-Z])/g, "$1-$2"], [/[\s_.\-]+/g, "-"]];
223
224
  return kebabCaseRegexes.reduce((str, [pattern, replacement]) => str.replace(pattern, replacement), value).toLowerCase();
224
225
  }
226
+ function camelCaseForPHPLabels(value) {
227
+ return value
228
+ .replaceAll("/", "\\")
229
+ .split("\\")
230
+ .map(part => {
231
+ part = part
232
+ .replaceAll(/[^a-zA-Z0-9\x7f-\xff](\w|$)/ig, (_, chr) => typeof chr === 'string' ? chr.toUpperCase() : "")
233
+ .replaceAll(/\d[a-z]/g, match => match.toUpperCase());
234
+ return part.length > 1 ? part.substring(0, 1).toUpperCase() + part.substring(1) : part.toUpperCase();
235
+ })
236
+ .join("\\");
237
+ }
225
238
  async function loadEnvFile(filePath) {
226
239
  return (0, promises_1.readFile)(filePath, 'utf-8').then(parseEnvFile, () => ({}));
227
240
  }
@@ -11,7 +11,7 @@ class PseudoSemaphore {
11
11
  }
12
12
  register(id) {
13
13
  if (this.flags.has(id)) {
14
- throw new Error();
14
+ throw new Error(`A semaphore with an id of "${id}" already exists`);
15
15
  }
16
16
  this.initializeFlag(id);
17
17
  this.resolve(id, undefined);
@@ -45,10 +45,10 @@ class PseudoSemaphore {
45
45
  }
46
46
  getFlag(id) {
47
47
  const flag = this.flags.get(id);
48
- if (flag) {
49
- return flag;
48
+ if (flag === undefined) {
49
+ throw new Error(`A semaphore with an id of "${id}" does not exist`);
50
50
  }
51
- throw new Error();
51
+ return flag;
52
52
  }
53
53
  initializeFlag(id) {
54
54
  const controller = {};
@@ -183,7 +183,7 @@ function buildVerifiedConfig(config) {
183
183
  let targetHandlePrefix = config.targetHandlePrefix ?? config.plainEntrypointsHandlePrefix ?? "";
184
184
  if (plainEntrypointsVersion > 1) {
185
185
  if (!targetHandlePrefix) {
186
- targetHandlePrefix = deriveDefaultHandlePrefixFromComposerJsonOrThemeName();
186
+ targetHandlePrefix = deriveDefaultHandlePrefixFromComposerJsonOrThemeName(shared_1.kebabCase);
187
187
  if (!targetHandlePrefix) {
188
188
  throw new Error("Plain Entrypoints V2 and higher require either 'targetHandlePrefix' to be set or an adjacent composer.json or style.css file to be present");
189
189
  }
@@ -192,6 +192,7 @@ function buildVerifiedConfig(config) {
192
192
  throw new Error("Plain Entrypoints V2 and higher require 'outputDir' to be set");
193
193
  }
194
194
  }
195
+ const targetNamespace = config.targetNamespace || deriveDefaultHandlePrefixFromComposerJsonOrThemeName(shared_1.camelCaseForPHPLabels, true);
195
196
  const { staticEntrypoints, dynamicEntrypoints } = (0, entrypoint_resolution_logic_1.resolveAllConfigLevelEntrypoints)(config);
196
197
  const rawSources = [...staticEntrypoints, ...dynamicEntrypoints];
197
198
  let variablesFilePath = undefined;
@@ -206,7 +207,7 @@ function buildVerifiedConfig(config) {
206
207
  const cfg = {
207
208
  currentVariables, postcss, standaloneBlocks, stats, variablesFilePath, verbose, externals, assumeGlobalizedPlauditLibraries, processTranslationConfigs, combineAssetMetadata,
208
209
  useWebpackResourceFiltering, outputDir, extensionsVersion, plainEntrypointsVersion, srcDir, srcPrefixes, targetHandlePrefix, useUnifiedLoader, includePostInitFallback, omitDistDev,
209
- onlyRunPostCSSOnPCSS
210
+ onlyRunPostCSSOnPCSS, targetNamespace
210
211
  };
211
212
  // Destination -> source map
212
213
  const allocatedDestinations = {};
@@ -287,7 +288,7 @@ function finalizeEntryDestination(entry, dynamicEffectiveDestinationsWithExpecte
287
288
  return [entry[0], { ...entry[1], destination: derivedDestination }];
288
289
  }
289
290
  let defaultHandlePrefix = undefined;
290
- function deriveDefaultHandlePrefixFromComposerJsonOrThemeName() {
291
+ function deriveDefaultHandlePrefixFromComposerJsonOrThemeName(stringTransformer, keepPlauditSep = false) {
291
292
  if (defaultHandlePrefix !== undefined) {
292
293
  return defaultHandlePrefix;
293
294
  }
@@ -297,20 +298,20 @@ function deriveDefaultHandlePrefixFromComposerJsonOrThemeName() {
297
298
  }
298
299
  catch {
299
300
  // Then composer.json doesn't exist
300
- return deriveDefaultHandlePrefixFromThemeName();
301
+ return deriveDefaultHandlePrefixFromThemeName(stringTransformer);
301
302
  }
302
303
  if (typeof composerJson !== 'object' || typeof composerJson.name !== 'string' || !composerJson.name) {
303
304
  throw new ReferenceError("targetHandlePrefix was not set and the adjacent composer.json file does not have a valid name in it");
304
305
  }
305
- return (0, shared_1.kebabCase)(composerJson.name.replace(/plaudit\/plaudit/, 'plaudit'));
306
+ return stringTransformer(keepPlauditSep ? composerJson.name.replace(/plaudit\/plaudit-/, 'plaudit/') : composerJson.name.replace(/plaudit\/plaudit/, 'plaudit'));
306
307
  }
307
- function deriveDefaultHandlePrefixFromThemeName() {
308
+ function deriveDefaultHandlePrefixFromThemeName(stringTransformer) {
308
309
  const styleFileContents = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), "style.css"), 'utf-8');
309
310
  const themeName = /^\W*Theme\s*Name:\s*(.+)$/im.exec(styleFileContents)?.[1]?.trim();
310
311
  if (!themeName) {
311
312
  throw new ReferenceError("targetHandlePrefix was not set and the adjacent style.css file does not have a valid name in it");
312
313
  }
313
- return (0, shared_1.kebabCase)(themeName);
314
+ return stringTransformer(themeName);
314
315
  }
315
316
  function withDerivedOutputDir(cfg, sources) {
316
317
  const destinations = sources.map(([_, { destination }]) => destination.split(/[\/\\]/g));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plaudit/webpack-extensions",
3
- "version": "3.9.4",
3
+ "version": "3.10.0",
4
4
  "license": "SEE LICENSE IN LICENSE.md",
5
5
  "files": [
6
6
  "/dist",
@@ -31,16 +31,18 @@
31
31
  "@plaudit/gutenberg-api-extensions": "^2.97.1",
32
32
  "@types/browser-sync-webpack-plugin": "^2.2.5",
33
33
  "@types/jsdom": "^28.0.3",
34
- "@types/node": "^25.9.2",
34
+ "@types/node": "^25.9.3",
35
35
  "@types/postcss-functions": "^4.0.4",
36
36
  "@types/postcss-import": "^14.0.3",
37
37
  "@types/tapable": "^2.3.0",
38
38
  "@types/webpack-sources": "^3.2.3",
39
+ "react": "^18.3.1",
40
+ "react-dom": "^18.3.1",
39
41
  "typescript": "^6.0.3",
40
42
  "webpack-bundle-analyzer": "^5.3.0"
41
43
  },
42
44
  "dependencies": {
43
- "@plaudit/php-writer": "^1.4.5",
45
+ "@plaudit/php-writer": "^1.5.0",
44
46
  "@plaudit/postcss-color-function": "^5.1.0",
45
47
  "@plaudit/postcss-strip-units": "^3.0.0",
46
48
  "@plaudit/postcss-variables": "^2.0.1",
@@ -52,7 +54,7 @@
52
54
  "css-minimizer-webpack-plugin": "^8.0.0",
53
55
  "cssnano": "^7.1.9",
54
56
  "fork-ts-checker-webpack-plugin": "^9.1.0",
55
- "http-proxy-middleware": "^3.0.6",
57
+ "http-proxy-middleware": "^3.0.7",
56
58
  "jsdom": "^29.1.1",
57
59
  "json2php": "^0.0.12",
58
60
  "postcss": "^8.5.15",