@plaudit/webpack-extensions 2.27.0 → 2.29.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/BlockJSONManagingPlugin.d.ts +5 -4
- package/build/wordpress-scripts-wrapper/BlockJSONManagingPlugin.js +169 -176
- package/build/wordpress-scripts-wrapper/ExtensionsConfigFileGeneratorPlugin.js +3 -3
- package/build/wordpress-scripts-wrapper.d.ts +6 -0
- package/build/wordpress-scripts-wrapper.js +74 -10
- package/package.json +2 -2
|
@@ -3,11 +3,12 @@ export default class BlockJSONManagingPlugin implements WebpackPluginInstance {
|
|
|
3
3
|
private readonly standaloneBlocks;
|
|
4
4
|
private readonly processingModules;
|
|
5
5
|
private static readonly sourceToOutputMapping;
|
|
6
|
-
private static readonly
|
|
6
|
+
private static readonly blockJsonToEntrypointsMap;
|
|
7
|
+
private static readonly blockJSONAssetSources;
|
|
7
8
|
constructor(standaloneBlocks: boolean, processingModules: boolean);
|
|
8
9
|
apply(compiler: Compiler): void;
|
|
9
|
-
findCommonAncestor(...paths: string[]): string[];
|
|
10
|
-
findRelativeRouteBetween(path1: string, path2: string): string;
|
|
10
|
+
static findCommonAncestor(...paths: string[]): string[];
|
|
11
|
+
static findRelativeRouteBetween(path1: string, path2: string): string;
|
|
11
12
|
private static hashThingForAsset;
|
|
12
|
-
private static
|
|
13
|
+
private static stripFilePrefix;
|
|
13
14
|
}
|
|
@@ -12,186 +12,205 @@ class BlockJSONManagingPlugin {
|
|
|
12
12
|
standaloneBlocks;
|
|
13
13
|
processingModules;
|
|
14
14
|
static sourceToOutputMapping = new Map();
|
|
15
|
-
static
|
|
15
|
+
static blockJsonToEntrypointsMap = new Map();
|
|
16
|
+
static blockJSONAssetSources = new Map();
|
|
16
17
|
constructor(standaloneBlocks, processingModules) {
|
|
17
18
|
this.standaloneBlocks = standaloneBlocks;
|
|
18
19
|
this.processingModules = processingModules;
|
|
19
20
|
}
|
|
20
21
|
apply(compiler) {
|
|
21
|
-
compiler.hooks.compilation.tap(
|
|
22
|
-
compilation.hooks.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
publicPath: true,
|
|
30
|
-
assets: true,
|
|
31
|
-
moduleAssets: true,
|
|
32
|
-
chunks: true,
|
|
33
|
-
modules: true,
|
|
34
|
-
source: true,
|
|
35
|
-
errorDetails: false,
|
|
36
|
-
timings: false
|
|
37
|
-
});
|
|
38
|
-
if (!stats.assets) {
|
|
39
|
-
throw new Error("Stats did not include assets despite them being requested");
|
|
22
|
+
compiler.hooks.compilation.tap(this.constructor.name, compilation => {
|
|
23
|
+
compilation.hooks.processAssets.tap({ name: this.constructor.name, stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ANALYSE }, () => {
|
|
24
|
+
for (const blockEntrypoint of compilation.entrypoints.values()) {
|
|
25
|
+
if (blockEntrypoint.name?.endsWith("/block.json")) {
|
|
26
|
+
const source = blockEntrypoint.origins.map(origin => origin.request)[0];
|
|
27
|
+
const name = blockEntrypoint.getEntrypointChunk().name;
|
|
28
|
+
if (!source || !name) {
|
|
29
|
+
continue;
|
|
40
30
|
}
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
BlockJSONManagingPlugin.blockJSONAssetSources.set(name, source);
|
|
32
|
+
const dependencies = blockEntrypoint.getEntrypointChunk().getEntryOptions()?.dependOn;
|
|
33
|
+
if (dependencies) {
|
|
34
|
+
for (const dependency of dependencies) {
|
|
35
|
+
const entrypoint = compilation.entrypoints.get(dependency);
|
|
36
|
+
if (!entrypoint) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const srcPath = entrypoint.origins.map(origin => origin.request)[0];
|
|
40
|
+
if (!srcPath) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const destPath = /m?[jt]sx?$/i.test(node_path_1.default.extname(srcPath))
|
|
44
|
+
? entrypoint.getFiles().find(file => file.endsWith(".mjs")) ?? entrypoint.getFiles().find(file => file.endsWith(".js"))
|
|
45
|
+
: entrypoint.getFiles().find(file => file.endsWith(".css"));
|
|
46
|
+
if (!destPath) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const entryMeta = { hash: entrypoint.getEntrypointChunk().hash ?? destPath, path: destPath };
|
|
50
|
+
const currentEntrypoints = BlockJSONManagingPlugin.blockJsonToEntrypointsMap.get(name);
|
|
51
|
+
if (currentEntrypoints) {
|
|
52
|
+
currentEntrypoints.set(srcPath, entryMeta);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
BlockJSONManagingPlugin.blockJsonToEntrypointsMap.set(name, new Map([[srcPath, entryMeta]]));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
43
58
|
}
|
|
44
|
-
singleFileInputToOutputNameAndHashCache = BlockJSONManagingPlugin.resolveFilesFromStats(compilationAssets, stats);
|
|
45
|
-
assetSourceFilesCache = new Map(stats.assets
|
|
46
|
-
.map(asset => [asset.name, asset.info?.sourceFilename])
|
|
47
|
-
.filter((v) => v[0] !== undefined && v[1] !== undefined));
|
|
48
59
|
}
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
compilation.hooks.afterProcessAssets.tap(`${this.constructor.name}_ProcessBlockJSONFiles`, compilationAssets => {
|
|
63
|
+
// We start by trimming away the unused metadata files that WebPack creates.
|
|
64
|
+
for (const name of Object.keys(compilationAssets)) {
|
|
65
|
+
if (name.endsWith("block.json.asset.php")) {
|
|
66
|
+
compilation.deleteAsset(name);
|
|
67
|
+
compilation.deleteAsset(name.substring(0, name.length - 10) + ".js"); // This removes the block.json.js and block.json.js.map files
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (this.processingModules) {
|
|
71
|
+
// We perform the processing in the non-modules half ONLY because we don't necessarily have all the information we need during the modules half.
|
|
72
|
+
for (const name of BlockJSONManagingPlugin.blockJSONAssetSources.keys()) {
|
|
73
|
+
compilation.deleteAsset(name); // While the method is called, "deleteAsset", it doesn't actually delete it - just halts emission.
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const blockDirConfigData = {};
|
|
78
|
+
const mappableKeys = ["editorStyle", "style", "viewStyle", "viewScript", "script", "editorScript", "viewScriptModule", "scriptModule"];
|
|
51
79
|
const remapValue = (value, name) => {
|
|
52
80
|
if (value.startsWith("file:")) {
|
|
53
81
|
let res = BlockJSONManagingPlugin.sourceToOutputMapping.get(`${name};${value}`);
|
|
54
82
|
if (res !== undefined) {
|
|
55
83
|
return res;
|
|
56
84
|
}
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
if (styleOutputPath !== undefined) {
|
|
85
|
+
const sourceDir = node_path_1.default.dirname(BlockJSONManagingPlugin.blockJSONAssetSources.get(name) ?? name);
|
|
86
|
+
const inputPath = node_path_1.default.normalize(node_path_1.default.join(sourceDir, value.substring(5)));
|
|
87
|
+
const output = BlockJSONManagingPlugin.blockJsonToEntrypointsMap.get(name)?.get(inputPath);
|
|
88
|
+
if (output !== undefined) {
|
|
62
89
|
const prefix = value.startsWith("./", 5) ? "./" : "";
|
|
63
|
-
const relativePath = node_path_1.default.relative(node_path_1.default.dirname(name),
|
|
64
|
-
const res = [`file:${prefix}${relativePath}`,
|
|
90
|
+
const relativePath = node_path_1.default.relative(node_path_1.default.dirname(name), output.path);
|
|
91
|
+
const res = [`file:${prefix}${relativePath}`, output.hash];
|
|
65
92
|
BlockJSONManagingPlugin.sourceToOutputMapping.set(`${name};${value}`, res);
|
|
66
93
|
return res;
|
|
67
94
|
}
|
|
68
95
|
}
|
|
69
96
|
return [value, ""];
|
|
70
97
|
};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
98
|
+
for (const [name, source] of BlockJSONManagingPlugin.blockJSONAssetSources.entries()) {
|
|
99
|
+
const sourceDir = node_path_1.default.dirname(source);
|
|
100
|
+
const asset = compilation.assets[name]?.buffer().toString();
|
|
101
|
+
if (!asset) {
|
|
102
|
+
continue;
|
|
74
103
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (mappableKey in json) {
|
|
86
|
-
const unmappedValue = json[mappableKey];
|
|
87
|
-
if (Array.isArray(unmappedValue)) {
|
|
88
|
-
const remappedValue = unmappedValue.map(value => remapValue(value, name));
|
|
89
|
-
json[mappableKey] = remappedValue.map(([resource]) => resource);
|
|
90
|
-
compositeHash += "~" + remappedValue.map(([_, hash]) => hash).join("~");
|
|
91
|
-
}
|
|
92
|
-
else if (typeof unmappedValue === 'string') {
|
|
93
|
-
const remappedValue = remapValue(unmappedValue, name);
|
|
94
|
-
json[mappableKey] = remappedValue[0];
|
|
95
|
-
compositeHash += "~" + remappedValue[1];
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if (json["version"]) {
|
|
100
|
-
json["version"] = `${json["version"]}-${BlockJSONManagingPlugin.hashThingForAsset(compositeHash)}`;
|
|
104
|
+
blockDirConfigData[name] = true;
|
|
105
|
+
const json = JSON.parse(asset);
|
|
106
|
+
let compositeHash = "";
|
|
107
|
+
for (const mappableKey of mappableKeys) {
|
|
108
|
+
if (mappableKey in json) {
|
|
109
|
+
const unmappedValue = json[mappableKey];
|
|
110
|
+
if (Array.isArray(unmappedValue)) {
|
|
111
|
+
const remappedValue = unmappedValue.map(value => remapValue(value, name));
|
|
112
|
+
json[mappableKey] = remappedValue.map(([resource]) => resource);
|
|
113
|
+
compositeHash += "~" + remappedValue.map(([_, hash]) => hash).join("~");
|
|
101
114
|
}
|
|
102
|
-
else {
|
|
103
|
-
|
|
115
|
+
else if (typeof unmappedValue === 'string') {
|
|
116
|
+
const remappedValue = remapValue(unmappedValue, name);
|
|
117
|
+
json[mappableKey] = remappedValue[0];
|
|
118
|
+
compositeHash += "~" + remappedValue[1];
|
|
104
119
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
json["plaudit"]["setup"] = setupFiles.length === 1 ? setupFiles[0] : setupFiles;
|
|
135
|
-
}
|
|
136
|
-
if (json["acf"]) {
|
|
137
|
-
if (json["acf"]["renderTemplate"]) {
|
|
138
|
-
json["render_template"] = json["acf"]["renderTemplate"];
|
|
139
|
-
delete json["acf"]["renderTemplate"];
|
|
140
|
-
}
|
|
141
|
-
else if (json["acf"]["render_template"]) {
|
|
142
|
-
json["render_template"] = json["acf"]["render_template"];
|
|
143
|
-
delete json["acf"]["render_template"];
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
const blockName = json["name"]?.toString() || "non-existent/block-name";
|
|
147
|
-
let rawRenderTemplate = json["render"] ?? json["render_template"];
|
|
148
|
-
rawRenderTemplate = (rawRenderTemplate
|
|
149
|
-
? (typeof rawRenderTemplate === 'string' ? [rawRenderTemplate] : rawRenderTemplate)
|
|
150
|
-
: [`${blockName.substring(blockName.indexOf('/') + 1)}.php`, "template.php", "template.twig"]);
|
|
151
|
-
const renderTemplate = pathsNeedRemapping
|
|
152
|
-
? rawRenderTemplate
|
|
153
|
-
.map(p => node_path_1.default.normalize(node_path_1.default.join(sourceDir, stripFilePrefix(p))))
|
|
154
|
-
.filter(p => node_fs_1.default.existsSync(p))
|
|
155
|
-
.map(p => `file:./${this.findRelativeRouteBetween(outputDir, p)}`)
|
|
156
|
-
: rawRenderTemplate
|
|
157
|
-
.filter(p => node_fs_1.default.existsSync(node_path_1.default.normalize(node_path_1.default.join(sourceDir, stripFilePrefix(p)))));
|
|
158
|
-
if (renderTemplate.length === 0) {
|
|
159
|
-
delete json["render_template"];
|
|
160
|
-
delete json["render"];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (json["version"]) {
|
|
123
|
+
json["version"] = `${json["version"]}-${BlockJSONManagingPlugin.hashThingForAsset(compositeHash)}`;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
json["version"] = BlockJSONManagingPlugin.hashThingForAsset(compositeHash);
|
|
127
|
+
}
|
|
128
|
+
const outputDir = node_path_1.default.join(compiler.outputPath, node_path_1.default.dirname(name));
|
|
129
|
+
const pathsNeedRemapping = !this.standaloneBlocks && json["plaudit"] !== "simple";
|
|
130
|
+
const rawSetupFiles = json["plaudit"]?.["setup"]
|
|
131
|
+
? (typeof json["plaudit"]["setup"] === 'string' ? [json["plaudit"]["setup"]] : json["plaudit"]["setup"])
|
|
132
|
+
: ["setup.php"];
|
|
133
|
+
const setupFiles = pathsNeedRemapping
|
|
134
|
+
? rawSetupFiles
|
|
135
|
+
.map(p => node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p))))
|
|
136
|
+
.filter(p => node_fs_1.default.existsSync(p))
|
|
137
|
+
.map(p => `file:./${BlockJSONManagingPlugin.findRelativeRouteBetween(outputDir, p)}`)
|
|
138
|
+
: rawSetupFiles
|
|
139
|
+
.filter(p => node_fs_1.default.existsSync(node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p)))));
|
|
140
|
+
if (setupFiles.length === 0) {
|
|
141
|
+
if (json["plaudit"]?.["setup"] !== undefined) {
|
|
142
|
+
delete json["plaudit"]["setup"];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
if (typeof json["plaudit"] !== 'object') {
|
|
147
|
+
if (json["plaudit"] === "native") {
|
|
148
|
+
json["plaudit"] = { type: "native" };
|
|
161
149
|
}
|
|
162
150
|
else {
|
|
163
|
-
|
|
164
|
-
if (json["acf"] || (json["plaudit"] && (json["plaudit"] !== "native" && (typeof json["plaudit"] !== 'object' || json["plaudit"]?.["type"] !== "native")))) {
|
|
165
|
-
// ACF-like blocks need to have the template stored in render_template.
|
|
166
|
-
// Because we can statically detect ACF-like blocks, we can make the move here instead of at run-time.
|
|
167
|
-
validTemplateLocation = "render_template";
|
|
168
|
-
invalidTemplateLocation = "render";
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
validTemplateLocation = "render";
|
|
172
|
-
invalidTemplateLocation = "render_template";
|
|
173
|
-
}
|
|
174
|
-
delete json[invalidTemplateLocation];
|
|
175
|
-
if (renderTemplate.length > 1) {
|
|
176
|
-
const error = new webpack_1.WebpackError("Encountered a block with multiple possible render files");
|
|
177
|
-
error.file = node_path_1.default.join(sourceDir, 'block.json');
|
|
178
|
-
compilation.warnings.push(error);
|
|
179
|
-
json[validTemplateLocation] = renderTemplate.find(p => p.endsWith(".php")) ?? renderTemplate[0];
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
json[validTemplateLocation] = renderTemplate[0];
|
|
183
|
-
}
|
|
151
|
+
json["plaudit"] = {};
|
|
184
152
|
}
|
|
185
|
-
compilation.updateAsset(name, new webpack_1.sources.RawSource(JSON.stringify(json, undefined, " ")));
|
|
186
153
|
}
|
|
154
|
+
json["plaudit"]["setup"] = setupFiles.length === 1 ? setupFiles[0] : setupFiles;
|
|
187
155
|
}
|
|
156
|
+
if (json["acf"]) {
|
|
157
|
+
if (json["acf"]["renderTemplate"]) {
|
|
158
|
+
json["render_template"] = json["acf"]["renderTemplate"];
|
|
159
|
+
delete json["acf"]["renderTemplate"];
|
|
160
|
+
}
|
|
161
|
+
else if (json["acf"]["render_template"]) {
|
|
162
|
+
json["render_template"] = json["acf"]["render_template"];
|
|
163
|
+
delete json["acf"]["render_template"];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const blockName = json["name"]?.toString() || "non-existent/block-name";
|
|
167
|
+
let rawRenderTemplate = json["render"] ?? json["render_template"];
|
|
168
|
+
rawRenderTemplate = (rawRenderTemplate
|
|
169
|
+
? (typeof rawRenderTemplate === 'string' ? [rawRenderTemplate] : rawRenderTemplate)
|
|
170
|
+
: [`${blockName.substring(blockName.indexOf('/') + 1)}.php`, "template.php", "template.twig"]);
|
|
171
|
+
const renderTemplate = pathsNeedRemapping
|
|
172
|
+
? rawRenderTemplate
|
|
173
|
+
.map(p => node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p))))
|
|
174
|
+
.filter(p => node_fs_1.default.existsSync(p))
|
|
175
|
+
.map(p => `file:./${BlockJSONManagingPlugin.findRelativeRouteBetween(outputDir, p)}`)
|
|
176
|
+
: rawRenderTemplate
|
|
177
|
+
.filter(p => node_fs_1.default.existsSync(node_path_1.default.normalize(node_path_1.default.join(sourceDir, BlockJSONManagingPlugin.stripFilePrefix(p)))));
|
|
178
|
+
if (renderTemplate.length === 0) {
|
|
179
|
+
delete json["render_template"];
|
|
180
|
+
delete json["render"];
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
let validTemplateLocation, invalidTemplateLocation;
|
|
184
|
+
if (json["acf"] || (json["plaudit"] && (json["plaudit"] !== "native" && (typeof json["plaudit"] !== 'object' || json["plaudit"]?.["type"] !== "native")))) {
|
|
185
|
+
// ACF-like blocks need to have the template stored in render_template.
|
|
186
|
+
// Because we can statically detect ACF-like blocks, we can make the move here instead of at run-time.
|
|
187
|
+
validTemplateLocation = "render_template";
|
|
188
|
+
invalidTemplateLocation = "render";
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
validTemplateLocation = "render";
|
|
192
|
+
invalidTemplateLocation = "render_template";
|
|
193
|
+
}
|
|
194
|
+
delete json[invalidTemplateLocation];
|
|
195
|
+
if (renderTemplate.length > 1) {
|
|
196
|
+
const error = new webpack_1.WebpackError("Encountered a block with multiple possible render files");
|
|
197
|
+
error.file = node_path_1.default.join(sourceDir, 'block.json');
|
|
198
|
+
compilation.warnings.push(error);
|
|
199
|
+
json[validTemplateLocation] = renderTemplate.find(p => p.endsWith(".php")) ?? renderTemplate[0];
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
json[validTemplateLocation] = renderTemplate[0];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
compilation[name in compilation.assets ? 'updateAsset' : 'emitAsset'](name, new webpack_1.sources.RawSource(JSON.stringify(json, undefined, " ")));
|
|
188
206
|
}
|
|
189
|
-
const sortedBlockDirConfigData = Object.fromEntries(Object.entries(blockDirConfigData)
|
|
207
|
+
const sortedBlockDirConfigData = Object.fromEntries(Object.entries(blockDirConfigData)
|
|
208
|
+
.sort(([a], [b]) => a.localeCompare(b)));
|
|
190
209
|
compilation.emitAsset("blockdir.config", new webpack_1.sources.RawSource((0, php_serializer_1.default)(sortedBlockDirConfigData)));
|
|
191
210
|
});
|
|
192
211
|
});
|
|
193
212
|
}
|
|
194
|
-
findCommonAncestor(...paths) {
|
|
213
|
+
static findCommonAncestor(...paths) {
|
|
195
214
|
return paths.map(p => node_path_1.default.normalize(p).split(node_path_1.default.sep)).reduce((prior, current) => {
|
|
196
215
|
for (let i = 0, limit = Math.min(prior.length, current.length); i < limit; i++) {
|
|
197
216
|
if (prior[i] !== current[i]) {
|
|
@@ -201,8 +220,8 @@ class BlockJSONManagingPlugin {
|
|
|
201
220
|
return current.length < prior.length ? current : prior;
|
|
202
221
|
});
|
|
203
222
|
}
|
|
204
|
-
findRelativeRouteBetween(path1, path2) {
|
|
205
|
-
const commonAncestor =
|
|
223
|
+
static findRelativeRouteBetween(path1, path2) {
|
|
224
|
+
const commonAncestor = BlockJSONManagingPlugin.findCommonAncestor(path1, path2);
|
|
206
225
|
const route = Array(path1.split(node_path_1.default.sep).length - commonAncestor.length).fill("..");
|
|
207
226
|
route.push(node_path_1.default.relative(commonAncestor.join(node_path_1.default.sep), path2));
|
|
208
227
|
return route.join(node_path_1.default.sep);
|
|
@@ -210,34 +229,8 @@ class BlockJSONManagingPlugin {
|
|
|
210
229
|
static hashThingForAsset(thing) {
|
|
211
230
|
return node_crypto_1.default.createHash('md5').update(thing).digest("hex").substring(0, 20).toLowerCase();
|
|
212
231
|
}
|
|
213
|
-
static
|
|
214
|
-
|
|
215
|
-
.filter((asset) => asset.chunks?.length === 1)
|
|
216
|
-
.filter(asset => !asset.name.endsWith("-rtl.css"))
|
|
217
|
-
.filter(asset => !asset.name.endsWith('.asset.php'))
|
|
218
|
-
.map(asset => {
|
|
219
|
-
let assetHash = asset.info.contenthash ?? asset.info.fullhash;
|
|
220
|
-
if (Array.isArray(assetHash)) {
|
|
221
|
-
assetHash = BlockJSONManagingPlugin.hashThingForAsset(assetHash.join('~'));
|
|
222
|
-
}
|
|
223
|
-
return [asset.chunks[0], [asset.name, assetHash ?? (() => {
|
|
224
|
-
const realAsset = compilationAssets[asset.name];
|
|
225
|
-
return BlockJSONManagingPlugin.hashThingForAsset(realAsset ? realAsset.source().toString() : Date.now().toString());
|
|
226
|
-
})]];
|
|
227
|
-
}));
|
|
228
|
-
const res = new Map(stats.modules
|
|
229
|
-
.map(module => {
|
|
230
|
-
if (module.nameForCondition !== undefined && module.chunks?.length === 1) {
|
|
231
|
-
const output = singleFileChunkToOutputName.get(module.chunks[0]);
|
|
232
|
-
return output !== undefined ? [module.nameForCondition, output] : undefined;
|
|
233
|
-
}
|
|
234
|
-
return undefined;
|
|
235
|
-
})
|
|
236
|
-
.filter((v) => v !== undefined));
|
|
237
|
-
for (const [key, value] of BlockJSONManagingPlugin.moduleSourcesToOutputs.entries()) {
|
|
238
|
-
res.set(key, value);
|
|
239
|
-
}
|
|
240
|
-
return res;
|
|
232
|
+
static stripFilePrefix(file) {
|
|
233
|
+
return file.startsWith("file:./") ? file.substring(7) : file;
|
|
241
234
|
}
|
|
242
235
|
}
|
|
243
236
|
exports.default = BlockJSONManagingPlugin;
|
|
@@ -13,7 +13,7 @@ class ExtensionsConfigFileGeneratorPlugin {
|
|
|
13
13
|
this.extensionsPath = extensionsPath;
|
|
14
14
|
}
|
|
15
15
|
apply(compiler) {
|
|
16
|
-
compiler.hooks.make.tapPromise(
|
|
16
|
+
compiler.hooks.make.tapPromise(this.constructor.name, async (compilation) => {
|
|
17
17
|
if (!compilation.contextDependencies.has(this.extensionsPath)) {
|
|
18
18
|
compilation.contextDependencies.add(this.extensionsPath);
|
|
19
19
|
}
|
|
@@ -28,9 +28,9 @@ class ExtensionsConfigFileGeneratorPlugin {
|
|
|
28
28
|
}
|
|
29
29
|
await Promise.all(emissionPromises);
|
|
30
30
|
});
|
|
31
|
-
compiler.hooks.thisCompilation.tap(
|
|
31
|
+
compiler.hooks.thisCompilation.tap(this.constructor.name, compilation => {
|
|
32
32
|
compilation.hooks.processAssets.tap({
|
|
33
|
-
name:
|
|
33
|
+
name: `${this.constructor.name}_ProcessAssets`,
|
|
34
34
|
stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_ANALYSE
|
|
35
35
|
}, compilationAssets => {
|
|
36
36
|
const stats = compilation.getStats().toJson({
|
|
@@ -15,6 +15,12 @@ type PlauditWordpressWebpackConfig = {
|
|
|
15
15
|
postcss?: {
|
|
16
16
|
functions?: (variables: (name: string) => unknown) => PostcssFunctionsOptions['functions'];
|
|
17
17
|
};
|
|
18
|
+
externals?: {
|
|
19
|
+
[dep: string]: string | {
|
|
20
|
+
import: string;
|
|
21
|
+
handle: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
18
24
|
};
|
|
19
25
|
declare const _default: (config: PlauditWordpressWebpackConfig, webpackConfig?: Configuration[] | Configuration) => Configuration[];
|
|
20
26
|
export = _default;
|
|
@@ -10,19 +10,20 @@ const ExtensionsConfigFileGeneratorPlugin_1 = __importDefault(require("./wordpre
|
|
|
10
10
|
const VariablesJSMonitorPlugin_1 = __importDefault(require("./wordpress-scripts-wrapper/VariablesJSMonitorPlugin"));
|
|
11
11
|
const BrowserSyncPlugin_1 = require("./wordpress-scripts-wrapper/BrowserSyncPlugin");
|
|
12
12
|
const static_configs_1 = require("./wordpress-scripts-wrapper/static-configs");
|
|
13
|
+
const dependency_extraction_webpack_plugin_1 = __importDefault(require("@wordpress/dependency-extraction-webpack-plugin"));
|
|
13
14
|
const copy_webpack_plugin_1 = __importDefault(require("copy-webpack-plugin"));
|
|
14
15
|
const fork_ts_checker_webpack_plugin_1 = __importDefault(require("fork-ts-checker-webpack-plugin"));
|
|
15
16
|
const webpack_remove_empty_scripts_1 = __importDefault(require("webpack-remove-empty-scripts"));
|
|
16
17
|
function joinPossiblyAbsolutePaths(...paths) {
|
|
17
18
|
return paths.reduce((res, p) => !res || node_path_1.default.isAbsolute(p) ? p : node_path_1.default.join(res, p), '') || '.';
|
|
18
19
|
}
|
|
19
|
-
function mapToRealEntrypoints(entrypoint, dir, mapper = (entrypoint) => entrypoint) {
|
|
20
|
+
function mapToRealEntrypoints(entrypoint, dir, mapper = (entrypoint) => entrypoint, lazyDependent) {
|
|
20
21
|
return (Array.isArray(entrypoint) ? entrypoint : [entrypoint])
|
|
21
22
|
.map(ep => joinPossiblyAbsolutePaths(dir, mapper(ep)))
|
|
22
23
|
.filter(ep => node_fs_1.default.statSync(ep, { throwIfNoEntry: false })?.isFile())
|
|
23
24
|
.map(ep => {
|
|
24
25
|
const parsedEntrypoint = node_path_1.default.parse(ep);
|
|
25
|
-
return [joinPossiblyAbsolutePaths(node_path_1.default.basename(parsedEntrypoint.dir), parsedEntrypoint.name), { import: ep }];
|
|
26
|
+
return [joinPossiblyAbsolutePaths(node_path_1.default.basename(parsedEntrypoint.dir), parsedEntrypoint.name), { import: ep, lazyDependent }];
|
|
26
27
|
});
|
|
27
28
|
}
|
|
28
29
|
let isInThemeCache = undefined;
|
|
@@ -224,10 +225,10 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
|
|
|
224
225
|
scriptExtension = scriptWithoutModuleExtension;
|
|
225
226
|
entrypointFields = ["editorStyle", "viewStyle", "style", "editorScript", "viewScript", "script"];
|
|
226
227
|
}
|
|
227
|
-
const { standaloneBlocks, variablesFilePath, verbose } = config;
|
|
228
|
+
const { standaloneBlocks, variablesFilePath, verbose, externals } = config;
|
|
228
229
|
let currentVariables = config.currentVariables;
|
|
229
230
|
replaceDefaultURLProcessing(webpackConfig);
|
|
230
|
-
const fixedRules = injectPostcssConfigOverrides(webpackConfig, name => currentVariables[name], config.postcss.functions ?? (() => ({})), verbose);
|
|
231
|
+
const fixedRules = injectPostcssConfigOverrides(webpackConfig, name => currentVariables[name], config.postcss.functions ?? (() => ({})), verbose) ?? [];
|
|
231
232
|
return sources.map(([src, dest]) => {
|
|
232
233
|
const srcRoots = (typeof dest !== 'string' && dest.withLegacyBlocksIn
|
|
233
234
|
? [...src.split(','), ...resolveLegacyBlockScriptsInFolder(dest.withLegacyBlocksIn)]
|
|
@@ -281,6 +282,37 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
|
|
|
281
282
|
if (srcIsDirectory && (typeof dest !== 'string' && dest.directoryLayout === 'extensions')) {
|
|
282
283
|
plugins.push(new ExtensionsConfigFileGeneratorPlugin_1.default(srcRoot));
|
|
283
284
|
}
|
|
285
|
+
if (externals) {
|
|
286
|
+
const pluginIndex = plugins.findIndex(plugin => plugin instanceof dependency_extraction_webpack_plugin_1.default);
|
|
287
|
+
if (pluginIndex === -1) {
|
|
288
|
+
console.error("Cannot apply externals when they have been disabled via CLI flag.");
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
plugins[pluginIndex] = new dependency_extraction_webpack_plugin_1.default({
|
|
292
|
+
requestToExternal(request) {
|
|
293
|
+
const possibleExternal = externals[request];
|
|
294
|
+
if (typeof possibleExternal === 'string') {
|
|
295
|
+
return possibleExternal;
|
|
296
|
+
}
|
|
297
|
+
else if (possibleExternal !== undefined) {
|
|
298
|
+
return possibleExternal['import'];
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
requestToHandle(request) {
|
|
305
|
+
const possibleExternal = externals[request];
|
|
306
|
+
if (possibleExternal !== undefined && typeof possibleExternal !== 'string') {
|
|
307
|
+
return typeof possibleExternal.handle;
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
return request;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
284
316
|
if (process.argv.includes('--browser-sync') || process.env['BROWSER_SYNC'] === 'true') {
|
|
285
317
|
plugins.push(new BrowserSyncPlugin_1.BrowserSyncPlugin());
|
|
286
318
|
}
|
|
@@ -304,11 +336,13 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
|
|
|
304
336
|
const res = [];
|
|
305
337
|
try {
|
|
306
338
|
const blockJSON = JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(dir, 'block.json'), 'utf8'));
|
|
339
|
+
const blockJSONChunkName = node_path_1.default.join(node_path_1.default.basename(dir), "block.json");
|
|
307
340
|
for (const key of entrypointFields) {
|
|
308
341
|
if (key in blockJSON) {
|
|
309
|
-
res.push(...mapToRealEntrypoints(blockJSON[key], dir, ep => ep.startsWith("file:") ? ep.substring(5) : ep));
|
|
342
|
+
res.push(...mapToRealEntrypoints(blockJSON[key], dir, ep => ep.startsWith("file:") ? ep.substring(5) : ep, blockJSONChunkName));
|
|
310
343
|
}
|
|
311
344
|
}
|
|
345
|
+
res.push([blockJSONChunkName, { import: node_path_1.default.join(dir, 'block.json') }]);
|
|
312
346
|
return res;
|
|
313
347
|
}
|
|
314
348
|
catch (e) {
|
|
@@ -341,6 +375,27 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
|
|
|
341
375
|
}
|
|
342
376
|
}
|
|
343
377
|
}
|
|
378
|
+
// This is used to allow for block.json dependencies to correctly account for name-deduplication
|
|
379
|
+
for (const [key, entry] of Object.entries(currentEntry)) {
|
|
380
|
+
if (typeof entry === 'object' && !Array.isArray(entry) && 'lazyDependent' in entry && typeof entry.lazyDependent === 'string') {
|
|
381
|
+
const target = currentEntry[entry.lazyDependent];
|
|
382
|
+
if (typeof target === 'object' && !Array.isArray(target)) {
|
|
383
|
+
let dependOn;
|
|
384
|
+
if (target.dependOn === undefined) {
|
|
385
|
+
dependOn = target.dependOn = [];
|
|
386
|
+
}
|
|
387
|
+
else if (typeof target.dependOn === 'string') {
|
|
388
|
+
dependOn = target.dependOn = [target.dependOn];
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
dependOn = target.dependOn;
|
|
392
|
+
}
|
|
393
|
+
if (!dependOn.includes(key)) {
|
|
394
|
+
dependOn.push(key);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
344
399
|
return currentEntry;
|
|
345
400
|
};
|
|
346
401
|
}
|
|
@@ -395,7 +450,16 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
|
|
|
395
450
|
},
|
|
396
451
|
module: {
|
|
397
452
|
...webpackConfig.module,
|
|
398
|
-
rules: fixedRules
|
|
453
|
+
rules: [...fixedRules, {
|
|
454
|
+
test: /block\.json/i,
|
|
455
|
+
type: 'asset/resource',
|
|
456
|
+
generator: {
|
|
457
|
+
filename(pathData) {
|
|
458
|
+
// This mess of a name-generator accounts for WebPack's calculated name changing when block.json has dependents.
|
|
459
|
+
return node_path_1.default.join(node_path_1.default.basename(node_path_1.default.dirname(pathData.filename ?? pathData.runtime?.toString() ?? "[name]")), "[name][ext]");
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}]
|
|
399
463
|
},
|
|
400
464
|
resolve: {
|
|
401
465
|
...webpackConfig.resolve,
|
|
@@ -405,7 +469,7 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
|
|
|
405
469
|
stats: config.stats,
|
|
406
470
|
plugins: copyFiles
|
|
407
471
|
? plugins.map(plugin => plugin.constructor.name === 'CopyPlugin'
|
|
408
|
-
? new copy_webpack_plugin_1.default({ patterns: [{ from: standaloneBlocks ? '**/(
|
|
472
|
+
? new copy_webpack_plugin_1.default({ patterns: [{ from: standaloneBlocks ? '**/(*.(php|twig|svg))' : '**/(*.(asset\.php|svg))',
|
|
409
473
|
context: srcRoot, noErrorOnMissing: true }] })
|
|
410
474
|
: plugin)
|
|
411
475
|
: (srcIsDirectory
|
|
@@ -419,17 +483,17 @@ function processIndividualWebpackConfig(config, webpackConfig, sources) {
|
|
|
419
483
|
return entry();
|
|
420
484
|
}
|
|
421
485
|
};
|
|
422
|
-
}).filter(
|
|
486
|
+
}).filter(cfg => cfg !== undefined);
|
|
423
487
|
}
|
|
424
488
|
module.exports = function (config, webpackConfig = require("@wordpress/scripts/config/webpack.config")) {
|
|
425
489
|
testForDuplicatedEntryPaths(config);
|
|
426
|
-
const { standaloneBlocks = false, stats = 'errors-warnings', variables: rawVariables, verbose = process.argv.includes('--verbose') || process.env['VERBOSE'] === 'true', postcss = {} } = config;
|
|
490
|
+
const { standaloneBlocks = false, stats = 'errors-warnings', variables: rawVariables, verbose = process.argv.includes('--verbose') || process.env['VERBOSE'] === 'true', postcss = {}, externals } = config;
|
|
427
491
|
let variablesFilePath = undefined;
|
|
428
492
|
const currentVariables = rawVariables ?? {};
|
|
429
493
|
if (!rawVariables) {
|
|
430
494
|
variablesFilePath = ["variables.js", "src/site/variables.js"].map(p => node_path_1.default.join(process.cwd(), p)).filter(p => node_fs_1.default.existsSync(p))[0];
|
|
431
495
|
}
|
|
432
|
-
const cfg = { currentVariables, postcss, standaloneBlocks, stats, variablesFilePath, verbose };
|
|
496
|
+
const cfg = { currentVariables, postcss, standaloneBlocks, stats, variablesFilePath, verbose, externals };
|
|
433
497
|
const sources = Array.isArray(config.src) ? config.src.map(s => [s, s]) : Object.entries(config.src);
|
|
434
498
|
if (Array.isArray(webpackConfig)) {
|
|
435
499
|
return webpackConfig.flatMap(wpCfg => processIndividualWebpackConfig(cfg, wpCfg, sources));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plaudit/webpack-extensions",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.29.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepublishOnly": "rm -rf build && mkdir build && tsc",
|
|
6
6
|
"build": "tsc",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"postcss-load-config": "^4.0.2",
|
|
30
30
|
"postcss-loader": "^7.3.4",
|
|
31
31
|
"ts-node": "^10.9.2",
|
|
32
|
-
"typescript": "^5.
|
|
32
|
+
"typescript": "^5.6.2"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@plaudit/postcss-color-function": "^5.0.0",
|