@plaudit/webpack-extensions 3.16.0 → 3.18.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.
Files changed (32) hide show
  1. package/CHANGELOG.md +88 -1
  2. package/README.md +22 -2
  3. package/USER-GUIDE.md +21 -16
  4. package/dist/plugins/AbstractBiPhasicGroupAndEntryPlugin.d.ts +1 -1
  5. package/dist/plugins/AbstractBiPhasicGroupPlugin.d.ts +3 -3
  6. package/dist/plugins/EnhancedBlockJSONPlugin.d.ts +1 -0
  7. package/dist/plugins/EnhancedBlockJSONPlugin.js +36 -25
  8. package/dist/plugins/MiniCSSExtractPluginErrorCleaner.d.ts +2 -3
  9. package/dist/plugins/PackageConfigSanityChecker.d.ts +2 -3
  10. package/dist/plugins/PlainEntrypointsConfigFileGeneratorPlugin.js +22 -9
  11. package/dist/plugins/VariablesJSMonitorPlugin.d.ts +2 -3
  12. package/dist/plugins/WPMLConfigBuilder.d.ts +2 -3
  13. package/dist/plugins/dependency-extraction-webpack-plugin-config-builder.d.ts +3 -6
  14. package/dist/plugins/dependency-extraction-webpack-plugin-config-builder.js +8 -21
  15. package/dist/shared.d.ts +24 -24
  16. package/dist/shared.js +41 -54
  17. package/dist/utils/common-config-helpers.d.ts +2 -2
  18. package/dist/utils/common-config-helpers.js +21 -13
  19. package/dist/utils/css-writer.js +3 -3
  20. package/dist/utils/entrypoint-resolution-logic.d.ts +5 -2
  21. package/dist/utils/location-encoding-filename-parser.d.ts +0 -1
  22. package/dist/utils/location-encoding-filename-parser.js +4 -3
  23. package/dist/utils/path-query-and-related-helpers.d.ts +0 -1
  24. package/dist/utils/path-query-and-related-helpers.js +0 -4
  25. package/dist/wordpress-ports/dependency-extraction-webpack-plugin/index.d.ts +72 -0
  26. package/dist/wordpress-ports/dependency-extraction-webpack-plugin/index.js +522 -0
  27. package/dist/wordpress-ports/dependency-extraction-webpack-plugin/util.d.ts +56 -0
  28. package/dist/wordpress-ports/dependency-extraction-webpack-plugin/util.js +150 -0
  29. package/dist/wordpress-scripts-wrapper.js +151 -89
  30. package/package.json +32 -8
  31. package/dist/plugins/BrowserSyncPlugin.d.ts +0 -25
  32. package/dist/plugins/BrowserSyncPlugin.js +0 -212
package/dist/shared.d.ts CHANGED
@@ -1,21 +1,24 @@
1
1
  import { PHPFile, PHPWriter } from "@plaudit/php-writer";
2
2
  import { HereOrNowDoc } from "@plaudit/php-writer/expressions";
3
3
  import type { Options as PostcssFunctionsOptions } from "postcss-functions";
4
- import { type AssetInfo, type Compilation, type Configuration, type Entrypoint, WebpackError, type Compiler } from "webpack";
4
+ import { type AssetInfo, type Compilation, type Configuration, type Entrypoint, WebpackError } from "webpack";
5
5
  import { SourceType } from "./utils/entrypoint-resolution-logic";
6
6
  import type { NormalizedEnqueuingControlFlags } from "./utils/path-query-and-related-helpers";
7
7
  export * from "./utils/entrypoint-resolution-logic";
