@plaudit/webpack-extensions 2.61.2 → 2.62.1
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/build/plugins/AbstractMultiPhaseLibraryPlugin.d.ts +14 -0
- package/build/plugins/AbstractMultiPhaseLibraryPlugin.js +88 -0
- package/build/plugins/ExtensionsConfigFileGeneratorPlugin.d.ts +5 -6
- package/build/plugins/ExtensionsConfigFileGeneratorPlugin.js +83 -118
- package/build/plugins/ExtensionsConfigFileGeneratorPluginV1.d.ts +8 -0
- package/build/plugins/ExtensionsConfigFileGeneratorPluginV1.js +49 -0
- package/build/plugins/PlainEntrypointsConfigFileGeneratorPlugin.d.ts +5 -10
- package/build/plugins/PlainEntrypointsConfigFileGeneratorPlugin.js +36 -62
- package/build/plugins/PlainEntrypointsStyleBlockJSONPlugin.d.ts +25 -0
- package/build/plugins/PlainEntrypointsStyleBlockJSONPlugin.js +434 -0
- package/build/plugins/SpecialAssetHandlingPlugin.d.ts +4 -4
- package/build/plugins/SpecialAssetHandlingPlugin.js +13 -19
- package/build/plugins/UnifiedLoaderGenerator.js +2 -2
- package/build/plugins/WPMLConfigBuilder.d.ts +1 -3
- package/build/plugins/WPMLConfigBuilder.js +14 -22
- package/build/shared.d.ts +33 -17
- package/build/shared.js +80 -27
- package/build/utils/common-config-helpers.d.ts +2 -2
- package/build/utils/common-config-helpers.js +84 -27
- package/build/utils/php-writer.d.ts +129 -16
- package/build/utils/php-writer.js +261 -41
- package/build/wordpress-scripts-wrapper.js +14 -10
- package/package.json +1 -1
- package/build/plugins/BlockJSONManagingPlugin.d.ts +0 -40
- package/build/plugins/BlockJSONManagingPlugin.js +0 -594
|
@@ -6,18 +6,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.WPMLConfigBuilderPlugin = void 0;
|
|
7
7
|
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const shared_1 = require("../shared");
|
|
9
10
|
const jsdom_1 = require("jsdom");
|
|
10
11
|
const webpack_1 = require("webpack");
|
|
11
12
|
const xml_formatter_1 = __importDefault(require("xml-formatter"));
|
|
12
13
|
class WPMLConfigBuilderPlugin {
|
|
13
|
-
blockJSONManagingPlugin;
|
|
14
14
|
destDir;
|
|
15
15
|
static jsdomInstance;
|
|
16
16
|
static domParser;
|
|
17
17
|
static xmlSerializer;
|
|
18
18
|
parsedDocumentsCache = new Map();
|
|
19
|
-
constructor(
|
|
20
|
-
this.blockJSONManagingPlugin = blockJSONManagingPlugin;
|
|
19
|
+
constructor(destDir) {
|
|
21
20
|
this.destDir = destDir;
|
|
22
21
|
}
|
|
23
22
|
apply(compiler) {
|
|
@@ -52,7 +51,7 @@ class WPMLConfigBuilderPlugin {
|
|
|
52
51
|
for (const category of nonMergeableCategories) {
|
|
53
52
|
for (const [key, value] of Object.entries(wpmlConfig[category])) {
|
|
54
53
|
if (key in mergedConfig[category]) {
|
|
55
|
-
compilation.errors.push(newWebpackErrorForFile(`Already encountered a definition for the ${category} entry named, "${key}"`, file));
|
|
54
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(`Already encountered a definition for the ${category} entry named, "${key}"`, file));
|
|
56
55
|
}
|
|
57
56
|
else {
|
|
58
57
|
mergedConfig[category][key] = value;
|
|
@@ -69,7 +68,7 @@ class WPMLConfigBuilderPlugin {
|
|
|
69
68
|
}
|
|
70
69
|
catch (e) {
|
|
71
70
|
if (typeof e === 'string') {
|
|
72
|
-
compilation.errors.push(newWebpackErrorForFile(e, file));
|
|
71
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(e, file));
|
|
73
72
|
}
|
|
74
73
|
else {
|
|
75
74
|
compilation.errors.push(e);
|
|
@@ -145,7 +144,6 @@ class WPMLConfigBuilderPlugin {
|
|
|
145
144
|
}
|
|
146
145
|
appendNamedElementsListToConfig("shortcodes", mergedConfig.shortcodes, config);
|
|
147
146
|
appendNamedElementsListToConfig("taxonomies", mergedConfig.taxonomies, config);
|
|
148
|
-
this.blockJSONManagingPlugin.additionalMetadata.set("wpml-config", true);
|
|
149
147
|
compilation[wpmlEmitPath in compilation.assets ? 'updateAsset' : 'emitAsset'](wpmlEmitPath, new webpack_1.sources.RawSource(WPMLConfigBuilderPlugin.prettyPrintXML(config)));
|
|
150
148
|
});
|
|
151
149
|
});
|
|
@@ -205,7 +203,7 @@ class WPMLConfigBuilderPlugin {
|
|
|
205
203
|
}
|
|
206
204
|
catch (e) {
|
|
207
205
|
if (typeof e === 'string') {
|
|
208
|
-
compilation.errors.push(newWebpackErrorForFile(e, file));
|
|
206
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(e, file));
|
|
209
207
|
}
|
|
210
208
|
else {
|
|
211
209
|
compilation.errors.push(e);
|
|
@@ -225,12 +223,12 @@ class WPMLConfigBuilderPlugin {
|
|
|
225
223
|
const tag = child.getElementsByTagName("tag")[0];
|
|
226
224
|
const shortcodeName = tag?.textContent?.trim();
|
|
227
225
|
if (!shortcodeName) {
|
|
228
|
-
compilation.errors.push(newWebpackErrorForFile(`A shortcode entry in a wpml-config.xml file is missing its tag name.`, file));
|
|
226
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(`A shortcode entry in a wpml-config.xml file is missing its tag name.`, file));
|
|
229
227
|
continue;
|
|
230
228
|
}
|
|
231
229
|
const existing = res.shortcodes[shortcodeName];
|
|
232
230
|
if (existing) {
|
|
233
|
-
compilation.errors.push(newWebpackErrorForFile(`Already encountered a definition for the shortcode entry named, "${shortcodeName}"`, file));
|
|
231
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(`Already encountered a definition for the shortcode entry named, "${shortcodeName}"`, file));
|
|
234
232
|
}
|
|
235
233
|
else {
|
|
236
234
|
res.shortcodes[shortcodeName] = child;
|
|
@@ -241,7 +239,7 @@ class WPMLConfigBuilderPlugin {
|
|
|
241
239
|
importStandardTranslateOptionMap(element, file, "taxonomy", res.taxonomies, compilation);
|
|
242
240
|
break;
|
|
243
241
|
default:
|
|
244
|
-
compilation.errors.push(newWebpackErrorForFile(`Unsupported element type in a wpml-config.xml file: ${element.nodeName}`, file));
|
|
242
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(`Unsupported element type in a wpml-config.xml file: ${element.nodeName}`, file));
|
|
245
243
|
break;
|
|
246
244
|
}
|
|
247
245
|
}
|
|
@@ -254,17 +252,17 @@ function importStandardTranslateOptionMap(element, file, type, actionMap, compil
|
|
|
254
252
|
for (const child of element.children) {
|
|
255
253
|
const field = child.textContent;
|
|
256
254
|
if (!field) {
|
|
257
|
-
compilation.errors.push(newWebpackErrorForFile(`Encountered an empty ${type} entry in a wpml-config.xml file.`, file));
|
|
255
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(`Encountered an empty ${type} entry in a wpml-config.xml file.`, file));
|
|
258
256
|
continue;
|
|
259
257
|
}
|
|
260
258
|
const translate = child.getAttribute("translate");
|
|
261
259
|
if (!translate) {
|
|
262
|
-
compilation.errors.push(newWebpackErrorForFile(`The ${type} entry for ${field} is missing the translate attribute.`, file));
|
|
260
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(`The ${type} entry for ${field} is missing the translate attribute.`, file));
|
|
263
261
|
continue;
|
|
264
262
|
}
|
|
265
263
|
const existing = actionMap[field];
|
|
266
264
|
if (existing) {
|
|
267
|
-
compilation.errors.push(newWebpackErrorForFile(`Already encountered a definition for the ${type} entry named, "${field}"`, file));
|
|
265
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(`Already encountered a definition for the ${type} entry named, "${field}"`, file));
|
|
268
266
|
}
|
|
269
267
|
else {
|
|
270
268
|
actionMap[field] = child;
|
|
@@ -275,17 +273,17 @@ function importStandardTranslateActionMap(element, file, type, actionMap, compil
|
|
|
275
273
|
for (const child of element.children) {
|
|
276
274
|
const field = child.textContent?.trim();
|
|
277
275
|
if (!field) {
|
|
278
|
-
compilation.errors.push(newWebpackErrorForFile(`Encountered a empty ${type} entry without a name in a wpml-config.xml file.`, file));
|
|
276
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(`Encountered a empty ${type} entry without a name in a wpml-config.xml file.`, file));
|
|
279
277
|
continue;
|
|
280
278
|
}
|
|
281
279
|
const action = child.getAttribute("action");
|
|
282
280
|
if (!action) {
|
|
283
|
-
compilation.errors.push(newWebpackErrorForFile(`The ${type} entry for ${field} is missing an action.`, file));
|
|
281
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(`The ${type} entry for ${field} is missing an action.`, file));
|
|
284
282
|
continue;
|
|
285
283
|
}
|
|
286
284
|
const existing = actionMap[field];
|
|
287
285
|
if (existing) {
|
|
288
|
-
compilation.errors.push(newWebpackErrorForFile(`Already encountered a definition for the ${type} entry named, "${field}"`, file));
|
|
286
|
+
compilation.errors.push((0, shared_1.newWebpackErrorForFile)(`Already encountered a definition for the ${type} entry named, "${field}"`, file));
|
|
289
287
|
}
|
|
290
288
|
else {
|
|
291
289
|
actionMap[field] = child;
|
|
@@ -433,12 +431,6 @@ function mergeGenericSettingsKeys(existing, novel) {
|
|
|
433
431
|
}
|
|
434
432
|
return { ...existing, ...novel, keys: mergeGenericSettingsKeyLists(existing.keys, novel.keys) };
|
|
435
433
|
}
|
|
436
|
-
function newWebpackErrorForFile(error, file) {
|
|
437
|
-
const res = new webpack_1.WebpackError(error);
|
|
438
|
-
res.hideStack = true;
|
|
439
|
-
res.file = file;
|
|
440
|
-
return res;
|
|
441
|
-
}
|
|
442
434
|
function writeGenericSettingsKeys(keys, parent, document) {
|
|
443
435
|
parent.append(...keys.sort((a, b) => a.name.localeCompare(b.name)).map(key => {
|
|
444
436
|
const element = document.createElement("key");
|
package/build/shared.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { PHPWriter } from "./utils/php-writer";
|
|
1
2
|
import type { Options as PostcssFunctionsOptions } from "postcss-functions";
|
|
2
|
-
import type
|
|
3
|
+
import { type Configuration, type EntryOptions, WebpackError } from "webpack";
|
|
3
4
|
export type RawAssetData = Record<string, {
|
|
4
5
|
dependencies: string[];
|
|
5
6
|
version: string;
|
|
@@ -71,30 +72,45 @@ export type PlauditWordpressWebpackConfig = {
|
|
|
71
72
|
srcPrefixes?: string[];
|
|
72
73
|
useUnifiedLoader?: boolean;
|
|
73
74
|
};
|
|
74
|
-
export
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
type
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
export type SmuggledBlockEntrypointInfo = [
|
|
76
|
+
string,
|
|
77
|
+
EntrypointFields[number],
|
|
78
|
+
string,
|
|
79
|
+
string,
|
|
80
|
+
string
|
|
81
|
+
];
|
|
82
|
+
export type UnpackedBlockEntrypointInfo = {
|
|
83
|
+
blockJsonOrigin: string;
|
|
84
|
+
entrypointField: EntrypointFields[number];
|
|
85
|
+
originalValue: string;
|
|
86
|
+
entrypointName: string;
|
|
87
|
+
handle: string;
|
|
84
88
|
};
|
|
85
|
-
export declare
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
export declare function packBlockEntrypointInfoForSmuggling(info: UnpackedBlockEntrypointInfo): SmuggledBlockEntrypointInfo;
|
|
90
|
+
export declare function unpackSmuggledBlockEntrypointInfo(library: EntryOptions['library']): UnpackedBlockEntrypointInfo | undefined;
|
|
91
|
+
export declare function isSmuggledLibraryInfo(libraryName: NonNullable<EntryOptions['library']>['name'] | undefined): libraryName is SmuggledBlockEntrypointInfo;
|
|
92
|
+
export declare function makeEmittableConfigPHP(data: any, asFullFile: boolean, parentIndent?: string): string;
|
|
93
|
+
export type EntrypointFields = ["viewScriptModule", "scriptModule"] | ["editorStyle", "viewStyle", "style", "editorScript", "viewScript", "script"];
|
|
94
|
+
export declare const entrypointFields: ReadonlyArray<EntrypointFields[number]>;
|
|
95
|
+
export declare function convertEntrypointFieldForAssetType(entrypointField: EntrypointFields[number], assetType: 'script' | 'style'): EntrypointFields[number];
|
|
90
96
|
export declare function leadingSlashIt(pathOrSomething: string): string;
|
|
91
97
|
export declare const scriptExtension: RegExp;
|
|
92
98
|
export declare const scriptWithoutModuleExtension: RegExp;
|
|
93
99
|
export declare const scriptWithModuleExtension: RegExp;
|
|
94
100
|
export declare const styleExtension: RegExp;
|
|
95
|
-
export declare function scriptOrStyleTest(entryPath: string, scriptExtension: RegExp): "" | "
|
|
101
|
+
export declare function scriptOrStyleTest(entryPath: string, scriptExtension: RegExp): "" | "style" | "script";
|
|
102
|
+
export declare function isStyleField(field: string): boolean;
|
|
103
|
+
export declare function isScriptModuleField(field: string): boolean;
|
|
96
104
|
export declare function hasAtLeastOneItem<T>(list: T[]): list is [T, ...T[]];
|
|
105
|
+
export type TupleOf<T, N extends number> = N extends N ? number extends N ? T[] : _TupleOf<T, N, []> : never;
|
|
106
|
+
type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N ? R : _TupleOf<T, N, [T, ...R]>;
|
|
107
|
+
export declare function arrayIsLength<T, N extends number>(arr: T[] | null | undefined, length: N): arr is TupleOf<T, N>;
|
|
97
108
|
export declare function kebabCase(value: string): string;
|
|
98
109
|
export declare function loadEnvFile(filePath: string): Promise<Record<string, string>>;
|
|
99
110
|
export declare function parseEnvFile(contents: string): Record<string, string>;
|
|
111
|
+
export declare function newWebpackErrorForFile(error: string, file: string): WebpackError;
|
|
112
|
+
/**
|
|
113
|
+
* 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
|
|
114
|
+
*/
|
|
115
|
+
export declare function emitResolveBaseUriFunction(writer: PHPWriter): void;
|
|
100
116
|
export {};
|
package/build/shared.js
CHANGED
|
@@ -3,18 +3,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.styleExtension = exports.scriptWithModuleExtension = exports.scriptWithoutModuleExtension = exports.scriptExtension = exports.
|
|
6
|
+
exports.styleExtension = exports.scriptWithModuleExtension = exports.scriptWithoutModuleExtension = exports.scriptExtension = exports.entrypointFields = exports.standardLocationNames = void 0;
|
|
7
7
|
exports.isRawAssetData = isRawAssetData;
|
|
8
8
|
exports.determineCurrentSourceType = determineCurrentSourceType;
|
|
9
|
+
exports.packBlockEntrypointInfoForSmuggling = packBlockEntrypointInfoForSmuggling;
|
|
10
|
+
exports.unpackSmuggledBlockEntrypointInfo = unpackSmuggledBlockEntrypointInfo;
|
|
11
|
+
exports.isSmuggledLibraryInfo = isSmuggledLibraryInfo;
|
|
9
12
|
exports.makeEmittableConfigPHP = makeEmittableConfigPHP;
|
|
13
|
+
exports.convertEntrypointFieldForAssetType = convertEntrypointFieldForAssetType;
|
|
10
14
|
exports.leadingSlashIt = leadingSlashIt;
|
|
11
15
|
exports.scriptOrStyleTest = scriptOrStyleTest;
|
|
16
|
+
exports.isStyleField = isStyleField;
|
|
17
|
+
exports.isScriptModuleField = isScriptModuleField;
|
|
12
18
|
exports.hasAtLeastOneItem = hasAtLeastOneItem;
|
|
19
|
+
exports.arrayIsLength = arrayIsLength;
|
|
13
20
|
exports.kebabCase = kebabCase;
|
|
14
21
|
exports.loadEnvFile = loadEnvFile;
|
|
15
22
|
exports.parseEnvFile = parseEnvFile;
|
|
16
|
-
|
|
23
|
+
exports.newWebpackErrorForFile = newWebpackErrorForFile;
|
|
24
|
+
exports.emitResolveBaseUriFunction = emitResolveBaseUriFunction;
|
|
17
25
|
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
26
|
+
const json_to_php_but_with____injection_1 = __importDefault(require("./utils/json-to-php-but-with-__-injection"));
|
|
27
|
+
const php_writer_1 = require("./utils/php-writer");
|
|
28
|
+
const webpack_1 = require("webpack");
|
|
18
29
|
function isRawAssetData(thing) {
|
|
19
30
|
if (!thing || typeof thing !== 'object') {
|
|
20
31
|
return false;
|
|
@@ -45,34 +56,37 @@ function determineCurrentSourceType(dest, srcIsDirectory) {
|
|
|
45
56
|
return dest.directoryLayout;
|
|
46
57
|
}
|
|
47
58
|
}
|
|
48
|
-
function
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
class SyncsManager {
|
|
57
|
-
readinessMapping = new Map();
|
|
58
|
-
get(name) {
|
|
59
|
-
const res = this.readinessMapping.get(name);
|
|
60
|
-
if (res) {
|
|
61
|
-
return res;
|
|
62
|
-
}
|
|
63
|
-
this.readinessMapping.set(name, { nonModule: this.makeSync(), module: this.makeSync() });
|
|
64
|
-
return this.readinessMapping.get(name);
|
|
59
|
+
function packBlockEntrypointInfoForSmuggling(info) {
|
|
60
|
+
return [info.blockJsonOrigin, info.entrypointField, info.originalValue, info.entrypointName, info.handle];
|
|
61
|
+
}
|
|
62
|
+
function unpackSmuggledBlockEntrypointInfo(library) {
|
|
63
|
+
const libraryName = library?.name;
|
|
64
|
+
if (!isSmuggledLibraryInfo(libraryName)) {
|
|
65
|
+
return undefined;
|
|
65
66
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
});
|
|
72
|
-
return res;
|
|
67
|
+
return { blockJsonOrigin: libraryName[0], entrypointField: libraryName[1], originalValue: libraryName[2], entrypointName: libraryName[3], handle: libraryName[4] };
|
|
68
|
+
}
|
|
69
|
+
function isSmuggledLibraryInfo(libraryName) {
|
|
70
|
+
if (!Array.isArray(libraryName) || !arrayIsLength(libraryName, 5) || libraryName.some(item => typeof item !== 'string')) {
|
|
71
|
+
return false;
|
|
73
72
|
}
|
|
73
|
+
return libraryName[0].endsWith("/block.json") && exports.entrypointFields.includes(libraryName[1]);
|
|
74
|
+
}
|
|
75
|
+
function makeEmittableConfigPHP(data, asFullFile, parentIndent = "") {
|
|
76
|
+
const prettyPrintedMetadata = json_to_php_but_with____injection_1.default.make({ indent: "\t", linebreak: "\n", shortArraySyntax: true })(data, parentIndent)
|
|
77
|
+
.replaceAll(/(\n\t*)\[\s+],/gs, "$1[],")
|
|
78
|
+
.replaceAll(/\[\n\t+([^\n]+)\n\t+]/gs, (_, inner) => `[${inner.trim()}]`)
|
|
79
|
+
.replaceAll(/'rest' => \[\n\t+(\[(?:'[^']+')?]),\n\t+('[^']+')(?:,\n\t+(\[[^\n]+]))?\n\t+]/gs, (_, deps, hash, args) => `'rest' => [${[deps, hash, args].filter(value => !!value).join(", ")}]`);
|
|
80
|
+
return asFullFile ? `<?php return ${prettyPrintedMetadata};` : prettyPrintedMetadata.trim();
|
|
81
|
+
}
|
|
82
|
+
exports.entrypointFields = [
|
|
83
|
+
"editorStyle", "viewStyle", "style", "editorScript", "viewScript", "script", "viewScriptModule", "scriptModule"
|
|
84
|
+
];
|
|
85
|
+
function convertEntrypointFieldForAssetType(entrypointField, assetType) {
|
|
86
|
+
// Using these word fragments instead of the full words allows us to avoid having to deal with the capitalization of the first letter
|
|
87
|
+
const searchRep = assetType === 'script' ? ['tyle', 'cript'] : ['cript', 'tyle'];
|
|
88
|
+
return entrypointField.replace(...searchRep);
|
|
74
89
|
}
|
|
75
|
-
exports.SyncsManager = SyncsManager;
|
|
76
90
|
function leadingSlashIt(pathOrSomething) {
|
|
77
91
|
return pathOrSomething.startsWith('/') ? pathOrSomething : ('/' + pathOrSomething);
|
|
78
92
|
}
|
|
@@ -83,9 +97,18 @@ exports.styleExtension = /(?<filename>.+)(?<extension>\.(p?c|sa)ss)$/i;
|
|
|
83
97
|
function scriptOrStyleTest(entryPath, scriptExtension) {
|
|
84
98
|
return scriptExtension.test(entryPath) ? "script" : (exports.styleExtension.test(entryPath) ? "style" : "");
|
|
85
99
|
}
|
|
100
|
+
function isStyleField(field) {
|
|
101
|
+
return field.endsWith("tyle");
|
|
102
|
+
}
|
|
103
|
+
function isScriptModuleField(field) {
|
|
104
|
+
return field.includes("odule");
|
|
105
|
+
}
|
|
86
106
|
function hasAtLeastOneItem(list) {
|
|
87
107
|
return list.length > 0;
|
|
88
108
|
}
|
|
109
|
+
function arrayIsLength(arr, length) {
|
|
110
|
+
return !!arr && arr.length === length;
|
|
111
|
+
}
|
|
89
112
|
function kebabCase(value) {
|
|
90
113
|
const kebabCaseRegexes = [[/([a-z])([A-Z])/g, "$1-$2"], [/[\s_.\-]+/g, "-"]];
|
|
91
114
|
return kebabCaseRegexes.reduce((str, [pattern, replacement]) => str.replace(pattern, replacement), value).toLowerCase();
|
|
@@ -101,3 +124,33 @@ function parseEnvFile(contents) {
|
|
|
101
124
|
return equalsPos === -1 ? [line, ""] : [line.substring(0, equalsPos), line.substring(equalsPos + 1)];
|
|
102
125
|
}));
|
|
103
126
|
}
|
|
127
|
+
function newWebpackErrorForFile(error, file) {
|
|
128
|
+
const res = new webpack_1.WebpackError(error);
|
|
129
|
+
res.hideStack = true;
|
|
130
|
+
res.file = file;
|
|
131
|
+
return res;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 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
|
|
135
|
+
*/
|
|
136
|
+
function emitResolveBaseUriFunction(writer) {
|
|
137
|
+
const dir = new php_writer_1.Var("dir");
|
|
138
|
+
const baseUris = new php_writer_1.Var("base_uris");
|
|
139
|
+
const assignmentTarget = new php_writer_1.ArrayAccess(baseUris, dir);
|
|
140
|
+
const path = new php_writer_1.Var("path");
|
|
141
|
+
writer.function("plaudit_webpack_extensions__resolve_base_uri", [dir], writer => {
|
|
142
|
+
writer
|
|
143
|
+
.static(baseUris, { initializer: [] })
|
|
144
|
+
.if(php_writer_1.Expr.isset(assignmentTarget))
|
|
145
|
+
.return(assignmentTarget)
|
|
146
|
+
.elseIf(php_writer_1.Expr.call("str_starts_with", [dir, php_writer_1.Constants.ABSPATH]))
|
|
147
|
+
.assign(path, php_writer_1.Expr.call("ltrim", [php_writer_1.Expr.call("substr", [dir, php_writer_1.Expr.call("strlen", [php_writer_1.Constants.ABSPATH])]), "/"]))
|
|
148
|
+
.elseIf(php_writer_1.Expr.call("str_starts_with", [dir, "/workspace/website"]))
|
|
149
|
+
.assign(path, php_writer_1.Expr.call("ltrim", [php_writer_1.Expr.call("substr", [dir, 18]), "/"]))
|
|
150
|
+
.else()
|
|
151
|
+
.call("error_log", ["UNABLE TO FIGURE OUT WHAT THE RELATIVE PATH TO THE BUILT FILES DIRECTORY SHOULD BE"])
|
|
152
|
+
.assign(path, "")
|
|
153
|
+
.endIf()
|
|
154
|
+
.call("trailingslashit", [php_writer_1.Expr.call("home_url", [path])], { return: true, assignTo: assignmentTarget });
|
|
155
|
+
}, { returnType: "string", includeExistenceCheck: true });
|
|
156
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PlauditWordpressWebpackConfig, VerifiedAdvancedOutputConfig } from "../shared";
|
|
1
|
+
import { EntrypointFields, PlauditWordpressWebpackConfig, VerifiedAdvancedOutputConfig } from "../shared";
|
|
2
2
|
import type { Compiler, Configuration, EntryObject, WebpackPluginInstance } from "webpack";
|
|
3
3
|
import type WebpackRemoveEmptyScriptsPlugin from "webpack-remove-empty-scripts";
|
|
4
4
|
export type VerifiedPlauditWordpressWebpackConfig = Required<Omit<PlauditWordpressWebpackConfig, 'variables' | 'src' | 'externals'>> & {
|
|
@@ -10,7 +10,7 @@ export type CommonPluginConfig = {
|
|
|
10
10
|
removeEmptyScriptsPlugin: WebpackRemoveEmptyScriptsPlugin;
|
|
11
11
|
};
|
|
12
12
|
export type CommonConfigProcessingResult = {
|
|
13
|
-
entrypointFields:
|
|
13
|
+
entrypointFields: EntrypointFields;
|
|
14
14
|
fixedRules: NonNullable<Configuration['module']>['rules'];
|
|
15
15
|
processingModules: boolean;
|
|
16
16
|
scriptExtension: RegExp;
|
|
@@ -10,7 +10,6 @@ exports.commonMakeWebpackConfig = commonMakeWebpackConfig;
|
|
|
10
10
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
11
11
|
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
12
12
|
const node_path_1 = __importDefault(require("node:path"));
|
|
13
|
-
const BlockJSONManagingPlugin_1 = require("../plugins/BlockJSONManagingPlugin");
|
|
14
13
|
const shared_1 = require("../shared");
|
|
15
14
|
const copy_webpack_plugin_1 = __importDefault(require("copy-webpack-plugin"));
|
|
16
15
|
let isInThemeCache = undefined;
|
|
@@ -34,20 +33,20 @@ function groupEntrypointsByAssetFile(entrypoints, entrypointNameExtractor) {
|
|
|
34
33
|
}
|
|
35
34
|
return seenPaths;
|
|
36
35
|
}
|
|
37
|
-
function mapToRealEntrypoints(entrypoint, dir, args = {}) {
|
|
38
|
-
const { mapper = ep => ep,
|
|
36
|
+
function mapToRealEntrypoints(entrypoint, dir, supportedExtensions, args = {}) {
|
|
37
|
+
const { mapper = ep => ep, destDir } = args;
|
|
39
38
|
return (Array.isArray(entrypoint) ? entrypoint : [entrypoint])
|
|
40
39
|
.map(ep => joinPossiblyAbsolutePaths(dir, mapper(ep)))
|
|
41
|
-
.filter(ep => node_fs_1.default.statSync(ep, { throwIfNoEntry: false })?.isFile())
|
|
40
|
+
.filter(ep => supportedExtensions(ep) && node_fs_1.default.statSync(ep, { throwIfNoEntry: false })?.isFile())
|
|
42
41
|
.map(ep => {
|
|
43
42
|
const parsedEntrypoint = node_path_1.default.parse(ep);
|
|
44
|
-
return [joinPossiblyAbsolutePaths(destDir, node_path_1.default.basename(parsedEntrypoint.dir), parsedEntrypoint.name), { import: ep
|
|
43
|
+
return [joinPossiblyAbsolutePaths(destDir, node_path_1.default.basename(parsedEntrypoint.dir), parsedEntrypoint.name), { import: ep }];
|
|
45
44
|
});
|
|
46
45
|
}
|
|
47
|
-
function parseEntrypointsJSON(dir, dest) {
|
|
46
|
+
function parseEntrypointsJSON(dir, dest, supportedExtensions) {
|
|
48
47
|
const entrypointsJSON = JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(dir, 'entrypoints.json'), 'utf8'));
|
|
49
48
|
if (Array.isArray(entrypointsJSON)) {
|
|
50
|
-
return mapToRealEntrypoints(entrypointsJSON, dir, { destDir: dest.destination });
|
|
49
|
+
return mapToRealEntrypoints(entrypointsJSON, dir, supportedExtensions, { destDir: dest.destination });
|
|
51
50
|
}
|
|
52
51
|
else {
|
|
53
52
|
return Object.entries(entrypointsJSON).map(([name, config]) => {
|
|
@@ -115,31 +114,95 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
|
|
|
115
114
|
if (!dirent.isDirectory()) {
|
|
116
115
|
continue;
|
|
117
116
|
}
|
|
118
|
-
//TODO:
|
|
117
|
+
//TODO: It should be possible to handle all block.json files simultaneously, which would allow for better detection of repeated code
|
|
119
118
|
const dir = joinPossiblyAbsolutePaths(srcRoot, dirent.name);
|
|
120
119
|
loadingEntrypoints.push(new Promise(async (resolve) => {
|
|
121
120
|
const rawEntrypoints = [];
|
|
122
121
|
const wpmlFiles = [];
|
|
123
122
|
try {
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
const blockJsonOrigin = node_path_1.default.join(dir, 'block.json');
|
|
124
|
+
const blockJson = JSON.parse(await promises_1.default.readFile(blockJsonOrigin, 'utf8'));
|
|
125
|
+
const blockJsonChunkName = node_path_1.default.join(dest.destination, node_path_1.default.relative(srcRoot, dir), "block");
|
|
126
|
+
const presentEntrypoints = (await Promise.all(entrypointFields
|
|
127
|
+
.filter(entrypointField => entrypointField in blockJson)
|
|
128
|
+
.flatMap(entrypointField => {
|
|
129
|
+
return (Array.isArray(blockJson[entrypointField]) ? blockJson[entrypointField] : [blockJson[entrypointField]])
|
|
130
|
+
.filter(originalValue => originalValue.startsWith("file:"))
|
|
131
|
+
.map(originalValue => {
|
|
132
|
+
const entrypointPath = originalValue.substring(5);
|
|
133
|
+
const absoluteSrc = node_path_1.default.normalize(node_path_1.default.join(dir, entrypointPath));
|
|
134
|
+
return promises_1.default.stat(absoluteSrc)
|
|
135
|
+
.then(stats => {
|
|
136
|
+
if (stats.isFile()) {
|
|
137
|
+
const parsedEntrypoint = node_path_1.default.parse(node_path_1.default.normalize(node_path_1.default.join(dest.destination, node_path_1.default.relative(srcRoot, dir), entrypointPath)));
|
|
138
|
+
const extensionlessExpectedSrc = node_path_1.default.normalize(node_path_1.default.join(parsedEntrypoint.dir, parsedEntrypoint.name));
|
|
139
|
+
const entrypointName = node_path_1.default.normalize(joinPossiblyAbsolutePaths(parsedEntrypoint.dir, parsedEntrypoint.name));
|
|
140
|
+
return { entrypointField, originalValue, entrypointName, extensionlessExpectedSrc, absoluteSrc };
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
}, () => undefined);
|
|
146
|
+
});
|
|
147
|
+
}))).filter(pe => pe !== undefined);
|
|
148
|
+
const entrypointNamesWithEffectiveDuplicates = presentEntrypoints
|
|
149
|
+
.map(entry => entry.entrypointName)
|
|
150
|
+
.reduce((a, dest) => {
|
|
151
|
+
// If it's undefined, then this is the first instance, otherwise, it's not the first instance and, therefore, is expected to be a duplicate
|
|
152
|
+
a[dest] = (a[dest] !== undefined);
|
|
153
|
+
return a;
|
|
154
|
+
}, {});
|
|
155
|
+
const handlePrefix = blockJson['name']?.toString() ?? `__UNKNOWN_PREFIX__/${dirent.name}`;
|
|
156
|
+
const allocatedDestinations = {};
|
|
157
|
+
const resolvedBlockEntrypoints = presentEntrypoints
|
|
158
|
+
.map(presentEntrypoint => {
|
|
159
|
+
const overallSource = node_path_1.default.dirname(blockJsonOrigin);
|
|
160
|
+
const overallSourceRelativeName = node_path_1.default.relative(overallSource, node_path_1.default.normalize(node_path_1.default.join(blockJsonOrigin, node_path_1.default.relative(overallSource, presentEntrypoint.extensionlessExpectedSrc))));
|
|
161
|
+
if (!entrypointNamesWithEffectiveDuplicates[presentEntrypoint.entrypointName]) {
|
|
162
|
+
return { blockJsonOrigin, ...presentEntrypoint, handle: `${handlePrefix}/${overallSourceRelativeName}` };
|
|
129
163
|
}
|
|
130
|
-
|
|
164
|
+
const baseSuffix = `_${(0, shared_1.isStyleField)(presentEntrypoint.entrypointField) ? "style" : "script"}`;
|
|
165
|
+
let count = 0, suffix = baseSuffix, deduplicatedEntrypointName;
|
|
166
|
+
while (((deduplicatedEntrypointName = (presentEntrypoint.entrypointName + suffix)) in allocatedDestinations)
|
|
167
|
+
&& allocatedDestinations[deduplicatedEntrypointName] !== presentEntrypoint.originalValue) {
|
|
168
|
+
suffix = baseSuffix + "_" + (++count);
|
|
169
|
+
}
|
|
170
|
+
allocatedDestinations[deduplicatedEntrypointName] = presentEntrypoint.originalValue;
|
|
171
|
+
const deduplicatedExtensionlessExpectedSrc = presentEntrypoint.extensionlessExpectedSrc + suffix;
|
|
172
|
+
return {
|
|
173
|
+
blockJsonOrigin,
|
|
174
|
+
...presentEntrypoint,
|
|
175
|
+
entrypointName: deduplicatedEntrypointName,
|
|
176
|
+
extensionlessExpectedSrc: deduplicatedExtensionlessExpectedSrc,
|
|
177
|
+
handle: `${handlePrefix}/${count ? overallSourceRelativeName + "_" + count : overallSourceRelativeName}`
|
|
178
|
+
};
|
|
179
|
+
});
|
|
180
|
+
rawEntrypoints.push(...resolvedBlockEntrypoints
|
|
181
|
+
.map(resolvedBlockEntrypoint => {
|
|
182
|
+
return [
|
|
183
|
+
resolvedBlockEntrypoint.entrypointName,
|
|
184
|
+
{
|
|
185
|
+
import: resolvedBlockEntrypoint.absoluteSrc,
|
|
186
|
+
library: { name: (0, shared_1.packBlockEntrypointInfoForSmuggling)(resolvedBlockEntrypoint), type: `block-json-${dest.destination}` }
|
|
187
|
+
}
|
|
188
|
+
];
|
|
189
|
+
}));
|
|
190
|
+
rawEntrypoints.push([blockJsonChunkName, { import: blockJsonOrigin, library: { name: "block-json-inclusion-assurance", type: `block-json-${dest.destination}` } }]);
|
|
131
191
|
wpmlFiles.push(node_path_1.default.join(dir, 'block.json'));
|
|
132
|
-
BlockJSONManagingPlugin_1.BlockJSONManagingPlugin.recordBlockJSONAssetSourceDir(blockJSONChunkName, dir);
|
|
133
192
|
}
|
|
134
193
|
catch (e) {
|
|
135
194
|
try {
|
|
136
195
|
const packageJSON = JSON.parse(await promises_1.default.readFile(node_path_1.default.join(dir, 'package.json'), 'utf8'));
|
|
137
|
-
|
|
138
|
-
|
|
196
|
+
if (packageJSON['main']) {
|
|
197
|
+
rawEntrypoints.push(...mapToRealEntrypoints(packageJSON['main'], dir, commonConfig.scriptExtension.test, { destDir: dest.destination }));
|
|
198
|
+
}
|
|
199
|
+
if (!processingModules && packageJSON['style']) {
|
|
200
|
+
rawEntrypoints.push(...mapToRealEntrypoints(packageJSON['style'], dir, shared_1.styleExtension.test, { destDir: dest.destination }));
|
|
201
|
+
}
|
|
139
202
|
}
|
|
140
203
|
catch (e) {
|
|
141
204
|
try {
|
|
142
|
-
rawEntrypoints.push(...parseEntrypointsJSON(dir, dest));
|
|
205
|
+
rawEntrypoints.push(...parseEntrypointsJSON(dir, dest, ep => commonConfig.scriptExtension.test(ep) || shared_1.styleExtension.test(ep)));
|
|
143
206
|
}
|
|
144
207
|
catch (e) {
|
|
145
208
|
// This just means that the directory doesn't contain any declared entrypoints.
|
|
@@ -173,22 +236,16 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
|
|
|
173
236
|
}
|
|
174
237
|
}
|
|
175
238
|
}
|
|
176
|
-
// This is used to allow for block.json dependencies to correctly account for name-deduplication
|
|
177
|
-
for (const [key, entry] of Object.entries(currentEntry)) {
|
|
178
|
-
if (typeof entry === 'object' && !Array.isArray(entry) && 'lazyDependent' in entry && typeof entry.lazyDependent === 'string') {
|
|
179
|
-
BlockJSONManagingPlugin_1.BlockJSONManagingPlugin.recordRawDependency(entry.lazyDependent, key);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
239
|
if (!processingModules) {
|
|
183
240
|
const wpmlEntrypointFiles = allEntrypoints.flatMap(e => e[1]);
|
|
184
241
|
try {
|
|
185
242
|
await promises_1.default.access(node_path_1.default.join(srcRoot, "wpml-config.xml"));
|
|
186
|
-
currentEntry["wpml-config.xml"] = { import: [node_path_1.default.join(srcRoot, "wpml-config.xml"), ...wpmlEntrypointFiles] };
|
|
243
|
+
currentEntry["wpml-config.xml"] = { import: [node_path_1.default.join(srcRoot, "wpml-config.xml"), ...wpmlEntrypointFiles], library: { type: `block-json-${dest.destination}` } };
|
|
187
244
|
}
|
|
188
245
|
catch (e) {
|
|
189
246
|
// If the wpml-config.xml file does not exist, just "import" the other files that will be used to build the emitted version
|
|
190
247
|
if (wpmlEntrypointFiles.length) {
|
|
191
|
-
currentEntry["wpml-config.xml"] = { import: wpmlEntrypointFiles };
|
|
248
|
+
currentEntry["wpml-config.xml"] = { import: wpmlEntrypointFiles, library: { type: `block-json-${dest.destination}` } };
|
|
192
249
|
}
|
|
193
250
|
}
|
|
194
251
|
}
|
|
@@ -260,7 +317,7 @@ function commonMakeWebpackConfig(config, commonConfig, webpackConfig, srcIsDirec
|
|
|
260
317
|
.map(plugin => !processingModules && plugin.constructor.name === 'CopyPlugin'
|
|
261
318
|
? new copy_webpack_plugin_1.default({
|
|
262
319
|
patterns: [{
|
|
263
|
-
from: standaloneBlocks ? '
|
|
320
|
+
from: standaloneBlocks ? '**/*.(php|twig|svg)' : '**/*.(asset\.php|svg)',
|
|
264
321
|
to: dest.destination,
|
|
265
322
|
context: srcRoot /* canCopyFiles can only be true if srcRoot is a string, so this is safe */, noErrorOnMissing: true
|
|
266
323
|
}]
|