@plaudit/webpack-extensions 2.94.1 → 2.96.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 +23 -1
- package/USER-GUIDE.md +17 -12
- package/dist/plugins/AbstractBiPhasicGroupAndEntryPlugin.d.ts +1 -1
- package/dist/plugins/EnhancedBlockJSONPlugin.d.ts +1 -0
- package/dist/plugins/EnhancedBlockJSONPlugin.js +35 -24
- package/dist/plugins/ExtensionsConfigFileGeneratorPlugin.js +1 -1
- package/dist/plugins/PlainEntrypointsConfigFileGeneratorPlugin.js +35 -20
- package/dist/plugins/dependency-extraction-webpack-plugin-config-builder.d.ts +3 -6
- package/dist/plugins/dependency-extraction-webpack-plugin-config-builder.js +8 -21
- package/dist/shared.d.ts +17 -12
- package/dist/shared.js +27 -17
- package/dist/utils/common-config-helpers.js +8 -5
- package/dist/utils/css-writer.js +3 -3
- package/dist/utils/location-encoding-filename-parser.js +2 -2
- package/dist/utils/path-query-and-related-helpers.d.ts +0 -1
- package/dist/utils/path-query-and-related-helpers.js +0 -4
- package/dist/wordpress-ports/dependency-extraction-webpack-plugin/index.d.ts +72 -0
- package/dist/wordpress-ports/dependency-extraction-webpack-plugin/index.js +519 -0
- package/dist/wordpress-ports/dependency-extraction-webpack-plugin/util.d.ts +56 -0
- package/dist/wordpress-ports/dependency-extraction-webpack-plugin/util.js +150 -0
- package/dist/wordpress-scripts-wrapper.js +42 -39
- package/package.json +17 -1
package/CHANGELOG.md
CHANGED
|
@@ -60,6 +60,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
60
60
|
- Legacy PostCSS features that have been integrated into modern CSS
|
|
61
61
|
- `@extends` support
|
|
62
62
|
|
|
63
|
+
## [2.96.0] - 2026-08-07
|
|
64
|
+
### Added
|
|
65
|
+
- A port of WordPress's Dependency Extraction Webpack Plugin because they keep breaking it
|
|
66
|
+
- Warnings and additional info for entrypoints that are lazy-loaded and assigned to actual locations
|
|
67
|
+
|
|
68
|
+
### Removed
|
|
69
|
+
- "combineAssetMetadata" - it has never actually been a valid prop
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
- Path-query handle handling
|
|
73
|
+
- Double emission of CSS from entrypoint.json files when module processing is enabled
|
|
74
|
+
- A bug that could result in writes outside the webpack context root
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
- Backported the hook_name fix from the 3.x branch
|
|
78
|
+
|
|
79
|
+
## [2.95.0] - 2026-08-04
|
|
80
|
+
### Added
|
|
81
|
+
- Logic so that files and directories with names equal to "example" or "examples" or that include "example" as a name segment are skipped
|
|
82
|
+
- This is done to allow us to include example files
|
|
83
|
+
- Updated the user guide with this information
|
|
84
|
+
|
|
63
85
|
## [2.94.1] - 2026-07-20
|
|
64
86
|
### Fixed
|
|
65
87
|
- A bug that caused all styles bound for editor use to be emitted as inline CSS
|
|
@@ -289,7 +311,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
289
311
|
|
|
290
312
|
## [2.72.1] - 2025-10-29
|
|
291
313
|
### Fixed
|
|
292
|
-
- The wrapper being unable to find the `
|
|
314
|
+
- The wrapper being unable to find the `EnhancedDependencyExtractionWebpackPlugin` due to version desyncs
|
|
293
315
|
- This isn't so much a "fix" as it is a "mitigation" - version desyncs are not fixable at the library level
|
|
294
316
|
|
|
295
317
|
## [2.72.0] - 2025-10-13
|
package/USER-GUIDE.md
CHANGED
|
@@ -104,7 +104,7 @@ However, if you need to do something unusual or just want to know what everythin
|
|
|
104
104
|
- Any time that `dist` is referenced in a path, it should be replaced with the value of `outputDir` in your WebPack file
|
|
105
105
|
- As with `src`, the value of `outputDir` *should be* `dist`; however, this might not be the case in some inherited or older code
|
|
106
106
|
- Keys in the `src` *object* are all assumed to be paths relative to `srcDir` if it is specified or the folder in which the `webpack.config.js` file is located if it is not specified
|
|
107
|
-
- Paths in values in the `src`
|
|
107
|
+
- Paths in *values* in the `src` object are all assumed to be paths relative to `outputDir` if it is specified or the folder in which the `webpack.config.js` file is located if it is not specified
|
|
108
108
|
- All file names are informational placeholders. They can be whatever you want provided that they are web-safe (basically, don't do things like calling the email address block "✉️" and you'll be fine)
|
|
109
109
|
|
|
110
110
|
### Examples
|
|
@@ -117,6 +117,10 @@ However, if you need to do something unusual or just want to know what everythin
|
|
|
117
117
|
- All folder and file names should be in kebab-case
|
|
118
118
|
- Assets *should not* be in the root of the `src` folder. Assets that aren't block- or extension-bound should be in the `site` folder (or in a folder named after where they'll be used like, `admin` or `map-page`)
|
|
119
119
|
|
|
120
|
+
### Enforced Naming Conventions
|
|
121
|
+
- Directory and file names that start with a "~" are interpreted as "backup code" and are, therefore, not built.
|
|
122
|
+
- File and directory names that are equal to "example" or "examples", or have "example" as a name segment (see [Location-Encoding Filenames](#location-encoding-filenames) for details on what a name-segment is) are treated as example code and are also not built
|
|
123
|
+
|
|
120
124
|
### Blocks
|
|
121
125
|
- Block folder names *should* match the local portion of their name (ex: `plaudit-query-loop-maps/address-wrapper` should be stored in `address-wrapper`)
|
|
122
126
|
|
|
@@ -310,7 +314,7 @@ src: {
|
|
|
310
314
|
| `srcDir` | `string` | `""` | Source directory (**Required** on new sites) |
|
|
311
315
|
| `outputDir` | `string` | `""` | Output directory (**Required** on new sites) |
|
|
312
316
|
| `useUnifiedLoader` | `boolean` | `false` | Generate unified-loader.php (always set to `true` on new sites!) |
|
|
313
|
-
| `useWebpackResourceFiltering` | `boolean` | `
|
|
317
|
+
| `useWebpackResourceFiltering` | `boolean` | `true` | Generates versioned copies of images, fonts, etc (always set to `true` on new sites!) |
|
|
314
318
|
| `plainEntrypointsVersion` | `1\|2` | `1` | Use 2 for new sites |
|
|
315
319
|
| `extensionsVersion` | `1\|2\|3` | `1` | Use 3 for new sites |
|
|
316
320
|
| `verbose` | `boolean` | `false` | Verbose logging |
|
|
@@ -354,16 +358,17 @@ Notes on how to read the following table:
|
|
|
354
358
|
- `(-|=)` means "this can be either a dash or an equal sign"
|
|
355
359
|
- Pipe-separated items in parentheses means "any one of these items can go here"
|
|
356
360
|
|
|
357
|
-
| Name
|
|
358
|
-
|
|
359
|
-
| Enqueuing Location
|
|
360
|
-
| Type Override
|
|
361
|
-
| Inline
|
|
362
|
-
| Strategy
|
|
363
|
-
| Fetch Priority
|
|
364
|
-
| In Footer
|
|
365
|
-
| In Header
|
|
366
|
-
| Extension
|
|
361
|
+
| Name | Token | Usage |
|
|
362
|
+
|---------------------|-------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
363
|
+
| Enqueuing Location | `(enqueuing-location)[(-\|=)priority]` | This is a special section that is actually a collection of values. See the [Enqueuing Location](#enqueuing-location) section for more details |
|
|
364
|
+
| Type Override | `script`, `style`, `script-module` | Can be used to override the detected of the asset. Must be the first token in the filename; if used directly, it is shorthand for `both-(Type Override)` |
|
|
365
|
+
| Inline | `inline[(-\|=)position]`, `strategy(-\|=)inline[-position]` | Indicates that the script should be inlined. `position` can be either `before` or `after` |
|
|
366
|
+
| Strategy | `lazy\|eager`, `strategy(-\|=)(lazy\|eager\|defer\|async)` | Controls the loading strategy. Lazy and eager have shorthand while the remaining values must be prefixed with `strategy` |
|
|
367
|
+
| Fetch Priority | `fetchpriority(-\|=)(low\|high\|auto)` | Controls the fetchpriority property; `auto` is the default |
|
|
368
|
+
| In Footer | `in-footer`, `in_footer` | Sets the `in_footer` value to `true`; incompatible with `in-header` |
|
|
369
|
+
| In Header | `in-header`, `in_header` | Sets the `in_footer` value to `false`; incompatible with `in-footer` |
|
|
370
|
+
| Extension | `([ps]?c\|sa)ss`, `m?[jt]sx?` | This determines the type unless it is overridden. This **MUST** be the last token in the name (it is the file extension) |
|
|
371
|
+
| Example Code Marker | `example` | This informs the build system that the file contains example code and, therefore, should not be build |
|
|
367
372
|
|
|
368
373
|
### Enqueuing Location
|
|
369
374
|
If this is the first token, it can be suffixed with `-script`, `-style`, or `-script-module` to override the type.
|
|
@@ -2,7 +2,7 @@ import { MinimumViableMetadata, ParsedAssetJsonProvider, ParsedAssetsJson } from
|
|
|
2
2
|
import type { ExtensibleEntryObject, VerifiedPlauditWordpressWebpackConfig } from "../utils/common-config-helpers";
|
|
3
3
|
import { PseudoSemaphore } from "../utils/pseduo-semaphore";
|
|
4
4
|
import { AbstractBiPhasicGroupPlugin } from "./AbstractBiPhasicGroupPlugin";
|
|
5
|
-
import { Compilation, Compiler, Entrypoint } from "webpack";
|
|
5
|
+
import { type Compilation, type Compiler, type Entrypoint } from "webpack";
|
|
6
6
|
export type EntryProvider<M extends MinimumViableMetadata = MinimumViableMetadata> = () => ExtensibleEntryObject<M> | Promise<ExtensibleEntryObject<M>>;
|
|
7
7
|
export declare abstract class AbstractBiPhasicGroupAndEntryPlugin<M extends MinimumViableMetadata = MinimumViableMetadata> extends AbstractBiPhasicGroupPlugin {
|
|
8
8
|
private readonly context;
|
|
@@ -24,6 +24,7 @@ export declare class EnhancedBlockJSONPlugin extends AbstractBiPhasicGroupAndEnt
|
|
|
24
24
|
constructor(config: VerifiedPlauditWordpressWebpackConfig, dest: VerifiedAdvancedOutputConfig, webpackRemoveEmptyScriptsPlugin: WebpackRemoveEmptyScriptsPlugin, context: string, entry: EntryProvider<BlockEntrypointInfo>);
|
|
25
25
|
protected processAssets(compilation: Compilation, parsedAssetJsonProvider: ParsedAssetJsonProvider): Promise<void>;
|
|
26
26
|
private emitBlockLoaderFile;
|
|
27
|
+
private static readonly THEME_JSON_FLAG_PROPS;
|
|
27
28
|
private static pickOutFlagPropsFromBlockSupports;
|
|
28
29
|
private callRegisterFunction;
|
|
29
30
|
private transformBlocks;
|
|
@@ -226,37 +226,48 @@ class EnhancedBlockJSONPlugin extends AbstractBiPhasicGroupAndEntryPlugin_1.Abst
|
|
|
226
226
|
compilation.emitAsset((0, node_path_1.join)(this.dest.destination, "blockdir.config.php"), new webpack_1.sources.RawSource((0, shared_1.makeEmittableConfigPHP)(blockDirConfig, true)));
|
|
227
227
|
}
|
|
228
228
|
}
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
/*
|
|
230
|
+
* The block supports that have a boolean counterpart under theme.json's settings, as
|
|
231
|
+
* `settings key -> {support prop: settings prop}`. This is an allow-list rather than an ignore-list
|
|
232
|
+
* because most supports (align, alignWide, anchor, contentRole, inserter, interactivity, listView,
|
|
233
|
+
* plaudit, ...) have no theme.json settings equivalent at all, and the ones that do don't always
|
|
234
|
+
* share a name: typography's fontSize is settings.typography.customFontSize, and Gutenberg still
|
|
235
|
+
* ships several of these under an __experimental prefix.
|
|
236
|
+
*/
|
|
237
|
+
static THEME_JSON_FLAG_PROPS = {
|
|
238
|
+
color: { background: 'background', link: 'link', text: 'text' },
|
|
239
|
+
dimensions: { aspectRatio: 'aspectRatio', minHeight: 'minHeight' },
|
|
240
|
+
spacing: { blockGap: 'blockGap', margin: 'margin', padding: 'padding' },
|
|
241
|
+
typography: {
|
|
242
|
+
fontSize: 'customFontSize',
|
|
243
|
+
lineHeight: 'lineHeight',
|
|
244
|
+
textAlign: 'textAlign',
|
|
245
|
+
fontStyle: 'fontStyle', __experimentalFontStyle: 'fontStyle',
|
|
246
|
+
fontWeight: 'fontWeight', __experimentalFontWeight: 'fontWeight',
|
|
247
|
+
letterSpacing: 'letterSpacing', __experimentalLetterSpacing: 'letterSpacing',
|
|
248
|
+
textDecoration: 'textDecoration', __experimentalTextDecoration: 'textDecoration',
|
|
249
|
+
textTransform: 'textTransform', __experimentalTextTransform: 'textTransform',
|
|
250
|
+
writingMode: 'writingMode', __experimentalWritingMode: 'writingMode'
|
|
251
|
+
}
|
|
252
|
+
};
|
|
231
253
|
static pickOutFlagPropsFromBlockSupports(supports) {
|
|
232
254
|
function isRecord(value) {
|
|
233
255
|
return typeof value === 'object' && !!value && !Array.isArray(value);
|
|
234
256
|
}
|
|
235
257
|
let addedProp = false;
|
|
236
258
|
const res = {};
|
|
237
|
-
|
|
238
|
-
const
|
|
239
|
-
if (isRecord(
|
|
240
|
-
|
|
241
|
-
for (const prop of ['background', 'link', 'text']) {
|
|
242
|
-
if (supports[prop]) {
|
|
243
|
-
colorFlags[prop] = true;
|
|
244
|
-
res.color = colorFlags;
|
|
245
|
-
addedProp = true;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
259
|
+
for (const [settingsKey, props] of Object.entries(EnhancedBlockJSONPlugin.THEME_JSON_FLAG_PROPS)) {
|
|
260
|
+
const support = supports[settingsKey];
|
|
261
|
+
if (!isRecord(support)) {
|
|
262
|
+
continue;
|
|
248
263
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
dimensionsFlags[prop] = true;
|
|
257
|
-
res.color = dimensionsFlags;
|
|
258
|
-
addedProp = true;
|
|
259
|
-
}
|
|
264
|
+
const flags = {};
|
|
265
|
+
for (const [supportProp, settingsProp] of Object.entries(props)) {
|
|
266
|
+
// A sided support such as `"margin": ["top", "bottom"]` is still just "on" as far as theme.json is concerned
|
|
267
|
+
if (support[supportProp]) {
|
|
268
|
+
flags[settingsProp] = true;
|
|
269
|
+
res[settingsKey] = flags;
|
|
270
|
+
addedProp = true;
|
|
260
271
|
}
|
|
261
272
|
}
|
|
262
273
|
}
|
|
@@ -52,7 +52,7 @@ class ExtensionsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAndEntryP
|
|
|
52
52
|
compilation.contextDependencies.add(srcRoot);
|
|
53
53
|
}
|
|
54
54
|
for await (const dirent of await (0, promises_1.opendir)(srcRoot)) {
|
|
55
|
-
if (dirent.name
|
|
55
|
+
if ((0, shared_1.shouldBeSkipped)(dirent.name)) {
|
|
56
56
|
continue;
|
|
57
57
|
}
|
|
58
58
|
if (dirent.isFile()) {
|
|
@@ -43,7 +43,7 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
|
|
|
43
43
|
for (const { src, rest, locations, type, handleName, lazyLoader, ...otherProps } of handles) {
|
|
44
44
|
const cleanBasename = (0, node_path_1.basename)(src).replace(/_(?:script(?:-\d+)?\.js|style(?:-\d+)?\.css)$|(?<!_(script|style))\.(js|css)$/, "");
|
|
45
45
|
let finalHandleName;
|
|
46
|
-
if (
|
|
46
|
+
if (handleName !== undefined) {
|
|
47
47
|
finalHandleName = (0, shared_1.convertUsageLocationsHandleToEmittableHandle)(handleName, cleanBasename);
|
|
48
48
|
}
|
|
49
49
|
else {
|
|
@@ -57,13 +57,13 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
|
|
|
57
57
|
plainEntrypointsConfig[`${type}Handles`][finalHandleName] = { src, rest, locations, type, lazyLoader, ...otherProps };
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
PlainEntrypointsConfigFileGeneratorPlugin.addHandlesToHandleLists('script', Object.entries(plainEntrypointsConfig.scriptHandles)
|
|
60
|
+
PlainEntrypointsConfigFileGeneratorPlugin.addHandlesToHandleLists(compilation, 'script', Object.entries(plainEntrypointsConfig.scriptHandles)
|
|
61
61
|
.toSorted(([a], [b]) => a.localeCompare(b)), handleLists);
|
|
62
|
-
PlainEntrypointsConfigFileGeneratorPlugin.addHandlesToHandleLists('script_module', Object.entries(plainEntrypointsConfig.script_moduleHandles)
|
|
62
|
+
PlainEntrypointsConfigFileGeneratorPlugin.addHandlesToHandleLists(compilation, 'script_module', Object.entries(plainEntrypointsConfig.script_moduleHandles)
|
|
63
63
|
.toSorted(([a], [b]) => a.localeCompare(b)), handleLists);
|
|
64
64
|
const sortedStyleHandles = Object.entries(plainEntrypointsConfig.styleHandles)
|
|
65
65
|
.toSorted(([a], [b]) => a.localeCompare(b));
|
|
66
|
-
PlainEntrypointsConfigFileGeneratorPlugin.addHandlesToHandleLists('style', sortedStyleHandles, handleLists);
|
|
66
|
+
PlainEntrypointsConfigFileGeneratorPlugin.addHandlesToHandleLists(compilation, 'style', sortedStyleHandles, handleLists);
|
|
67
67
|
const callItemSorter = (a, b) => a.handle.localeCompare(b.handle);
|
|
68
68
|
for (const list of Object.values(handleLists)) {
|
|
69
69
|
list.sort(callItemSorter);
|
|
@@ -121,8 +121,10 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
|
|
|
121
121
|
writer.return(editorSettings);
|
|
122
122
|
}, { functionArgParameters: [editorSettings], accountForAlreadyDoing: false });
|
|
123
123
|
}
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
// Only the register and inline lists, which are mutually exclusive, so each handle is collected
|
|
125
|
+
// exactly once. Flattening every list instead would collect a handle once per location it declares.
|
|
126
|
+
const lazyLoadedHandles = [...handleLists.register, ...handleLists.inline]
|
|
127
|
+
.map(handle => [handle.data.lazyLoader, handle])
|
|
126
128
|
.filter((entry) => entry[0] !== undefined)
|
|
127
129
|
.sort((a, b) => a[0].localeCompare(b[0]) || a[1].priority - b[1].priority);
|
|
128
130
|
if (lazyLoadedHandles.length > 0) {
|
|
@@ -142,7 +144,7 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
|
|
|
142
144
|
}
|
|
143
145
|
(0, shared_1.emitPHPWriterAsAsset)(writer, compilation, "plain-entrypoints-loader.php");
|
|
144
146
|
}
|
|
145
|
-
static addHandlesToHandleLists(type, handles, handleLists) {
|
|
147
|
+
static addHandlesToHandleLists(compilation, type, handles, handleLists) {
|
|
146
148
|
const defaultPriority = 10;
|
|
147
149
|
for (const [handle, data] of handles) {
|
|
148
150
|
if (data.locations.register !== false) {
|
|
@@ -151,6 +153,19 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
|
|
|
151
153
|
else if (data.inlinedAsset !== undefined) {
|
|
152
154
|
handleLists.inline.push({ handle, type, data, priority: typeof data.locations.inline === 'number' ? data.locations.inline : 10 });
|
|
153
155
|
}
|
|
156
|
+
if (data.lazyLoader !== undefined) {
|
|
157
|
+
// A lazily loaded handle is enqueued by its generated function and never by an action, so it
|
|
158
|
+
// is deliberately kept out of the location lists. Those lists are also what the lazy function
|
|
159
|
+
// is built from, and a handle present in several of them would be enqueued once per list.
|
|
160
|
+
const declaredLocations = (0, shared_1.constantKeys)(shared_1.standardLocationNamesMeta)
|
|
161
|
+
.filter(location => data.locations[location] || typeof data.locations[location] === 'number');
|
|
162
|
+
if (declaredLocations.length > 0) {
|
|
163
|
+
const locText = declaredLocations.length === 1 ? "location" : "locations";
|
|
164
|
+
compilation.warnings.push((0, shared_1.newWebpackErrorForFile)(`The handle "${handle}" declares both a lazyLoader (${data.lazyLoader}) and the ${declaredLocations.join(", ")} ${locText}.`
|
|
165
|
+
+ ` It will only be enqueued by ${data.lazyLoader}(); remove either the ${locText} or the lazyLoader.`, data.src));
|
|
166
|
+
}
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
154
169
|
for (const location of (0, shared_1.constantKeys)(shared_1.standardLocationNamesMeta)) {
|
|
155
170
|
let priority, hook_name;
|
|
156
171
|
const dataLocation = data.locations[location];
|
|
@@ -194,7 +209,6 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
|
|
|
194
209
|
}
|
|
195
210
|
}
|
|
196
211
|
static appendEnqueuingHandleLists(writer, handleLists) {
|
|
197
|
-
const lazyLoadableHandles = {};
|
|
198
212
|
for (const [sln, { action, supports_hook_name, additional_action_code }] of (0, shared_1.constantEntries)(shared_1.standardLocationNamesMeta)) {
|
|
199
213
|
const handleList = handleLists[sln];
|
|
200
214
|
if (handleList.length > 0) {
|
|
@@ -202,11 +216,14 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
|
|
|
202
216
|
for (const [priority, prioritizedHandleList] of PlainEntrypointsConfigFileGeneratorPlugin.separateHandleListByPriority(handleList)) {
|
|
203
217
|
if (supports_hook_name) {
|
|
204
218
|
const hookNamedHandleLists = PlainEntrypointsConfigFileGeneratorPlugin.separateHandleListByHookName(prioritizedHandleList);
|
|
205
|
-
if (
|
|
219
|
+
if (hookNamedHandleLists.named.length > 0) {
|
|
206
220
|
const hook_name_var = new expressions_1.Var("hook_name", "?string");
|
|
207
221
|
writer.action(action, writer => {
|
|
208
222
|
additional_action_code?.before?.(writer);
|
|
209
|
-
for (const
|
|
223
|
+
for (const handle of hookNamedHandleLists.global) {
|
|
224
|
+
writer.call(`wp_enqueue_${handle.type}`, [handle.handle]);
|
|
225
|
+
}
|
|
226
|
+
for (const [hook_name, handles] of hookNamedHandleLists.named) {
|
|
210
227
|
writer.if(expressions_1.Op.binary(hook_name_var, " === ", hook_name));
|
|
211
228
|
for (const handle of handles) {
|
|
212
229
|
writer.call(`wp_enqueue_${handle.type}`, [handle.handle]);
|
|
@@ -228,7 +245,6 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
|
|
|
228
245
|
}
|
|
229
246
|
}
|
|
230
247
|
}
|
|
231
|
-
return lazyLoadableHandles;
|
|
232
248
|
}
|
|
233
249
|
static separateHandleListByPriority(handleItems) {
|
|
234
250
|
const lists = new Map();
|
|
@@ -249,9 +265,16 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
|
|
|
249
265
|
* @private
|
|
250
266
|
*/
|
|
251
267
|
static separateHandleListByHookName(handleItems) {
|
|
268
|
+
const global = [];
|
|
252
269
|
const lists = new Map();
|
|
253
270
|
for (const handleItem of handleItems) {
|
|
254
271
|
const hook_name = handleItem.hook_name ?? "";
|
|
272
|
+
if (hook_name === "" || (Array.isArray(hook_name) && hook_name.includes(""))) {
|
|
273
|
+
// We're going to be handling global hooks (aka those without a name restriction) separately anyway,
|
|
274
|
+
// so there's no sense in mixing them in with the non-global ones
|
|
275
|
+
global.push(handleItem);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
255
278
|
for (const hn of Array.isArray(hook_name) ? hook_name : [hook_name]) {
|
|
256
279
|
const list = lists.get(hn);
|
|
257
280
|
if (list) {
|
|
@@ -262,15 +285,7 @@ class PlainEntrypointsConfigFileGeneratorPlugin extends AbstractBiPhasicGroupAnd
|
|
|
262
285
|
}
|
|
263
286
|
}
|
|
264
287
|
}
|
|
265
|
-
return lists.entries().toArray().sort((a, b) =>
|
|
266
|
-
if (a[0] === "") {
|
|
267
|
-
return b[0] === "" ? 0 : -1;
|
|
268
|
-
}
|
|
269
|
-
else if (b[0] === "") {
|
|
270
|
-
return 1;
|
|
271
|
-
}
|
|
272
|
-
return a[0].localeCompare(b[0]);
|
|
273
|
-
});
|
|
288
|
+
return { global, named: lists.entries().toArray().sort((a, b) => a[0].localeCompare(b[0])) };
|
|
274
289
|
}
|
|
275
290
|
attachUniquePhase(compilation) {
|
|
276
291
|
compilation.hooks.processAssets.tapPromise({ name: this.constructor.name, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_REPORT }, async () => {
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import type { Externals } from "../shared";
|
|
2
|
+
import { EnhancedDependencyExtractionWebpackPlugin } from "../wordpress-ports/dependency-extraction-webpack-plugin";
|
|
3
3
|
import type { Configuration } from "webpack";
|
|
4
|
-
export declare function makeDependencyExtractionPlugin(externals: Externals | undefined, assumeGlobalizedPlauditLibraries: boolean,
|
|
5
|
-
instance: DependencyExtractionWebpackPlugin;
|
|
6
|
-
addExternalizedDep: (dep: string) => void;
|
|
7
|
-
};
|
|
4
|
+
export declare function makeDependencyExtractionPlugin(externals: Externals | undefined, assumeGlobalizedPlauditLibraries: boolean, externalizing: Required<Configuration>['output']['library']): EnhancedDependencyExtractionWebpackPlugin;
|
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.makeDependencyExtractionPlugin = makeDependencyExtractionPlugin;
|
|
7
|
-
const dependency_extraction_webpack_plugin_1 =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return {
|
|
12
|
-
instance,
|
|
13
|
-
addExternalizedDep: (dep) => {
|
|
14
|
-
instance.externalizedDeps.add(dep);
|
|
15
|
-
}
|
|
16
|
-
};
|
|
4
|
+
const dependency_extraction_webpack_plugin_1 = require("../wordpress-ports/dependency-extraction-webpack-plugin");
|
|
5
|
+
const util_1 = require("../wordpress-ports/dependency-extraction-webpack-plugin/util");
|
|
6
|
+
function makeDependencyExtractionPlugin(externals, assumeGlobalizedPlauditLibraries, externalizing) {
|
|
7
|
+
return new dependency_extraction_webpack_plugin_1.EnhancedDependencyExtractionWebpackPlugin(makeDependencyExtractionPluginProps(externals, assumeGlobalizedPlauditLibraries, externalizing));
|
|
17
8
|
}
|
|
18
9
|
function makeDependencyExtractionPluginProps(externals, assumeGlobalizedPlauditLibraries, externalizing) {
|
|
19
10
|
if (!externals) {
|
|
@@ -93,7 +84,7 @@ const EXTERNALIZABLE_PLAUDIT_LIBRARIES = {
|
|
|
93
84
|
...Object.fromEntries(['@plaudit/frontend-apis', '@plaudit/library-extensions', '@plaudit/block-supports', '@plaudit/gutenberg-api-extensions']
|
|
94
85
|
.map(req => {
|
|
95
86
|
return [req, {
|
|
96
|
-
import: ['plaudit', camelCaseDash(req.substring(PLAUDIT_NAMESPACE.length))],
|
|
87
|
+
import: ['plaudit', (0, util_1.camelCaseDash)(req.substring(PLAUDIT_NAMESPACE.length))],
|
|
97
88
|
handle: `plaudit-${req.substring(PLAUDIT_NAMESPACE.length)}`
|
|
98
89
|
}];
|
|
99
90
|
})),
|
|
@@ -116,12 +107,6 @@ function normalizeRequest(request) {
|
|
|
116
107
|
function curryRequestHandlers(primary, secondary) {
|
|
117
108
|
return (...args) => primary(...args) ?? secondary(...args);
|
|
118
109
|
}
|
|
119
|
-
/**
|
|
120
|
-
* Copied from @wordpress/dependency-extraction-webpack-plugin for consistency
|
|
121
|
-
*/
|
|
122
|
-
function camelCaseDash(string) {
|
|
123
|
-
return string.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
124
|
-
}
|
|
125
110
|
function handleExternalizingEqualsPossibleExternal(possibleExternal, ext) {
|
|
126
111
|
if (!ext || !possibleExternal) {
|
|
127
112
|
return possibleExternal;
|
|
@@ -151,7 +136,9 @@ function handleExternalizingEqualsPossibleExternal(possibleExternal, ext) {
|
|
|
151
136
|
}
|
|
152
137
|
else {
|
|
153
138
|
for (const key of ['amd', 'commonjs', 'root']) {
|
|
154
|
-
|
|
139
|
+
// The recursion returns the external when it should be kept and undefined when it matched, so
|
|
140
|
+
// only an undefined result means this umd name is the thing being built and must not externalize.
|
|
141
|
+
if (key in ext && handleExternalizingEqualsPossibleExternal(possibleExternal, ext[key]) === undefined) {
|
|
155
142
|
return undefined;
|
|
156
143
|
}
|
|
157
144
|
}
|
package/dist/shared.d.ts
CHANGED
|
@@ -5,17 +5,20 @@ import { type AssetInfo, type Compilation, type Configuration, type Entrypoint,
|
|
|
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
|
|
13
|
-
dependencies:
|
|
12
|
+
export type ParsedAssetJson = {
|
|
13
|
+
dependencies: WPModuleDependency[];
|
|
14
|
+
module_dependencies?: WPModuleDependency[];
|
|
14
15
|
version: string;
|
|
15
|
-
|
|
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: */
|
|
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?:
|
|
34
|
+
module_dependencies?: WPModuleDependency[];
|
|
32
35
|
};
|
|
33
36
|
export type InlinedAsset = {
|
|
34
37
|
position?: 'before' | 'after';
|
|
@@ -118,7 +121,7 @@ export type AdvancedOutputConfig = {
|
|
|
118
121
|
directoryLayout?: SourceType;
|
|
119
122
|
assumeGlobalizedPlauditLibraries?: boolean;
|
|
120
123
|
externalize?: Required<Configuration>['output']['library'];
|
|
121
|
-
bundleAnalyzer?: boolean;
|
|
124
|
+
bundleAnalyzer?: boolean | 'no-auto-open';
|
|
122
125
|
locations?: UsageLocations | UsageLocations['handle'];
|
|
123
126
|
lazyLoader?: string;
|
|
124
127
|
pathQueryParameters?: PathQueryParameters;
|
|
@@ -143,7 +146,6 @@ export type PlauditWordpressWebpackConfig = {
|
|
|
143
146
|
externals?: Externals;
|
|
144
147
|
assumeGlobalizedPlauditLibraries?: boolean;
|
|
145
148
|
processTranslationConfigs?: boolean;
|
|
146
|
-
combineAssetMetadata?: boolean;
|
|
147
149
|
useWebpackResourceFiltering?: boolean;
|
|
148
150
|
outputDir?: string;
|
|
149
151
|
extensionsVersion?: 1 | 2 | 3;
|
|
@@ -170,7 +172,6 @@ export declare function applyStandards(config: PlauditWordpressWebpackConfig): {
|
|
|
170
172
|
readonly externals?: Externals;
|
|
171
173
|
readonly assumeGlobalizedPlauditLibraries?: boolean;
|
|
172
174
|
readonly processTranslationConfigs?: boolean;
|
|
173
|
-
readonly combineAssetMetadata?: boolean;
|
|
174
175
|
useWebpackResourceFiltering?: boolean;
|
|
175
176
|
outputDir?: string;
|
|
176
177
|
extensionsVersion?: 1 | 2 | 3;
|
|
@@ -228,7 +229,7 @@ export declare const styleExtension: RegExp;
|
|
|
228
229
|
export declare function scriptOrStyleTest(entryPath: string, scriptExtension: RegExp): "script" | "style" | "";
|
|
229
230
|
export declare function isStyleField(field: string): field is 'style' | 'viewStyle' | 'editorStyle';
|
|
230
231
|
export declare function isScriptModuleField(field: string): field is 'viewScriptModule';
|
|
231
|
-
export declare function mergeModuleDependencyArrays(a:
|
|
232
|
+
export declare function mergeModuleDependencyArrays(a: WPModuleDependency[] | undefined, b: WPModuleDependency[] | undefined): WPModuleDependency[] | undefined;
|
|
232
233
|
export declare function getHandleGroup(field: string): 'styleHandles' | 'scriptHandles' | 'scriptModuleHandles';
|
|
233
234
|
export type StripFirstTwoItems<A extends any[]> = A extends [any, any, ...rest: infer R] ? R : never;
|
|
234
235
|
export declare function hasAtLeastOneItem<T>(list: T[]): list is [T, ...T[]];
|
|
@@ -254,7 +255,7 @@ export declare function getParsedAssetsJsonDataForEntrypoint(compilation: Compil
|
|
|
254
255
|
assetData: ParsedAssetsJson[string];
|
|
255
256
|
} | undefined;
|
|
256
257
|
export declare function emitPHPWriterAsAsset(writer: PHPWriter, compilation: Compilation, file: string, assetInfo?: AssetInfo): void;
|
|
257
|
-
export declare function dedent(text: TemplateStringsArray): string;
|
|
258
|
+
export declare function dedent(text: TemplateStringsArray, ...values: unknown[]): string;
|
|
258
259
|
export declare function resolveLegacyBlockScriptsInFolder(folder: string): string[];
|
|
259
260
|
/**
|
|
260
261
|
* @param compilation
|
|
@@ -272,3 +273,7 @@ export declare function synchronousDirIterator(dirPath: string): Generator<impor
|
|
|
272
273
|
* @link https://dev.to/jdbar
|
|
273
274
|
*/
|
|
274
275
|
export declare function instanceOfNodeError<T extends new (...args: any) => Error>(value: unknown, errorType: T): value is InstanceType<T> & NodeJS.ErrnoException;
|
|
276
|
+
/**
|
|
277
|
+
* This tests if the name starts with a "~", is equal to "example" or "examples", or includes "example" as a name segment
|
|
278
|
+
*/
|
|
279
|
+
export declare function shouldBeSkipped(name: string): boolean;
|
package/dist/shared.js
CHANGED
|
@@ -53,6 +53,7 @@ exports.appendAddInlineAssetCall = appendAddInlineAssetCall;
|
|
|
53
53
|
exports.wrapInlineAssetContents = wrapInlineAssetContents;
|
|
54
54
|
exports.synchronousDirIterator = synchronousDirIterator;
|
|
55
55
|
exports.instanceOfNodeError = instanceOfNodeError;
|
|
56
|
+
exports.shouldBeSkipped = shouldBeSkipped;
|
|
56
57
|
const node_crypto_1 = require("node:crypto");
|
|
57
58
|
const node_fs_1 = require("node:fs");
|
|
58
59
|
const promises_1 = require("node:fs/promises");
|
|
@@ -84,7 +85,7 @@ exports.standardLocationNamesMeta = {
|
|
|
84
85
|
analytics: { action: "plaudit_enqueue_analytics" },
|
|
85
86
|
};
|
|
86
87
|
function isStandardLocationName(name) {
|
|
87
|
-
return
|
|
88
|
+
return Object.hasOwn(exports.standardLocationNamesMeta, name);
|
|
88
89
|
}
|
|
89
90
|
function isRegisterScriptArgsShorthandName(name) {
|
|
90
91
|
return ['lazy', 'eager', 'inline'].includes(name);
|
|
@@ -270,18 +271,10 @@ function emitResolveBaseUriFunction(writer) {
|
|
|
270
271
|
}
|
|
271
272
|
function getAssetsJson(compilation) {
|
|
272
273
|
const asset = compilation.getAsset("assets.json");
|
|
273
|
-
if (
|
|
274
|
-
throw new Error("assets.json is unexpectedly missing");
|
|
275
|
-
}
|
|
276
|
-
if (isParsedAssetsJson(asset.info["parsed-assets-json"])) {
|
|
274
|
+
if (asset && isParsedAssetsJson(asset.info["parsed-assets-json"])) {
|
|
277
275
|
return asset.info["parsed-assets-json"];
|
|
278
276
|
}
|
|
279
|
-
|
|
280
|
-
if (!isParsedAssetsJson(parsedAssetJson)) {
|
|
281
|
-
throw new Error("assets.json is does not match the RawAssetData format");
|
|
282
|
-
}
|
|
283
|
-
compilation.updateAsset("assets.json", s => s, a => ({ ...a, "parsed-assets-json": parsedAssetJson }));
|
|
284
|
-
return parsedAssetJson;
|
|
277
|
+
throw new Error("assets.json is unexpectedly missing");
|
|
285
278
|
}
|
|
286
279
|
function getParsedAssetsJsonDataForEntrypoint(compilation, entrypoint, metadata) {
|
|
287
280
|
const dest = metadata.dest;
|
|
@@ -321,13 +314,24 @@ function emitPHPWriterAsAsset(writer, compilation, file, assetInfo) {
|
|
|
321
314
|
const contents = writer.toString() + "\n";
|
|
322
315
|
compilation[file in compilation.assets ? 'updateAsset' : 'emitAsset'](file, new webpack_1.sources.RawSource(contents), { size: Buffer.byteLength(contents), ...assetInfo });
|
|
323
316
|
}
|
|
324
|
-
function dedent(text) {
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
if (
|
|
328
|
-
|
|
317
|
+
function dedent(text, ...values) {
|
|
318
|
+
const lines = text.reduce((result, part, i) => result + String(values[i - 1]) + part).split(/\r?\n/);
|
|
319
|
+
// A template that opens and closes on its own line frames the content with two throwaway lines
|
|
320
|
+
if (lines[0]?.trim() === "") {
|
|
321
|
+
lines.shift();
|
|
322
|
+
}
|
|
323
|
+
if (lines.length > 1 && lines.at(-1)?.trim() === "") {
|
|
324
|
+
lines.pop();
|
|
329
325
|
}
|
|
330
|
-
|
|
326
|
+
// Only the lines with content get a say in the indent, and a line break must never count as one
|
|
327
|
+
const indent = lines.filter(line => line.trim() !== "")
|
|
328
|
+
.reduce((shortest, line) => {
|
|
329
|
+
const lineIndent = /^[ \t]*/.exec(line)?.[0] ?? "";
|
|
330
|
+
return shortest === undefined || lineIndent.length < shortest.length ? lineIndent : shortest;
|
|
331
|
+
}, undefined);
|
|
332
|
+
return indent
|
|
333
|
+
? lines.map(line => line.startsWith(indent) ? line.substring(indent.length) : line).join("\n")
|
|
334
|
+
: lines.join("\n");
|
|
331
335
|
}
|
|
332
336
|
function resolveLegacyBlockScriptsInFolder(folder) {
|
|
333
337
|
const blockScriptEntrypoints = [];
|
|
@@ -390,3 +394,9 @@ function* synchronousDirIterator(dirPath) {
|
|
|
390
394
|
function instanceOfNodeError(value, errorType) {
|
|
391
395
|
return !!value && value instanceof errorType;
|
|
392
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* This tests if the name starts with a "~", is equal to "example" or "examples", or includes "example" as a name segment
|
|
399
|
+
*/
|
|
400
|
+
function shouldBeSkipped(name) {
|
|
401
|
+
return name.startsWith("~") || name === "example" || name === "examples" || name.startsWith("example.") || name.includes(".example.");
|
|
402
|
+
}
|
|
@@ -126,7 +126,7 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
|
|
|
126
126
|
const seenExplicitHandles = { scriptHandles: {}, styleHandles: {}, scriptModuleHandles: {} };
|
|
127
127
|
const loadingEntrypoints = [];
|
|
128
128
|
for await (const dirent of await (0, promises_1.opendir)(srcRoot)) {
|
|
129
|
-
if (!dirent.isDirectory() || dirent.name
|
|
129
|
+
if (!dirent.isDirectory() || (0, shared_1.shouldBeSkipped)(dirent.name)) {
|
|
130
130
|
continue;
|
|
131
131
|
}
|
|
132
132
|
const dir = joinPossiblyAbsolutePaths(srcRoot, dirent.name);
|
|
@@ -233,7 +233,10 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
|
|
|
233
233
|
const resolvedBlockEntrypoints = presentEntrypoints
|
|
234
234
|
.map(presentEntrypoint => {
|
|
235
235
|
const overallSource = (0, node_path_1.dirname)(blockJsonOrigin);
|
|
236
|
-
|
|
236
|
+
// The handle suffix is the asset's extensionless name relative to its own block, so it
|
|
237
|
+
// has to come off the real on-disk path rather than the destination-relative expected src.
|
|
238
|
+
const parsedAbsoluteSrc = (0, node_path_1.parse)(presentEntrypoint.absoluteSrc);
|
|
239
|
+
const overallSourceRelativeName = (0, node_path_1.normalize)((0, node_path_1.join)((0, node_path_1.relative)(overallSource, parsedAbsoluteSrc.dir), parsedAbsoluteSrc.name));
|
|
237
240
|
const handleSuffix = (0, shared_1.convertUsageLocationsHandleToEmittableHandle)(dest.locations.handle, overallSourceRelativeName);
|
|
238
241
|
const handleGroup = (0, shared_1.getHandleGroup)(presentEntrypoint.entrypointField);
|
|
239
242
|
if (presentEntrypoint.handle) {
|
|
@@ -277,15 +280,15 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
|
|
|
277
280
|
const packageJsonOrigin = (0, node_path_1.join)(dir, 'package.json');
|
|
278
281
|
const packageJson = JSON.parse(await (0, promises_1.readFile)(packageJsonOrigin, 'utf8'));
|
|
279
282
|
if (packageJson['main']) {
|
|
280
|
-
rawEntrypoints.push(...mapToRealEntrypoints(packageJson['main'], dir, commonConfig.scriptExtension.test, { dest, entrypointJsonOrigin: packageJsonOrigin }));
|
|
283
|
+
rawEntrypoints.push(...mapToRealEntrypoints(packageJson['main'], dir, s => commonConfig.scriptExtension.test(s), { dest, entrypointJsonOrigin: packageJsonOrigin }));
|
|
281
284
|
}
|
|
282
285
|
if (!processingModules && packageJson['style']) {
|
|
283
|
-
rawEntrypoints.push(...mapToRealEntrypoints(packageJson['style'], dir, shared_1.styleExtension.test, { dest, entrypointJsonOrigin: packageJsonOrigin }));
|
|
286
|
+
rawEntrypoints.push(...mapToRealEntrypoints(packageJson['style'], dir, s => shared_1.styleExtension.test(s), { dest, entrypointJsonOrigin: packageJsonOrigin }));
|
|
284
287
|
}
|
|
285
288
|
}
|
|
286
289
|
catch (e) {
|
|
287
290
|
try {
|
|
288
|
-
rawEntrypoints.push(...parseEntrypointsJSON(dir, dest, ep => commonConfig.scriptExtension.test(ep) || shared_1.styleExtension.test(ep)));
|
|
291
|
+
rawEntrypoints.push(...parseEntrypointsJSON(dir, dest, ep => commonConfig.scriptExtension.test(ep) || (!processingModules && shared_1.styleExtension.test(ep))));
|
|
289
292
|
}
|
|
290
293
|
catch (e) {
|
|
291
294
|
// This just means that the directory doesn't contain any declared entrypoints.
|