@plaudit/webpack-extensions 2.38.0 → 2.40.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/build/wordpress-scripts-wrapper/AdditionalDependencyInjectorPlugin.d.ts +2 -1
- package/build/wordpress-scripts-wrapper/AdditionalDependencyInjectorPlugin.js +29 -36
- package/build/wordpress-scripts-wrapper/BlockJSONManagingPlugin.d.ts +10 -1
- package/build/wordpress-scripts-wrapper/BlockJSONManagingPlugin.js +292 -166
- package/build/wordpress-scripts-wrapper/WPMLConfigBuilder.d.ts +16 -0
- package/build/wordpress-scripts-wrapper/WPMLConfigBuilder.js +471 -0
- package/build/wordpress-scripts-wrapper/dependency-extraction-webpack-plugin-config-builder.d.ts +4 -1
- package/build/wordpress-scripts-wrapper/dependency-extraction-webpack-plugin-config-builder.js +22 -9
- package/build/wordpress-scripts-wrapper.d.ts +2 -0
- package/build/wordpress-scripts-wrapper.js +89 -44
- package/package.json +91 -72
|
@@ -2,6 +2,7 @@ import { type Compiler, type WebpackPluginInstance } from "webpack";
|
|
|
2
2
|
export default class AdditionalDependencyInjectorPlugin implements WebpackPluginInstance {
|
|
3
3
|
private readonly entrypointAdditionalDependencies;
|
|
4
4
|
private readonly processingModules;
|
|
5
|
-
|
|
5
|
+
private readonly addExternalizedDep;
|
|
6
|
+
constructor(entrypointAdditionalDependencies: string[], processingModules: boolean, addExternalizedDep: (dep: string) => void);
|
|
6
7
|
apply(compiler: Compiler): void;
|
|
7
8
|
}
|
|
@@ -8,53 +8,46 @@ const webpack_1 = require("webpack");
|
|
|
8
8
|
class AdditionalDependencyInjectorPlugin {
|
|
9
9
|
entrypointAdditionalDependencies;
|
|
10
10
|
processingModules;
|
|
11
|
-
|
|
11
|
+
addExternalizedDep;
|
|
12
|
+
constructor(entrypointAdditionalDependencies, processingModules, addExternalizedDep) {
|
|
12
13
|
this.entrypointAdditionalDependencies = entrypointAdditionalDependencies;
|
|
13
14
|
this.processingModules = processingModules;
|
|
15
|
+
this.addExternalizedDep = addExternalizedDep;
|
|
14
16
|
}
|
|
15
17
|
apply(compiler) {
|
|
16
18
|
compiler.hooks.thisCompilation.tap("AdditionalDependencyInjectorPlugin", compilation => {
|
|
17
19
|
compilation.hooks.processAssets.tap({
|
|
18
|
-
name: "
|
|
19
|
-
stage: webpack_1.Compilation.
|
|
20
|
-
},
|
|
21
|
-
const usableEntrypointTest = this.processingModules ? /\.
|
|
22
|
-
const assetSources = new Map();
|
|
20
|
+
name: "AdditionalDependencyInjectorPlugin_ProcessAssets_AddFakeModules",
|
|
21
|
+
stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
|
|
22
|
+
}, () => {
|
|
23
|
+
const usableEntrypointTest = this.processingModules ? /\.m[jt]sx?$/i : /\.[jt]sx?$/i;
|
|
23
24
|
for (const entrypoint of compilation.entrypoints.values()) {
|
|
24
25
|
const req = entrypoint.origins.filter(origin => usableEntrypointTest.test(origin.request))[0]?.request;
|
|
25
|
-
if (req) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
if (!req) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const additionalDependencies = [...this.entrypointAdditionalDependencies];
|
|
30
|
+
const firstLine = node_fs_1.default.readFileSync(req, 'utf8').trim().split(/\r?\n/)[0];
|
|
31
|
+
if (firstLine?.startsWith("//ADDITIONAL_DEPENDENCIES:")) {
|
|
32
|
+
additionalDependencies.push(...firstLine.substring(26).trim().split(',').map(dep => dep.trim()));
|
|
33
|
+
}
|
|
34
|
+
const chunk = entrypoint.getEntrypointChunk();
|
|
35
|
+
for (const additionalDep of additionalDependencies) {
|
|
36
|
+
this.addExternalizedDep(additionalDep);
|
|
37
|
+
compilation.chunkGraph.connectChunkAndModule(chunk, new webpack_1.ExternalModule("__REMOVE_ME__", "", additionalDep));
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
if (additionalDependencies.length > 0) {
|
|
47
|
-
const seen = new Set();
|
|
48
|
-
const additionalDeps = additionalDependencies.filter(dep => !seen.has(dep) && seen.add(dep)).sort().map(v => `'${v}'`).join(', ');
|
|
49
|
-
if (additionalDeps.length > 0) {
|
|
50
|
-
compilation.updateAsset(name, new webpack_1.sources.RawSource(asset.source().toString()
|
|
51
|
-
.replaceAll(/(?:, )?'wp-[^']+\/[^']+'/gi, '')
|
|
52
|
-
.replace(/('dependencies'\s+=>\s+(?:array\(|\[))(.*)([)\]], 'version')/g, (match, g1, g2, g3) => `${g1}${g2.length > 0 ? `${g2}, ${additionalDeps}` : additionalDeps}${g3}`)));
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
40
|
+
});
|
|
41
|
+
compilation.hooks.processAssets.tap({
|
|
42
|
+
name: "AdditionalDependencyInjectorPlugin_ProcessAssets_RemoveFakeModules",
|
|
43
|
+
stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_REPORT
|
|
44
|
+
}, () => {
|
|
45
|
+
for (const entrypoint of compilation.entrypoints.values()) {
|
|
46
|
+
const entrypointChunk = entrypoint.getEntrypointChunk();
|
|
47
|
+
for (const module of compilation.chunkGraph.getChunkModules(entrypointChunk)) {
|
|
48
|
+
if (module instanceof webpack_1.ExternalModule && module.request === '__REMOVE_ME__') {
|
|
49
|
+
compilation.chunkGraph.disconnectChunkAndModule(entrypointChunk, module);
|
|
55
50
|
}
|
|
56
|
-
compilation.updateAsset(name, new webpack_1.sources.RawSource(asset.source().toString()
|
|
57
|
-
.replaceAll(/(?:, )?'wp-[^']+\/[^']+'/gi, '')));
|
|
58
51
|
}
|
|
59
52
|
}
|
|
60
53
|
});
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Compilation, type Compiler, type WebpackPluginInstance } from "webpack";
|
|
2
2
|
export default class BlockJSONManagingPlugin implements WebpackPluginInstance {
|
|
3
3
|
private readonly standaloneBlocks;
|
|
4
4
|
private readonly processingModules;
|
|
5
5
|
static readonly mappableModuleKeys: readonly ["viewScriptModule", "scriptModule"];
|
|
6
6
|
static readonly mappableNonModuleKeys: readonly ["editorStyle", "style", "viewStyle", "editorScript", "script", "viewScript"];
|
|
7
|
+
private static readonly styleExtensionPattern;
|
|
8
|
+
private static readonly scriptExtensionPattern;
|
|
7
9
|
private static readonly mappableKeys;
|
|
8
10
|
private static readonly blockJsonToEntrypointsMap;
|
|
9
11
|
private static readonly blockJsonRawDependenciesMap;
|
|
10
12
|
private static readonly blockJSONAssetSourceDirs;
|
|
11
13
|
private static readonly blockJsonAssetKeyMapping;
|
|
14
|
+
private static readonly blockJsonAssetKeyReadinessMapping;
|
|
15
|
+
readonly additionalMetadata: Map<string, any>;
|
|
12
16
|
constructor(standaloneBlocks: boolean, processingModules: boolean);
|
|
13
17
|
static recordRawDependency(entrypoint: string, dependency: string): void;
|
|
14
18
|
static recordBlockJSONAssetSourceDir(entrypoint: string, source: string): void;
|
|
@@ -24,4 +28,9 @@ export default class BlockJSONManagingPlugin implements WebpackPluginInstance {
|
|
|
24
28
|
private static remapReferencedAssetFile;
|
|
25
29
|
private static getReferencedFileSlot;
|
|
26
30
|
private static addAssetToBlockJsonKey;
|
|
31
|
+
private registerAssetProcessor;
|
|
32
|
+
private static populateEntrypointsMap;
|
|
33
|
+
private registerBlockJsonProcessor;
|
|
34
|
+
private static normalizeRenderTemplate;
|
|
35
|
+
private static getSyncs;
|
|
27
36
|
}
|
|
@@ -13,11 +13,15 @@ class BlockJSONManagingPlugin {
|
|
|
13
13
|
processingModules;
|
|
14
14
|
static mappableModuleKeys = ["viewScriptModule", "scriptModule"];
|
|
15
15
|
static mappableNonModuleKeys = ["editorStyle", "style", "viewStyle", "editorScript", "script", "viewScript"];
|
|
16
|
+
static styleExtensionPattern = /\.(p?c|sa)ss$/i;
|
|
17
|
+
static scriptExtensionPattern = /\.m?[tj]sx?$/i;
|
|
16
18
|
static mappableKeys = [...BlockJSONManagingPlugin.mappableNonModuleKeys, ...BlockJSONManagingPlugin.mappableModuleKeys];
|
|
17
19
|
static blockJsonToEntrypointsMap = new Map();
|
|
18
20
|
static blockJsonRawDependenciesMap = new Map();
|
|
19
21
|
static blockJSONAssetSourceDirs = new Map();
|
|
20
22
|
static blockJsonAssetKeyMapping = new Map();
|
|
23
|
+
static blockJsonAssetKeyReadinessMapping = new Map();
|
|
24
|
+
additionalMetadata = new Map();
|
|
21
25
|
constructor(standaloneBlocks, processingModules) {
|
|
22
26
|
this.standaloneBlocks = standaloneBlocks;
|
|
23
27
|
this.processingModules = processingModules;
|
|
@@ -34,171 +38,11 @@ class BlockJSONManagingPlugin {
|
|
|
34
38
|
}
|
|
35
39
|
apply(compiler) {
|
|
36
40
|
compiler.hooks.compilation.tap(this.constructor.name, compilation => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
for (const [name] of currentBlockJSONAssets) {
|
|
43
|
-
const dependencies = BlockJSONManagingPlugin.blockJsonRawDependenciesMap.get(name);
|
|
44
|
-
if (dependencies) {
|
|
45
|
-
for (const dependency of dependencies) {
|
|
46
|
-
const entrypoint = compilation.entrypoints.get(dependency);
|
|
47
|
-
if (!entrypoint) {
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
const srcPath = entrypoint.origins.map(origin => origin.request)[0];
|
|
51
|
-
if (!srcPath) {
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
const destPath = BlockJSONManagingPlugin.resolveDestinationBySourceExtension(srcPath, entrypoint);
|
|
55
|
-
if (!destPath) {
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
const entrypointChunk = entrypoint.getEntrypointChunk();
|
|
59
|
-
const additionalFiles = [];
|
|
60
|
-
for (const entrypointChunkFile of entrypointChunk.files) {
|
|
61
|
-
if (!entrypointChunkFile.endsWith(".asset.php") && entrypointChunkFile !== destPath) {
|
|
62
|
-
additionalFiles.push(entrypointChunkFile);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
const entryMeta = { hash: entrypointChunk.hash ?? destPath, path: destPath };
|
|
66
|
-
const currentEntrypoints = BlockJSONManagingPlugin.blockJsonToEntrypointsMap.get(name);
|
|
67
|
-
if (currentEntrypoints) {
|
|
68
|
-
currentEntrypoints.set(srcPath, [entryMeta, additionalFiles]);
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
BlockJSONManagingPlugin.blockJsonToEntrypointsMap.set(name, new Map([[srcPath, [entryMeta, additionalFiles]]]));
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
//TODO: Fix modules support when running in non-dev mode
|
|
77
|
-
const blockDirConfigData = {};
|
|
78
|
-
for (const [name, sourceDir] of currentBlockJSONAssets) {
|
|
79
|
-
const assetContents = this.processingModules ? node_fs_1.default.readFileSync(testableCompilationAssets[name], 'utf8') : compilation.assets[name]?.buffer().toString();
|
|
80
|
-
if (!assetContents) {
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
const json = JSON.parse(assetContents);
|
|
84
|
-
const currentAssetKeyMappings = { directMappings: {}, referencedFiles: {}, compositeHash: "" };
|
|
85
|
-
for (const mappableKey of BlockJSONManagingPlugin[this.processingModules ? 'mappableModuleKeys' : 'mappableNonModuleKeys']) {
|
|
86
|
-
if (mappableKey in json) {
|
|
87
|
-
const unmappedValue = json[mappableKey];
|
|
88
|
-
if (Array.isArray(unmappedValue)) {
|
|
89
|
-
for (const uv of unmappedValue) {
|
|
90
|
-
BlockJSONManagingPlugin.incorporateRemappedAsset(currentAssetKeyMappings, mappableKey, ...BlockJSONManagingPlugin.remapReferencedAssetFile(uv, name));
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
else if (typeof unmappedValue === 'string') {
|
|
94
|
-
BlockJSONManagingPlugin.incorporateRemappedAsset(currentAssetKeyMappings, mappableKey, ...BlockJSONManagingPlugin.remapReferencedAssetFile(unmappedValue, name));
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
const assetKeyMappings = { ...BlockJSONManagingPlugin.blockJsonAssetKeyMapping.get(name), [this.processingModules ? 'module' : 'nonModule']: currentAssetKeyMappings };
|
|
99
|
-
BlockJSONManagingPlugin.blockJsonAssetKeyMapping.set(name, assetKeyMappings);
|
|
100
|
-
let compositeHash = "";
|
|
101
|
-
const condensedBlockJsonAssetKeyMappings = {};
|
|
102
|
-
for (const subType of ['nonModule', 'module']) {
|
|
103
|
-
const mappings = assetKeyMappings[subType];
|
|
104
|
-
if (mappings) {
|
|
105
|
-
compositeHash += mappings.compositeHash;
|
|
106
|
-
for (const mappableKey of BlockJSONManagingPlugin.mappableKeys) {
|
|
107
|
-
if (mappings.directMappings[mappableKey]) {
|
|
108
|
-
BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, mappableKey, mappings.directMappings[mappableKey]);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
for (const [referenceLocation, prefix] of [["editor", "editorS"], ["both", "s"], ["view", "viewS"]]) {
|
|
112
|
-
if (mappings.referencedFiles[referenceLocation]) {
|
|
113
|
-
for (const referencedFile of mappings.referencedFiles[referenceLocation]) {
|
|
114
|
-
if (referencedFile.endsWith(".css")) {
|
|
115
|
-
BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}tyle`, referencedFile);
|
|
116
|
-
}
|
|
117
|
-
else if (referencedFile.endsWith(".js")) {
|
|
118
|
-
BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}cript`, referencedFile);
|
|
119
|
-
}
|
|
120
|
-
else if (referencedFile.endsWith(".mjs")) {
|
|
121
|
-
BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}criptModule`, referencedFile);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
for (const mappableKey of BlockJSONManagingPlugin.mappableKeys) {
|
|
129
|
-
if (mappableKey in condensedBlockJsonAssetKeyMappings) {
|
|
130
|
-
json[mappableKey] = condensedBlockJsonAssetKeyMappings[mappableKey];
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
delete json[mappableKey];
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (json["version"]) {
|
|
137
|
-
json["version"] = `${json["version"]}-${BlockJSONManagingPlugin.hashThingForAsset(compositeHash)}`;
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
json["version"] = BlockJSONManagingPlugin.hashThingForAsset(compositeHash);
|
|
141
|
-
}
|
|
142
|
-
const outputDir = node_path_1.default.join(compiler.outputPath, node_path_1.default.dirname(name));
|
|
143
|
-
const pathsNeedRemapping = !this.standaloneBlocks && json["plaudit"] !== "simple";
|
|
144
|
-
BlockJSONManagingPlugin.remapReferencedPHPFilesOnKey(json, "setup", pathsNeedRemapping, sourceDir, outputDir, compilation, true);
|
|
145
|
-
BlockJSONManagingPlugin.remapReferencedPHPFilesOnKey(json, "variations", pathsNeedRemapping, sourceDir, outputDir, compilation, false);
|
|
146
|
-
if (json["acf"]) {
|
|
147
|
-
if (json["acf"]["renderTemplate"]) {
|
|
148
|
-
json["render_template"] = json["acf"]["renderTemplate"];
|
|
149
|
-
delete json["acf"]["renderTemplate"];
|
|
150
|
-
}
|
|
151
|
-
else if (json["acf"]["render_template"]) {
|
|
152
|
-
json["render_template"] = json["acf"]["render_template"];
|
|
153
|
-
delete json["acf"]["render_template"];
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
const blockName = json["name"]?.toString() || "non-existent/block-name";
|
|
157
|
-
let rawRenderTemplate = json["render"] ?? json["render_template"];
|
|
158
|
-
rawRenderTemplate = (rawRenderTemplate
|
|
159
|
-
? (typeof rawRenderTemplate === 'string' ? [rawRenderTemplate] : rawRenderTemplate)
|
|
160
|
-
: [`${blockName.substring(blockName.indexOf('/') + 1)}.php`, "template.php", "template.twig"]);
|
|
161
|
-
const renderTemplate = pathsNeedRemapping
|
|
162
|
-
? rawRenderTemplate
|
|
163
|
-
.map(p => node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p))))
|
|
164
|
-
.filter(p => node_fs_1.default.existsSync(p))
|
|
165
|
-
.map(p => `file:./${BlockJSONManagingPlugin.findRelativeRouteBetween(outputDir, p)}`)
|
|
166
|
-
: rawRenderTemplate
|
|
167
|
-
.filter(p => node_fs_1.default.existsSync(node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p)))));
|
|
168
|
-
if (renderTemplate.length === 0) {
|
|
169
|
-
delete json["render_template"];
|
|
170
|
-
delete json["render"];
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
let validTemplateLocation, invalidTemplateLocation;
|
|
174
|
-
if (json["acf"] || (json["plaudit"] && (json["plaudit"] !== "native" && (typeof json["plaudit"] !== 'object' || json["plaudit"]?.["type"] !== "native")))) {
|
|
175
|
-
// ACF-like blocks need to have the template stored in render_template.
|
|
176
|
-
// Because we can statically detect ACF-like blocks, we can make the move here instead of at run-time.
|
|
177
|
-
validTemplateLocation = "render_template";
|
|
178
|
-
invalidTemplateLocation = "render";
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
validTemplateLocation = "render";
|
|
182
|
-
invalidTemplateLocation = "render_template";
|
|
183
|
-
}
|
|
184
|
-
delete json[invalidTemplateLocation];
|
|
185
|
-
if (renderTemplate.length > 1) {
|
|
186
|
-
const error = new webpack_1.WebpackError("Encountered a block with multiple possible render files");
|
|
187
|
-
error.file = node_path_1.default.join(sourceDir, 'block.json');
|
|
188
|
-
compilation.warnings.push(error);
|
|
189
|
-
json[validTemplateLocation] = renderTemplate.find(p => p.endsWith(".php")) ?? renderTemplate[0];
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
json[validTemplateLocation] = renderTemplate[0];
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
compilation[name in compilation.assets ? 'updateAsset' : 'emitAsset'](name, new webpack_1.sources.RawSource(JSON.stringify(json, undefined, " ")));
|
|
196
|
-
blockDirConfigData[node_path_1.default.dirname(name)] = json;
|
|
197
|
-
}
|
|
198
|
-
const sortedBlockDirConfigData = Object.fromEntries([["__metadata", { version: 1 }], ...Object.entries(blockDirConfigData)
|
|
199
|
-
.sort(([a], [b]) => a.localeCompare(b))]);
|
|
200
|
-
compilation.emitAsset("blockdir.config", new webpack_1.sources.RawSource((0, php_serializer_1.default)(sortedBlockDirConfigData, { excludedKeys: ["$schema"] })));
|
|
201
|
-
});
|
|
41
|
+
this.additionalMetadata.clear();
|
|
42
|
+
this.registerAssetProcessor(compilation);
|
|
43
|
+
if (!this.processingModules) {
|
|
44
|
+
this.registerBlockJsonProcessor(compilation);
|
|
45
|
+
}
|
|
202
46
|
});
|
|
203
47
|
}
|
|
204
48
|
static resolveDestinationBySourceExtension(srcPath, entrypoint) {
|
|
@@ -331,7 +175,15 @@ class BlockJSONManagingPlugin {
|
|
|
331
175
|
const prefix = value.startsWith("./", 5) ? "./" : "";
|
|
332
176
|
const relativePath = node_path_1.default.relative(node_path_1.default.dirname(name), output.path);
|
|
333
177
|
const res = [`file:${prefix}${relativePath}`, output.hash];
|
|
334
|
-
|
|
178
|
+
if (BlockJSONManagingPlugin.styleExtensionPattern.test(output.path)) {
|
|
179
|
+
return [res,
|
|
180
|
+
additionalFiles.filter(additionalFile => !BlockJSONManagingPlugin.scriptExtensionPattern.test(additionalFile))
|
|
181
|
+
.map(additionalFile => `file:./${node_path_1.default.relative(node_path_1.default.dirname(name), additionalFile)}`)
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
return [res, additionalFiles.map(additionalFile => `file:./${node_path_1.default.relative(node_path_1.default.dirname(name), additionalFile)}`)];
|
|
186
|
+
}
|
|
335
187
|
}
|
|
336
188
|
}
|
|
337
189
|
return [[value, ""], []];
|
|
@@ -373,5 +225,279 @@ class BlockJSONManagingPlugin {
|
|
|
373
225
|
}
|
|
374
226
|
}
|
|
375
227
|
}
|
|
228
|
+
registerAssetProcessor(compilation) {
|
|
229
|
+
const tapName = { name: `${this.constructor.name}_ProcessBlockJSONFiles`, stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_DERIVED };
|
|
230
|
+
compilation.hooks.processAssets.tapPromise(tapName, async (compilationAssets) => {
|
|
231
|
+
const testableCompilationAssets = this.processingModules ? BlockJSONManagingPlugin.buildFakeCompilationAssets(compilation) : compilationAssets;
|
|
232
|
+
const currentBlockJSONAssets = BlockJSONManagingPlugin.blockJSONAssetSourceDirs.entries()
|
|
233
|
+
.filter(([name]) => name in testableCompilationAssets)
|
|
234
|
+
.toArray();
|
|
235
|
+
BlockJSONManagingPlugin.populateEntrypointsMap(currentBlockJSONAssets, compilation);
|
|
236
|
+
await Promise.all(currentBlockJSONAssets.map(async ([name]) => {
|
|
237
|
+
const assetContents = this.processingModules ? node_fs_1.default.readFileSync(testableCompilationAssets[name], 'utf8') : compilation.assets[name]?.buffer().toString();
|
|
238
|
+
if (!assetContents) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const json = JSON.parse(assetContents);
|
|
242
|
+
const currentAssetKeyMappings = { directMappings: {}, referencedFiles: {}, compositeHash: "" };
|
|
243
|
+
for (const mappableKey of BlockJSONManagingPlugin[this.processingModules ? 'mappableModuleKeys' : 'mappableNonModuleKeys']) {
|
|
244
|
+
if (mappableKey in json) {
|
|
245
|
+
const unmappedValue = json[mappableKey];
|
|
246
|
+
if (Array.isArray(unmappedValue)) {
|
|
247
|
+
for (const uv of unmappedValue) {
|
|
248
|
+
BlockJSONManagingPlugin.incorporateRemappedAsset(currentAssetKeyMappings, mappableKey, ...BlockJSONManagingPlugin.remapReferencedAssetFile(uv, name));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else if (typeof unmappedValue === 'string') {
|
|
252
|
+
BlockJSONManagingPlugin.incorporateRemappedAsset(currentAssetKeyMappings, mappableKey, ...BlockJSONManagingPlugin.remapReferencedAssetFile(unmappedValue, name));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const syncs = BlockJSONManagingPlugin.getSyncs(name);
|
|
257
|
+
let assetKeyMappings = BlockJSONManagingPlugin.blockJsonAssetKeyMapping.get(name);
|
|
258
|
+
if (!assetKeyMappings) {
|
|
259
|
+
BlockJSONManagingPlugin.blockJsonAssetKeyMapping.set(name, assetKeyMappings = {});
|
|
260
|
+
}
|
|
261
|
+
assetKeyMappings[this.processingModules ? 'module' : 'nonModule'] = currentAssetKeyMappings;
|
|
262
|
+
if (this.processingModules) {
|
|
263
|
+
syncs.module.resolve();
|
|
264
|
+
if (!BlockJSONManagingPlugin.mappableNonModuleKeys.some(key => key in json)) {
|
|
265
|
+
syncs.nonModule.resolve();
|
|
266
|
+
}
|
|
267
|
+
await syncs.nonModule.sync;
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
syncs.nonModule.resolve();
|
|
271
|
+
if (!BlockJSONManagingPlugin.mappableModuleKeys.some(key => key in json)) {
|
|
272
|
+
syncs.module.resolve();
|
|
273
|
+
}
|
|
274
|
+
await syncs.module.sync;
|
|
275
|
+
}
|
|
276
|
+
}));
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
static populateEntrypointsMap(currentBlockJSONAssets, compilation) {
|
|
280
|
+
for (const [name] of currentBlockJSONAssets) {
|
|
281
|
+
const dependencies = BlockJSONManagingPlugin.blockJsonRawDependenciesMap.get(name);
|
|
282
|
+
if (dependencies) {
|
|
283
|
+
for (const dependency of dependencies) {
|
|
284
|
+
const entrypoint = compilation.entrypoints.get(dependency);
|
|
285
|
+
if (!entrypoint) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const srcPath = entrypoint.origins.map(origin => origin.request)[0];
|
|
289
|
+
if (!srcPath) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
const destPath = BlockJSONManagingPlugin.resolveDestinationBySourceExtension(srcPath, entrypoint);
|
|
293
|
+
if (!destPath) {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
const entrypointChunk = entrypoint.getEntrypointChunk();
|
|
297
|
+
const additionalFiles = [];
|
|
298
|
+
for (const entrypointChunkFile of entrypointChunk.files) {
|
|
299
|
+
if (!entrypointChunkFile.endsWith(".asset.php") && entrypointChunkFile !== destPath) {
|
|
300
|
+
additionalFiles.push(entrypointChunkFile);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const entryMeta = { hash: entrypointChunk.hash ?? destPath, path: destPath };
|
|
304
|
+
const currentEntrypoints = BlockJSONManagingPlugin.blockJsonToEntrypointsMap.get(name);
|
|
305
|
+
if (currentEntrypoints) {
|
|
306
|
+
currentEntrypoints.set(srcPath, [entryMeta, additionalFiles]);
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
BlockJSONManagingPlugin.blockJsonToEntrypointsMap.set(name, new Map([[srcPath, [entryMeta, additionalFiles]]]));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
registerBlockJsonProcessor(compilation) {
|
|
316
|
+
const blockDirConfigData = {};
|
|
317
|
+
compilation.hooks.afterProcessAssets.tap(`${this.constructor.name}_GenerateMetadata`, compilationAssets => {
|
|
318
|
+
const currentBlockJSONAssets = BlockJSONManagingPlugin.blockJSONAssetSourceDirs.entries()
|
|
319
|
+
.filter(([name]) => name in compilationAssets)
|
|
320
|
+
.toArray();
|
|
321
|
+
for (const [name, sourceDir] of currentBlockJSONAssets) {
|
|
322
|
+
const assetKeyMappings = BlockJSONManagingPlugin.blockJsonAssetKeyMapping.get(name);
|
|
323
|
+
let compositeHash = "";
|
|
324
|
+
const condensedBlockJsonAssetKeyMappings = {};
|
|
325
|
+
for (const subType of ['nonModule', 'module']) {
|
|
326
|
+
const mappings = assetKeyMappings[subType];
|
|
327
|
+
if (mappings) {
|
|
328
|
+
compositeHash += mappings.compositeHash;
|
|
329
|
+
for (const mappableKey of BlockJSONManagingPlugin.mappableKeys) {
|
|
330
|
+
if (mappings.directMappings[mappableKey]) {
|
|
331
|
+
BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, mappableKey, mappings.directMappings[mappableKey]);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
for (const [referenceLocation, prefix] of [["editor", "editorS"], ["both", "s"], ["view", "viewS"]]) {
|
|
335
|
+
if (mappings.referencedFiles[referenceLocation]) {
|
|
336
|
+
for (const referencedFile of mappings.referencedFiles[referenceLocation]) {
|
|
337
|
+
if (referencedFile.endsWith(".css")) {
|
|
338
|
+
BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}tyle`, referencedFile);
|
|
339
|
+
}
|
|
340
|
+
else if (referencedFile.endsWith(".js")) {
|
|
341
|
+
BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}cript`, referencedFile);
|
|
342
|
+
}
|
|
343
|
+
else if (referencedFile.endsWith(".mjs")) {
|
|
344
|
+
BlockJSONManagingPlugin.addAssetToBlockJsonKey(condensedBlockJsonAssetKeyMappings, `${prefix}criptModule`, referencedFile);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
const assetContents = compilation.assets[name]?.buffer().toString();
|
|
352
|
+
if (!assetContents) {
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
const json = JSON.parse(assetContents);
|
|
356
|
+
for (const mappableKey of BlockJSONManagingPlugin.mappableKeys) {
|
|
357
|
+
if (mappableKey in condensedBlockJsonAssetKeyMappings) {
|
|
358
|
+
json[mappableKey] = condensedBlockJsonAssetKeyMappings[mappableKey];
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
delete json[mappableKey];
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (json["version"]) {
|
|
365
|
+
json["version"] = `${json["version"]}-${BlockJSONManagingPlugin.hashThingForAsset(compositeHash)}`;
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
json["version"] = BlockJSONManagingPlugin.hashThingForAsset(compositeHash);
|
|
369
|
+
}
|
|
370
|
+
const outputDir = node_path_1.default.join(compilation.compiler.outputPath, node_path_1.default.dirname(name));
|
|
371
|
+
const pathsNeedRemapping = !this.standaloneBlocks && json["plaudit"] !== "simple";
|
|
372
|
+
BlockJSONManagingPlugin.remapReferencedPHPFilesOnKey(json, "setup", pathsNeedRemapping, sourceDir, outputDir, compilation, true);
|
|
373
|
+
BlockJSONManagingPlugin.remapReferencedPHPFilesOnKey(json, "variations", pathsNeedRemapping, sourceDir, outputDir, compilation, false);
|
|
374
|
+
BlockJSONManagingPlugin.normalizeRenderTemplate(json, pathsNeedRemapping, sourceDir, outputDir, compilation);
|
|
375
|
+
compilation[name in compilation.assets ? 'updateAsset' : 'emitAsset'](name, new webpack_1.sources.RawSource(JSON.stringify(json, undefined, " ")));
|
|
376
|
+
blockDirConfigData[node_path_1.default.dirname(name)] = json;
|
|
377
|
+
}
|
|
378
|
+
let sortedBlockDirConfigData;
|
|
379
|
+
const blockDirConfigs = Object.entries(blockDirConfigData).sort(([a], [b]) => a.localeCompare(b));
|
|
380
|
+
const rawAssetDataSource = compilation.assets["assets.json"]?.source();
|
|
381
|
+
if (typeof rawAssetDataSource === 'string') {
|
|
382
|
+
const scriptHandles = {};
|
|
383
|
+
const styleHandles = {};
|
|
384
|
+
const rawAssetData = JSON.parse(rawAssetDataSource);
|
|
385
|
+
const mappableKeys = [...BlockJSONManagingPlugin.mappableModuleKeys, ...BlockJSONManagingPlugin.mappableNonModuleKeys];
|
|
386
|
+
for (const [blockFolder, config] of blockDirConfigs) {
|
|
387
|
+
for (const mappableKey of mappableKeys) {
|
|
388
|
+
const cfg = config[mappableKey];
|
|
389
|
+
if (cfg) {
|
|
390
|
+
if (Array.isArray(cfg)) {
|
|
391
|
+
for (let i = 0; i < cfg.length; i++) {
|
|
392
|
+
const assetDetails = getAssetDetails(blockFolder, cfg[i], rawAssetData);
|
|
393
|
+
if (assetDetails) {
|
|
394
|
+
(assetDetails[0] ? styleHandles : scriptHandles)[assetDetails[1]] = assetDetails[2];
|
|
395
|
+
cfg[i] = assetDetails[1];
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
const assetDetails = getAssetDetails(blockFolder, cfg, rawAssetData);
|
|
401
|
+
if (assetDetails) {
|
|
402
|
+
(assetDetails[0] ? styleHandles : scriptHandles)[assetDetails[1]] = assetDetails[2];
|
|
403
|
+
config[mappableKey] = assetDetails[1];
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
sortedBlockDirConfigData = Object.fromEntries([
|
|
410
|
+
["__metadata", { version: 2, ...Object.fromEntries(this.additionalMetadata.entries()), scriptHandles, styleHandles }],
|
|
411
|
+
...blockDirConfigs
|
|
412
|
+
]);
|
|
413
|
+
compilation.deleteAsset("assets.json");
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
sortedBlockDirConfigData = Object.fromEntries([["__metadata", { version: 1, ...Object.fromEntries(this.additionalMetadata.entries()) }], ...blockDirConfigs]);
|
|
417
|
+
}
|
|
418
|
+
compilation.emitAsset("blockdir.config", new webpack_1.sources.RawSource((0, php_serializer_1.default)(sortedBlockDirConfigData, { excludedKeys: ["$schema"] })));
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
static normalizeRenderTemplate(json, pathsNeedRemapping, sourceDir, outputDir, compilation) {
|
|
422
|
+
if (json["acf"]) {
|
|
423
|
+
if (json["acf"]["renderTemplate"]) {
|
|
424
|
+
json["render_template"] = json["acf"]["renderTemplate"];
|
|
425
|
+
delete json["acf"]["renderTemplate"];
|
|
426
|
+
}
|
|
427
|
+
else if (json["acf"]["render_template"]) {
|
|
428
|
+
json["render_template"] = json["acf"]["render_template"];
|
|
429
|
+
delete json["acf"]["render_template"];
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
const blockName = json["name"]?.toString() || "non-existent/block-name";
|
|
433
|
+
let rawRenderTemplate = json["render"] ?? json["render_template"];
|
|
434
|
+
rawRenderTemplate = (rawRenderTemplate
|
|
435
|
+
? (typeof rawRenderTemplate === 'string' ? [rawRenderTemplate] : rawRenderTemplate)
|
|
436
|
+
: [`${blockName.substring(blockName.indexOf('/') + 1)}.php`, "template.php", "template.twig"]);
|
|
437
|
+
const renderTemplate = pathsNeedRemapping
|
|
438
|
+
? rawRenderTemplate
|
|
439
|
+
.map(p => node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p))))
|
|
440
|
+
.filter(p => node_fs_1.default.existsSync(p))
|
|
441
|
+
.map(p => `file:./${BlockJSONManagingPlugin.findRelativeRouteBetween(outputDir, p)}`)
|
|
442
|
+
: rawRenderTemplate
|
|
443
|
+
.filter(p => node_fs_1.default.existsSync(node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p)))));
|
|
444
|
+
if (renderTemplate.length === 0) {
|
|
445
|
+
delete json["render_template"];
|
|
446
|
+
delete json["render"];
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
let validTemplateLocation, invalidTemplateLocation;
|
|
450
|
+
if (json["acf"] || (json["plaudit"] && (json["plaudit"] !== "native" && (typeof json["plaudit"] !== 'object' || json["plaudit"]?.["type"] !== "native")))) {
|
|
451
|
+
// ACF-like blocks need to have the template stored in render_template.
|
|
452
|
+
// Because we can statically detect ACF-like blocks, we can make the move here instead of at run-time.
|
|
453
|
+
validTemplateLocation = "render_template";
|
|
454
|
+
invalidTemplateLocation = "render";
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
validTemplateLocation = "render";
|
|
458
|
+
invalidTemplateLocation = "render_template";
|
|
459
|
+
}
|
|
460
|
+
delete json[invalidTemplateLocation];
|
|
461
|
+
if (renderTemplate.length > 1) {
|
|
462
|
+
const error = new webpack_1.WebpackError("Encountered a block with multiple possible render files");
|
|
463
|
+
error.file = node_path_1.default.join(sourceDir, 'block.json');
|
|
464
|
+
compilation.warnings.push(error);
|
|
465
|
+
json[validTemplateLocation] = renderTemplate.find(p => p.endsWith(".php")) ?? renderTemplate[0];
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
json[validTemplateLocation] = renderTemplate[0];
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
static getSyncs(name) {
|
|
473
|
+
const res = BlockJSONManagingPlugin.blockJsonAssetKeyReadinessMapping.get(name);
|
|
474
|
+
if (res) {
|
|
475
|
+
return res;
|
|
476
|
+
}
|
|
477
|
+
BlockJSONManagingPlugin.blockJsonAssetKeyReadinessMapping.set(name, { nonModule: makeSync(), module: makeSync() });
|
|
478
|
+
return BlockJSONManagingPlugin.blockJsonAssetKeyReadinessMapping.get(name);
|
|
479
|
+
}
|
|
376
480
|
}
|
|
377
481
|
exports.default = BlockJSONManagingPlugin;
|
|
482
|
+
function makeSync() {
|
|
483
|
+
const res = { done: false };
|
|
484
|
+
res.sync = new Promise((resolve, reject) => {
|
|
485
|
+
res.resolve = (v) => resolve(v);
|
|
486
|
+
res.reject = () => reject();
|
|
487
|
+
});
|
|
488
|
+
return res;
|
|
489
|
+
}
|
|
490
|
+
function getAssetDetails(blockFolder, asset, rawAssetData) {
|
|
491
|
+
if (!asset.startsWith("file:./")) {
|
|
492
|
+
return undefined;
|
|
493
|
+
}
|
|
494
|
+
const src = `${blockFolder}/${asset.substring(7)}`;
|
|
495
|
+
const isCss = src.endsWith(".css");
|
|
496
|
+
const assetData = isCss
|
|
497
|
+
? rawAssetData[src.substring(0, src.length - 3) + "js"] ?? rawAssetData[src.substring(0, src.length - 3).replace("style-style", "style") + "js"]
|
|
498
|
+
: rawAssetData[src];
|
|
499
|
+
if (!assetData) {
|
|
500
|
+
return undefined;
|
|
501
|
+
}
|
|
502
|
+
return [isCss, src.substring(0, src.length - (isCss ? 4 : 3)), { src, rest: [assetData.dependencies, assetData.version] }];
|
|
503
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Compiler, type WebpackPluginInstance } from "webpack";
|
|
2
|
+
import BlockJSONManagingPlugin from "./BlockJSONManagingPlugin";
|
|
3
|
+
export default class WPMLConfigBuilder implements WebpackPluginInstance {
|
|
4
|
+
private readonly blockJSONManagingPlugin;
|
|
5
|
+
private static jsdomInstance?;
|
|
6
|
+
private static domParser?;
|
|
7
|
+
private static xmlSerializer?;
|
|
8
|
+
private readonly parsedDocumentsCache;
|
|
9
|
+
constructor(blockJSONManagingPlugin: BlockJSONManagingPlugin);
|
|
10
|
+
apply(compiler: Compiler): void;
|
|
11
|
+
private static getJSDOMInstance;
|
|
12
|
+
private static getDOMParser;
|
|
13
|
+
private static getXMLSerializer;
|
|
14
|
+
private static prettyPrintXML;
|
|
15
|
+
private loadWPMLConfigXML;
|
|
16
|
+
}
|