8
- export type WPModuleDependency = {
8
+ export type WPModuleDependency = string | {
9
9
  id: string;
10
10
  import?: string;
11
11
  };
12
- export type ParsedAssetsJson = Record<string, {
13
- dependencies: string[];
12
+ export type ParsedAssetJson = {
13
+ dependencies: WPModuleDependency[];
14
+ module_dependencies?: WPModuleDependency[];
14
15
  version: string;
15
- module_dependencies?: (string | WPModuleDependency)[];
16
- }>;
16
+ type?: 'module';
17
+ handle?: string;
18
+ };
19
+ export type ParsedAssetsJson = Record<string, ParsedAssetJson>;
17
20
  export declare function isParsedAssetsJson(thing: any): thing is ParsedAssetsJson;
18
- type BaseRestType = [/* dependencies: */ string[], /* version: */ string];
21
+ type BaseRestType = [/* dependencies: */ WPModuleDependency[], /* version: */ string];
19
22
  export type AssetMetaSegment = {
20
23
  inlinedAsset: InlinedAsset;
21
24
  assetContents: string;
@@ -28,7 +31,7 @@ export type ScriptArgsObject = {
28
31
  strategy?: 'defer' | 'async';
29
32
  in_footer?: boolean;
30
33
  fetchpriority?: 'auto' | 'low' | 'high';
31
- module_dependencies?: (string | WPModuleDependency)[];
34
+ module_dependencies?: WPModuleDependency[];
32
35
  };
33
36
  export type InlinedAsset = {
34
37
  position?: 'before' | 'after';
@@ -102,9 +105,6 @@ export declare function constantEntries<K extends string, V>(object: {
102
105
  [k in K]: V;
103
106
  }): [K, V][];
104
107
  export declare function determineCurrentSourceType(dest: string | AdvancedOutputConfig, srcIsDirectory: boolean): SourceType;
105
- export interface WebpackPlugin {
106
- apply(compiler: Compiler): void;
107
- }
108
108
  export type ObjectIndividualExternalDepConfig = {
109
109
  import?: string | [string, ...string[]];
110
110
  handle: string;
@@ -120,16 +120,16 @@ export type AdvancedOutputConfig = {
120
120
  directoryLayout?: SourceType;
121
121
  assumeGlobalizedPlauditLibraries?: boolean;
122
122
  externalize?: Required<Configuration>['output']['library'];
123
- bundleAnalyzer?: boolean;
123
+ bundleAnalyzer?: boolean | 'no-auto-open';
124
124
  locations?: UsageLocations | UsageLocations['handle'];
125
125
  lazyLoader?: string;
126
- pathQueryParameters?: PathQueryParameters;
127
126
  enqueuingFlags?: NormalizedEnqueuingControlFlags;
128
127
  };
129
- type OptionalCfgFields = 'directoryLayout' | 'externalize' | 'lazyLoader' | 'pathQueryParameters';
128
+ type OptionalCfgFields = 'directoryLayout' | 'externalize' | 'lazyLoader';
130
129
  export type VerifiedAdvancedOutputConfig = Required<Omit<AdvancedOutputConfig, 'locations' | 'enqueuingFlags' | OptionalCfgFields>> & Pick<AdvancedOutputConfig, OptionalCfgFields> & {
131
130
  enqueuingFlags: NormalizedEnqueuingControlFlags | undefined;
132
131
  locations: NormalizedUsageLocations;
132
+ pathQueryParameters?: PathQueryParameters;
133
133
  };
134
134
  export type SourcesObject = Record<string, string | AdvancedOutputConfig | boolean>;
135
135
  export type PlauditWordpressWebpackConfig = {
@@ -144,8 +144,6 @@ export type PlauditWordpressWebpackConfig = {
144
144
  };
145
145
  externals?: Externals;
146
146
  assumeGlobalizedPlauditLibraries?: boolean;
147
- processTranslationConfigs?: boolean;
148
- combineAssetMetadata?: boolean;
149
147
  useWebpackResourceFiltering?: boolean;
150
148
  outputDir?: string;
151
149
  extensionsVersion?: 1 | 2 | 3;
@@ -160,6 +158,13 @@ export type PlauditWordpressWebpackConfig = {
160
158
  targetNamespace?: string;
161
159
  useBlockSupportsAsThemeJsonDefaults?: boolean;
162
160
  };
161
+ /** Unified-loader watch output: `dist` → `dist-dev` when SERVER_MODE is development. */
162
+ export declare function shouldWriteDistDev(config: Pick<PlauditWordpressWebpackConfig, 'outputDir' | 'useUnifiedLoader' | 'omitDistDev'>): boolean;
163
+ /**
164
+ * This MUST be kept in sync with the copy in @plaudit/dev-webpack-plugin
165
+ * @returns true for `dist-dev` (or any `*-dev` output folder produced by {@link shouldWriteDistDev}).
166
+ */
167
+ export declare function isDistDevOutputPath(outputPath: string): boolean;
163
168
  export declare function applyStandards(config: PlauditWordpressWebpackConfig): {
164
169
  readonly standard?: "2026-03-13";
165
170
  readonly standaloneBlocks?: boolean;
@@ -172,8 +177,6 @@ export declare function applyStandards(config: PlauditWordpressWebpackConfig): {
172
177
  };
173
178
  readonly externals?: Externals;
174
179
  readonly assumeGlobalizedPlauditLibraries?: boolean;
175
- readonly processTranslationConfigs?: boolean;
176
- readonly combineAssetMetadata?: boolean;
177
180
  useWebpackResourceFiltering?: boolean;
178
181
  outputDir?: string;
179
182
  extensionsVersion?: 1 | 2 | 3;
@@ -219,8 +222,7 @@ export type MinimumViableMetadata = {
219
222
  dest: VerifiedAdvancedOutputConfig;
220
223
  absoluteSrc: string;
221
224
  };
222
- export declare function convertUsageLocationsHandleToEmittableHandle(handle: UsageLocations['handle'], handlePrefix: string, generatedNiceName: string): string;
223
- export declare function convertUsageLocationsHandleToEmittableHandleSuffix(handle: UsageLocations['handle'], generatedNiceName: string): string;
225
+ export declare function convertUsageLocationsHandleToEmittableHandle(handle: UsageLocations['handle'], handlePrefix: string, handleSuffix: string): string;
224
226
  export declare function makeEmittableConfigPHP(data: any, asFullFile: boolean, parentIndent?: string): string;
225
227
  export declare const entrypointFields: readonly ["editorStyle", "viewStyle", "style", "editorScript", "viewScript", "script", "viewScriptModule"];
226
228
  export type EntrypointFields = (typeof entrypointFields[number])[];
@@ -233,7 +235,7 @@ export declare const styleExtension: RegExp;
233
235
  export declare function scriptOrStyleTest(entryPath: string, scriptExtension: RegExp): "script" | "style" | "";
234
236
  export declare function isStyleField(field: string): field is 'style' | 'viewStyle' | 'editorStyle';
235
237
  export declare function isScriptModuleField(field: string): field is 'viewScriptModule';
236
- export declare function mergeModuleDependencyArrays(a: (string | WPModuleDependency)[] | undefined, b: (string | WPModuleDependency)[] | undefined): (string | WPModuleDependency)[] | undefined;
238
+ export declare function mergeModuleDependencyArrays(a: WPModuleDependency[] | undefined, b: WPModuleDependency[] | undefined): WPModuleDependency[] | undefined;
237
239
  export declare function getHandleGroup(field: string): 'styleHandles' | 'scriptHandles' | 'scriptModuleHandles';
238
240
  export type StripFirstTwoItems<A extends any[]> = A extends [any, any, ...rest: infer R] ? R : never;
239
241
  export declare function hasAtLeastOneItem<T>(list: T[]): list is [T, ...T[]];
@@ -242,8 +244,6 @@ type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N
242
244
  export declare function arrayIsLength<T, N extends number>(arr: T[] | null | undefined, length: N): arr is TupleOf<T, N>;
243
245
  export declare function kebabCase(value: string): string;
244
246
  export declare function camelCaseForPHPLabels(value: string): string;
245
- export declare function loadEnvFile(filePath: string): Promise<Record<string, string>>;
246
- export declare function parseEnvFile(contents: string): Record<string, string>;
247
247
  export declare function newCleanWebpackError(error: string | ConstructorParameters<typeof WebpackError>): WebpackError;
248
248
  export declare function newWebpackErrorForFile(error: string | ConstructorParameters<typeof WebpackError>, file: string): WebpackError;
249
249
  /**
@@ -260,7 +260,7 @@ export declare function getParsedAssetsJsonDataForEntrypoint(compilation: Compil
260
260
  assetData: ParsedAssetsJson[string];
261
261
  } | undefined;
262
262
  export declare function emitPHPWriterAsAsset(writer: PHPWriter | PHPFile, compilation: Compilation, file: string, assetInfo?: AssetInfo): void;
263
- export declare function dedent(text: TemplateStringsArray): string;
263
+ export declare function dedent(text: TemplateStringsArray, ...values: unknown[]): string;
264
264
  export declare function resolveLegacyBlockScriptsInFolder(folder: string): string[];
265
265
  /**
266
266
  * @param compilation
package/dist/shared.js CHANGED
@@ -25,10 +25,11 @@ exports.isNormalizedUsageLocations = isNormalizedUsageLocations;
25
25
  exports.constantKeys = constantKeys;
26
26
  exports.constantEntries = constantEntries;
27
27
  exports.determineCurrentSourceType = determineCurrentSourceType;
28
+ exports.shouldWriteDistDev = shouldWriteDistDev;
29
+ exports.isDistDevOutputPath = isDistDevOutputPath;
28
30
  exports.applyStandards = applyStandards;
29
31
  exports.resolveStandard = resolveStandard;
30
32
  exports.convertUsageLocationsHandleToEmittableHandle = convertUsageLocationsHandleToEmittableHandle;
31
- exports.convertUsageLocationsHandleToEmittableHandleSuffix = convertUsageLocationsHandleToEmittableHandleSuffix;
32
33
  exports.makeEmittableConfigPHP = makeEmittableConfigPHP;
33
34
  exports.convertEntrypointFieldForAssetType = convertEntrypointFieldForAssetType;
34
35
  exports.leadingSlashIt = leadingSlashIt;
@@ -41,8 +42,6 @@ exports.hasAtLeastOneItem = hasAtLeastOneItem;
41
42
  exports.arrayIsLength = arrayIsLength;
42
43
  exports.kebabCase = kebabCase;
43
44
  exports.camelCaseForPHPLabels = camelCaseForPHPLabels;
44
- exports.loadEnvFile = loadEnvFile;
45
- exports.parseEnvFile = parseEnvFile;
46
45
  exports.newCleanWebpackError = newCleanWebpackError;
47
46
  exports.newWebpackErrorForFile = newWebpackErrorForFile;
48
47
  exports.emitResolveBaseUriFunction = emitResolveBaseUriFunction;
@@ -58,7 +57,6 @@ exports.instanceOfNodeError = instanceOfNodeError;
58
57
  exports.shouldBeSkipped = shouldBeSkipped;
59
58
  const node_crypto_1 = require("node:crypto");
60
59
  const node_fs_1 = require("node:fs");
61
- const promises_1 = require("node:fs/promises");
62
60
  const node_path_1 = __importDefault(require("node:path"));
63
61
  const php_writer_1 = require("@plaudit/php-writer");
64
62
  const expressions_1 = require("@plaudit/php-writer/expressions");
@@ -87,7 +85,7 @@ exports.standardLocationNamesMeta = {
87
85
  analytics: { action: "plaudit_enqueue_analytics" },
88
86
  };
89
87
  function isStandardLocationName(name) {
90
- return name in exports.standardLocationNamesMeta;
88
+ return Object.hasOwn(exports.standardLocationNamesMeta, name);
91
89
  }
92
90
  function isRegisterScriptArgsShorthandName(name) {
93
91
  return ['lazy', 'eager', 'inline'].includes(name);
@@ -117,6 +115,17 @@ function determineCurrentSourceType(dest, srcIsDirectory) {
117
115
  return dest.directoryLayout;
118
116
  }
119
117
  }
118
+ /** Unified-loader watch output: `dist` → `dist-dev` when SERVER_MODE is development. */
119
+ function shouldWriteDistDev(config) {
120
+ return !!(config.outputDir && config.useUnifiedLoader && !config.omitDistDev && (process.env['SERVER_MODE'] ?? 'development') === 'development');
121
+ }
122
+ /**
123
+ * This MUST be kept in sync with the copy in @plaudit/dev-webpack-plugin
124
+ * @returns true for `dist-dev` (or any `*-dev` output folder produced by {@link shouldWriteDistDev}).
125
+ */
126
+ function isDistDevOutputPath(outputPath) {
127
+ return node_path_1.default.basename(outputPath.replace(/[/\\]+$/, '')).endsWith('-dev');
128
+ }
120
129
  function applyStandards(config) {
121
130
  switch (config.standard) {
122
131
  case '2026-03-13':
@@ -146,37 +155,23 @@ function resolveStandard(standard) {
146
155
  return undefined;
147
156
  }
148
157
  }
149
- function convertUsageLocationsHandleToEmittableHandle(handle, handlePrefix, generatedNiceName) {
150
- let emittableHandle;
151
- if (!handle) {
152
- return `${handlePrefix}/${generatedNiceName}`;
153
- }
154
- if (typeof handle === 'string') {
155
- emittableHandle = handle;
156
- }
157
- else if (typeof handle === 'function') {
158
- emittableHandle = handle(`${handlePrefix}/${generatedNiceName}`);
159
- }
160
- else {
161
- emittableHandle = `${handlePrefix}/${handle.niceName}`;
162
- }
163
- return emittableHandle.replaceAll("{basename}", generatedNiceName);
164
- }
165
- function convertUsageLocationsHandleToEmittableHandleSuffix(handle, generatedNiceName) {
158
+ function convertUsageLocationsHandleToEmittableHandle(handle, handlePrefix, handleSuffix) {
159
+ const generatedHandle = `${handlePrefix}/${handleSuffix}`;
166
160
  let emittableHandle;
167
161
  if (!handle) {
168
- return generatedNiceName;
162
+ return generatedHandle;
169
163
  }
170
164
  if (typeof handle === 'string') {
171
165
  emittableHandle = handle;
172
166
  }
173
167
  else if (typeof handle === 'function') {
174
- emittableHandle = handle(generatedNiceName);
168
+ emittableHandle = handle(generatedHandle);
175
169
  }
176
170
  else {
177
- emittableHandle = handle.niceName;
171
+ emittableHandle = handle.niceName && `${handlePrefix}/${handle.niceName}`;
178
172
  }
179
- return emittableHandle.replaceAll("{basename}", generatedNiceName);
173
+ // A callback is free to return nothing, which means "use the handle you would have generated"
174
+ return emittableHandle ? emittableHandle.replaceAll("{basename}", handleSuffix) : generatedHandle;
180
175
  }
181
176
  function makeEmittableConfigPHP(data, asFullFile, parentIndent = "") {
182
177
  const prettyPrintedMetadata = php_writer_1.json2php.make({ indent: "\t", linebreak: "\n", shortArraySyntax: true })(data, parentIndent)
@@ -266,17 +261,6 @@ function camelCaseForPHPLabels(value) {
266
261
  })
267
262
  .join("\\");
268
263
  }
269
- async function loadEnvFile(filePath) {
270
- return (0, promises_1.readFile)(filePath, 'utf-8').then(parseEnvFile, () => ({}));
271
- }
272
- function parseEnvFile(contents) {
273
- return Object.fromEntries(contents.split(/(\r?\n)+/).map(line => line.trim())
274
- .filter(line => line.length > 0 && !line.startsWith("#") && !line.startsWith("//"))
275
- .map(line => {
276
- const equalsPos = line.indexOf('=');
277
- return equalsPos === -1 ? [line, ""] : [line.substring(0, equalsPos), line.substring(equalsPos + 1)];
278
- }));
279
- }
280
264
  function newCleanWebpackError(error) {
281
265
  const res = typeof error === 'string' ? new webpack_1.WebpackError(error) : new webpack_1.WebpackError(...error);
282
266
  res.hideStack = true;
@@ -313,18 +297,10 @@ function emitResolveBaseUriFunction(writer) {
313
297
  }
314
298
  function getAssetsJson(compilation) {
315
299
  const asset = compilation.getAsset("assets.json");
316
- if (!asset) {
317
- throw new Error("assets.json is unexpectedly missing");
318
- }
319
- if (isParsedAssetsJson(asset.info["parsed-assets-json"])) {
300
+ if (asset && isParsedAssetsJson(asset.info["parsed-assets-json"])) {
320
301
  return asset.info["parsed-assets-json"];
321
302
  }
322
- const parsedAssetJson = JSON.parse(asset.source.source().toString('utf-8'));
323
- if (!isParsedAssetsJson(parsedAssetJson)) {
324
- throw new Error("assets.json is does not match the RawAssetData format");
325
- }
326
- compilation.updateAsset("assets.json", s => s, a => ({ ...a, "parsed-assets-json": parsedAssetJson }));
327
- return parsedAssetJson;
303
+ throw new Error("assets.json is unexpectedly missing");
328
304
  }
329
305
  function getParsedAssetsJsonDataForEntrypoint(compilation, entrypoint, metadata) {
330
306
  const dest = metadata.dest;
@@ -364,13 +340,24 @@ function emitPHPWriterAsAsset(writer, compilation, file, assetInfo) {
364
340
  const contents = writer.toString() + "\n";
365
341
  compilation[file in compilation.assets ? 'updateAsset' : 'emitAsset'](file, new webpack_1.sources.RawSource(contents), { size: Buffer.byteLength(contents), ...assetInfo });
366
342
  }
367
- function dedent(text) {
368
- const actualText = text.join("\n");
369
- const firstLineIndent = actualText.split("\r?\n").find(line => line.length > 0)?.match(/^\s+/)?.[0];
370
- if (!firstLineIndent) {
371
- return actualText;
372
- }
373
- return actualText.replaceAll(new RegExp("^" + firstLineIndent, 'mg'), "").replace(/\n{2}$/, "\n");
343
+ function dedent(text, ...values) {
344
+ const lines = text.reduce((result, part, i) => result + String(values[i - 1]) + part).split(/\r?\n/);
345
+ // A template that opens and closes on its own line frames the content with two throwaway lines
346
+ if (lines[0]?.trim() === "") {
347
+ lines.shift();
348
+ }
349
+ if (lines.length > 1 && lines.at(-1)?.trim() === "") {
350
+ lines.pop();
351
+ }
352
+ // Only the lines with content get a say in the indent, and a line break must never count as one
353
+ const indent = lines.filter(line => line.trim() !== "")
354
+ .reduce((shortest, line) => {
355
+ const lineIndent = /^[ \t]*/.exec(line)?.[0] ?? "";
356
+ return shortest === undefined || lineIndent.length < shortest.length ? lineIndent : shortest;
357
+ }, undefined);
358
+ return indent
359
+ ? lines.map(line => line.startsWith(indent) ? line.substring(indent.length) : line).join("\n")
360
+ : lines.join("\n");
374
361
  }
375
362
  function resolveLegacyBlockScriptsInFolder(folder) {
376
363
  const blockScriptEntrypoints = [];
@@ -1,6 +1,6 @@
1
1
  import type { AbstractBiPhasicGroupAndEntryPlugin, EntryProvider } from "../plugins/AbstractBiPhasicGroupAndEntryPlugin";
2
2
  import type { AdditionalDependencyInjectorPlugin } from "../plugins/AdditionalDependencyInjectorPlugin";
3
- import { EntrypointFields, PlauditWordpressWebpackConfig, BlockEntrypointInfo, VerifiedAdvancedOutputConfig, MinimumViableMetadata, WebpackPlugin } from "../shared";
3
+ import { EntrypointFields, PlauditWordpressWebpackConfig, BlockEntrypointInfo, VerifiedAdvancedOutputConfig, MinimumViableMetadata } from "../shared";
4
4
  import type { Compiler, Configuration, DynamicEntryPlugin, WebpackPluginInstance } from "webpack";
5
5
  import type WebpackRemoveEmptyScriptsPlugin from "webpack-remove-empty-scripts";
6
6
  export type VerifiedPlauditWordpressWebpackConfig = Required<Omit<PlauditWordpressWebpackConfig, 'variables' | 'src' | 'externals' | 'standard'>> & {
@@ -8,7 +8,7 @@ export type VerifiedPlauditWordpressWebpackConfig = Required<Omit<PlauditWordpre
8
8
  currentVariables: Record<string, any>;
9
9
  } & Pick<PlauditWordpressWebpackConfig, 'externals'>;
10
10
  export type CommonPluginConfig = {
11
- plugins: (WebpackPluginInstance | WebpackPlugin | ((this: Compiler, compiler: Compiler) => void))[];
11
+ plugins: (WebpackPluginInstance | ((this: Compiler, compiler: Compiler) => void))[];
12
12
  removeEmptyScriptsPlugin: WebpackRemoveEmptyScriptsPlugin;
13
13
  makeAdditionalDependencyInjectorPlugin(referencePlugin: AbstractBiPhasicGroupAndEntryPlugin<any>): AdditionalDependencyInjectorPlugin;
14
14
  };
@@ -243,8 +243,10 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
243
243
  const resolvedBlockEntrypoints = presentEntrypoints
244
244
  .map(presentEntrypoint => {
245
245
  const overallSource = (0, node_path_1.dirname)(blockJsonOrigin);
246
- const overallSourceRelativeName = (0, node_path_1.relative)(overallSource, (0, node_path_1.normalize)((0, node_path_1.join)(blockJsonOrigin, (0, node_path_1.relative)(overallSource, presentEntrypoint.extensionlessExpectedSrc))));
247
- const handleSuffix = (0, shared_1.convertUsageLocationsHandleToEmittableHandleSuffix)(dest.locations.handle, overallSourceRelativeName);
246
+ // The handle suffix is the asset's extensionless name relative to its own block, so it
247
+ // has to come off the real on-disk path rather than the destination-relative expected src.
248
+ const parsedAbsoluteSrc = (0, node_path_1.parse)(presentEntrypoint.absoluteSrc);
249
+ const overallSourceRelativeName = (0, node_path_1.normalize)((0, node_path_1.join)((0, node_path_1.relative)(overallSource, parsedAbsoluteSrc.dir), parsedAbsoluteSrc.name));
248
250
  const handleGroup = (0, shared_1.getHandleGroup)(presentEntrypoint.entrypointField);
249
251
  let explicitlySetHandle;
250
252
  if (presentEntrypoint.handle) {
@@ -265,8 +267,9 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
265
267
  else {
266
268
  explicitlySetHandle = undefined;
267
269
  }
270
+ const emittableHandle = (0, shared_1.convertUsageLocationsHandleToEmittableHandle)(dest.locations.handle, handlePrefix, explicitlySetHandle ? explicitlySetHandle.substring(handlePrefix.length + 1) : overallSourceRelativeName);
268
271
  if (!entrypointNamesWithEffectiveDuplicates[presentEntrypoint.entrypointName]) {
269
- return { blockJsonOrigin, ...presentEntrypoint, handle: explicitlySetHandle ?? `${handlePrefix}/${handleSuffix}`, dest, handleGroup };
272
+ return { blockJsonOrigin, ...presentEntrypoint, handle: emittableHandle, dest, handleGroup };
270
273
  }
271
274
  const baseSuffix = `_${(0, shared_1.isStyleField)(presentEntrypoint.entrypointField) ? "style" : "script"}`;
272
275
  let count = 0, suffix = baseSuffix, deduplicatedEntrypointName;
@@ -281,7 +284,7 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
281
284
  ...presentEntrypoint,
282
285
  entrypointName: deduplicatedEntrypointName,
283
286
  extensionlessExpectedSrc: deduplicatedExtensionlessExpectedSrc,
284
- handle: explicitlySetHandle ?? `${handlePrefix}/${count ? handleSuffix + "_" + count : handleSuffix}`,
287
+ handle: emittableHandle,
285
288
  handleGroup,
286
289
  dest
287
290
  };
@@ -304,15 +307,15 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
304
307
  const packageJsonOrigin = (0, node_path_1.join)(dir, 'package.json');
305
308
  const packageJson = JSON.parse(await (0, promises_1.readFile)(packageJsonOrigin, 'utf8'));
306
309
  if (packageJson['main']) {
307
- rawEntrypoints.push(...mapToRealEntrypoints(packageJson['main'], dir, commonConfig.scriptExtension.test, { dest, entrypointJsonOrigin: packageJsonOrigin }));
310
+ rawEntrypoints.push(...mapToRealEntrypoints(packageJson['main'], dir, s => commonConfig.scriptExtension.test(s), { dest, entrypointJsonOrigin: packageJsonOrigin }));
308
311
  }
309
312
  if (!processingModules && packageJson['style']) {
310
- rawEntrypoints.push(...mapToRealEntrypoints(packageJson['style'], dir, shared_1.styleExtension.test, { dest, entrypointJsonOrigin: packageJsonOrigin }));
313
+ rawEntrypoints.push(...mapToRealEntrypoints(packageJson['style'], dir, s => shared_1.styleExtension.test(s), { dest, entrypointJsonOrigin: packageJsonOrigin }));
311
314
  }
312
315
  }
313
316
  catch (e) {
314
317
  try {
315
- rawEntrypoints.push(...parseEntrypointsJSON(dir, dest, ep => commonConfig.scriptExtension.test(ep) || shared_1.styleExtension.test(ep)));
318
+ rawEntrypoints.push(...parseEntrypointsJSON(dir, dest, ep => commonConfig.scriptExtension.test(ep) || (!processingModules && shared_1.styleExtension.test(ep))));
316
319
  }
317
320
  catch (e) {
318
321
  // This just means that the directory doesn't contain any declared entrypoints.
@@ -414,10 +417,12 @@ function commonMakeWebpackConfig(config, commonConfig, webpackConfig, externaliz
414
417
  outputLibrary = webpackConfig.output?.library;
415
418
  }
416
419
  const extensions = processingModules ? ['.mjsx', '.mjs', '.mtsx', '.mts', '...'] : ['.jsx', '.tsx', '.ts', '...'];
420
+ // `dist` (SERVER_MODE=production, or omitDistDev) is always minified production. `dist-dev` follows NODE_ENV so `wp-scripts start` stays fast.
421
+ const isProductionBuild = !(0, shared_1.isDistDevOutputPath)(config.outputDir) || process.env['NODE_ENV'] === 'production';
417
422
  return {
418
423
  ...webpackConfig,
419
- devtool: 'source-map',
420
- mode: "production",
424
+ devtool: isProductionBuild ? 'source-map' : (webpackConfig.devtool ?? 'eval-cheap-module-source-map'),
425
+ mode: isProductionBuild ? 'production' : 'development',
421
426
  output: {
422
427
  ...webpackConfig.output,
423
428
  path: outPath,
@@ -428,6 +433,7 @@ function commonMakeWebpackConfig(config, commonConfig, webpackConfig, externaliz
428
433
  },
429
434
  optimization: {
430
435
  ...webpackConfig.optimization,
436
+ minimize: isProductionBuild,
431
437
  splitChunks: {
432
438
  ...(webpackConfig.optimization?.splitChunks || {}),
433
439
  cacheGroups: {
@@ -447,10 +453,12 @@ function commonMakeWebpackConfig(config, commonConfig, webpackConfig, externaliz
447
453
  default: false
448
454
  }
449
455
  },
450
- minimizer: [
451
- ...(webpackConfig.optimization?.minimizer || []),
452
- new css_minimizer_webpack_plugin_1.default()
453
- ]
456
+ minimizer: isProductionBuild
457
+ ? [
458
+ ...(webpackConfig.optimization?.minimizer || []),
459
+ new css_minimizer_webpack_plugin_1.default()
460
+ ]
461
+ : webpackConfig.optimization?.minimizer
454
462
  },
455
463
  module: {
456
464
  ...webpackConfig.module,
@@ -9,7 +9,7 @@ function convertToCSS(writableCSSObject, pretty = true) {
9
9
  return convertToCSSPretty(writableCSSObject, "");
10
10
  }
11
11
  else {
12
- return convertToCSS(writableCSSObject);
12
+ return convertToCSSUgly(writableCSSObject);
13
13
  }
14
14
  }
15
15
  function convertToCSSPretty(writableCSSObject, indentation) {
@@ -23,7 +23,7 @@ function convertToCSSPretty(writableCSSObject, indentation) {
23
23
  }
24
24
  else {
25
25
  res += " {\n";
26
- res += convertToCSSPretty(writableCSSObject, indentation + "\t");
26
+ res += convertToCSSPretty(value, indentation + "\t");
27
27
  res += indentation + "}\n";
28
28
  }
29
29
  }
@@ -39,7 +39,7 @@ function convertToCSSUgly(writableCSSObject) {
39
39
  res += `:${value};`;
40
40
  }
41
41
  else {
42
- res += "{" + convertToCSSUgly(writableCSSObject) + "}";
42
+ res += "{" + convertToCSSUgly(value) + "}";
43
43
  }
44
44
  }
45
45
  return res;
@@ -1,10 +1,13 @@
1
- import { type AdvancedOutputConfig, type PlauditWordpressWebpackConfig } from "../shared";
1
+ import { type AdvancedOutputConfig, type PathQueryParameters, type PlauditWordpressWebpackConfig } from "../shared";
2
2
  export declare const enum SourceType {
3
3
  blocks = "blocks",
4
4
  extensions = "extensions",
5
5
  plain = "plain"
6
6
  }
7
7
  export declare function isSourceType(str: string): str is SourceType;
8
- type Entrypoints = [string, AdvancedOutputConfig][];
8
+ type ResolvedSourceConfig = AdvancedOutputConfig & {
9
+ pathQueryParameters?: PathQueryParameters;
10
+ };
11
+ type Entrypoints = [string, ResolvedSourceConfig][];
9
12
  export declare function resolveAllConfigLevelEntrypoints(config: PlauditWordpressWebpackConfig, projectRoot?: string): Record<'staticEntrypoints' | 'dynamicEntrypoints', Entrypoints>;
10
13
  export {};
@@ -10,7 +10,6 @@ export type ParsedLocationEncodingFilename = {
10
10
  };
11
11
  };
12
12
  flags: NormalizedEnqueuingControlFlags;
13
- niceName?: string;
14
13
  };
15
14
  export declare function parseLocationEncodingFilename(filename: string): ParsedLocationEncodingFilename | undefined;
16
15
  export declare function parseLocationEncodingFilenameForBlock(filename: string, errorBuilder?: (message: string, filename: string) => unknown): (Omit<ParsedLocationEncodingFilename, 'locations'> & {
@@ -79,16 +79,17 @@ function parseLocationEncodingFilename(filename) {
79
79
  return undefined;
80
80
  }
81
81
  if (niceName !== undefined) {
82
- locations.handle = { niceName };
82
+ // We need to kebab-case the nice name value for web-safety
83
+ locations.handle = { niceName: (0, shared_1.kebabCase)(niceName) };
83
84
  }
84
- return { type, locations, flags, niceName };
85
+ return { type, locations, flags };
85
86
  }
86
87
  function parseLocationEncodingFilenameForBlock(filename, errorBuilder = shared_1.newWebpackErrorForFile) {
87
88
  const parsedFilename = parseLocationEncodingFilename(filename);
88
89
  if (parsedFilename !== undefined) {
89
90
  const { handle, ...locations } = parsedFilename.locations;
90
91
  if ((0, shared_1.constantKeys)(locations).some(value => value !== 'clientView' && value !== 'clientEditor')) {
91
- throw errorBuilder(`Block assets cannot be enqueued anywhere other than view, editor, or both. Saw: ${(0, shared_1.constantKeys)(parsedFilename).join(", ")}`, filename);
92
+ throw errorBuilder(`Block assets cannot be enqueued anywhere other than view, editor, or both. Saw: ${(0, shared_1.constantKeys)(parsedFilename.locations).join(", ")}`, filename);
92
93
  }
93
94
  if (Object.values(locations).some(value => typeof value === 'number')) {
94
95
  throw errorBuilder(`Block assets cannot be enqueued with a priority`, filename);
@@ -15,7 +15,6 @@ export declare function unpackPotentiallyPrefixedFilePath(filePath: string): [st
15
15
  */
16
16
  export declare function unpackPathQuery(pathQuery: string): PathQueryParameters | undefined;
17
17
  export type LoadingStrategy = boolean | 'defer' | 'async' | 'eager' | 'lazy' | 'inline';
18
- export declare function isValidLoadingStrategy(strategy: any): strategy is LoadingStrategy | undefined;
19
18
  export declare function newInvalidLoadingStrategyError(strategy: unknown, file: string): import("webpack").WebpackError;
20
19
  export type InFooter = boolean;
21
20
  export declare function isValidInFooter(in_footer: unknown): in_footer is InFooter;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getAssetFileContents = getAssetFileContents;
4
4
  exports.unpackPotentiallyPrefixedFilePath = unpackPotentiallyPrefixedFilePath;
5
5
  exports.unpackPathQuery = unpackPathQuery;
6
- exports.isValidLoadingStrategy = isValidLoadingStrategy;
7
6
  exports.newInvalidLoadingStrategyError = newInvalidLoadingStrategyError;
8
7
  exports.isValidInFooter = isValidInFooter;
9
8
  exports.newInvalidInFooterError = newInvalidInFooterError;
@@ -78,9 +77,6 @@ function unpackPathQuery(pathQuery) {
78
77
  }, {});
79
78
  }
80
79
  const namedStrategies = ['defer', 'async', 'eager', 'lazy', 'inline'];
81
- function isValidLoadingStrategy(strategy) {
82
- return strategy === undefined || (typeof strategy === 'string' && namedStrategies.includes(strategy));
83
- }
84
80
  function newInvalidLoadingStrategyError(strategy, file) {
85
81
  return (0, shared_1.newWebpackErrorForFile)(`The strategy was invalid. Received: ${strategy}, Expected: undefined|boolean|'${namedStrategies.join("'|'")}'`, file);
86
82
  }
@@ -0,0 +1,72 @@
1
+ import LegacyDependencyExtractionWebpackPlugin from "@wordpress/dependency-extraction-webpack-plugin";
2
+ import { Compilation, Compiler, Module, type TemplatePath } from "webpack";
3
+ export interface EnhancedDependencyExtractionWebpackPluginOptions {
4
+ injectPolyfill?: boolean;
5
+ useDefaults?: boolean;
6
+ outputFilename?: TemplatePath;
7
+ requestToExternal?: (request: string) => string | string[] | undefined;
8
+ requestToExternalModule?: (request: string) => string | boolean | undefined;
9
+ requestToHandle?: (request: string) => string | undefined;
10
+ requestToScriptModule?: (request: string) => string | boolean | Error | undefined;
11
+ externalizedReport?: string | boolean;
12
+ }
13
+ export declare class EnhancedDependencyExtractionWebpackPlugin {
14
+ /**
15
+ * Track requests that are externalized.
16
+ *
17
+ * Because we don't have a closed set of dependencies, we need to track what has
18
+ * been externalized so we can recognize them in a later phase when the dependency
19
+ * lists are generated.
20
+ */
21
+ private readonly externalizedDeps;
22
+ private readonly options;
23
+ /**
24
+ * Track requests that a script build externalizes as script modules.
25
+ *
26
+ * These can only be reached through a runtime `import()`, which requires
27
+ * support for dynamic import in the output environment. The set is used
28
+ * to report an actionable error when that support is missing.
29
+ */
30
+ private readonly scriptModuleDepsInScript;
31
+ /**
32
+ * Whether we should use modules. This will be set later to match webpack's `output.module` option.
33
+ */
34
+ private useModules;
35
+ constructor(options: EnhancedDependencyExtractionWebpackPluginOptions | LegacyDependencyExtractionWebpackPlugin | EnhancedDependencyExtractionWebpackPlugin);
36
+ /**
37
+ * Convert a script module request to an external suitable for a script
38
+ * build.
39
+ *
40
+ * A classic script cannot contain a static `import`, so the `module`
41
+ * external type is not usable here: the script module has to be reached
42
+ * through a runtime `import()`, which is the `import` external type. The
43
+ * bare specifier is resolved by the import map that WordPress prints for
44
+ * enqueued script modules.
45
+ *
46
+ * @param {string} request Original module request.
47
+ * @param {string|boolean|Error=} external Result of a script module external resolution.
48
+ * @return {string|undefined} The resulting external definition.
49
+ */
50
+ static toScriptModuleExternalInScript(request: string, external?: string | boolean | Error): string | undefined;
51
+ private readonly externalizeWpDeps;
52
+ /**
53
+ * @param {string} request
54
+ * @return {string} Mapped dependency name
55
+ */
56
+ protected mapRequestToDependency(request: string): string;
57
+ apply(compiler: Compiler): void;
58
+ /**
59
+ * Check for magic comments before minification, so minification doesn't have to preserve them.
60
+ */
61
+ checkForMagicComments(compilation: Compilation): void;
62
+ addAssets(compilation: Compilation): void;
63
+ private static readonly staticDepsCurrent;
64
+ private static readonly staticDepsCache;
65
+ /**
66
+ * Can we trace a line of static dependencies from an entry to a module
67
+ *
68
+ * @return {boolean} True if there is a static import path to the root
69
+ */
70
+ static hasStaticDependencyPathToRoot(compilation: Compilation, block: Module): boolean;
71
+ readonly addExternalizedDep: (value: string) => Set<string>;
72
+ }