@plaudit/webpack-extensions 2.85.3 → 2.87.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -0
- package/USER-GUIDE.md +105 -81
- package/build/plugins/EnhancedBlockJSONPlugin.js +4 -7
- package/build/plugins/ExtensionsConfigFileGeneratorPlugin.d.ts +7 -3
- package/build/plugins/ExtensionsConfigFileGeneratorPlugin.js +74 -10
- package/build/plugins/PlainEntrypointsConfigFileGeneratorPlugin.js +2 -1
- package/build/shared.d.ts +51 -12
- package/build/shared.js +56 -2
- package/build/utils/common-config-helpers.d.ts +1 -1
- package/build/utils/common-config-helpers.js +63 -6
- package/build/utils/entrypoint-resolution-logic.d.ts +10 -0
- package/build/utils/entrypoint-resolution-logic.js +84 -0
- package/build/utils/location-encoding-filename-parser.d.ts +26 -0
- package/build/utils/location-encoding-filename-parser.js +118 -0
- package/build/utils/path-query-and-related-helpers.d.ts +11 -7
- package/build/utils/path-query-and-related-helpers.js +41 -49
- package/build/wordpress-scripts-wrapper.js +64 -25
- package/package.json +7 -3
package/build/shared.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { PHPWriter } from "@plaudit/php-writer";
|
|
2
2
|
import type { Options as PostcssFunctionsOptions } from "postcss-functions";
|
|
3
3
|
import { AssetInfo, Compilation, Configuration, Entrypoint, WebpackError, Compiler } from "webpack";
|
|
4
|
+
import { SourceType } from "./utils/entrypoint-resolution-logic";
|
|
5
|
+
import type { NormalizedEnqueuingControlFlags } from "./utils/path-query-and-related-helpers";
|
|
6
|
+
export * from "./utils/entrypoint-resolution-logic";
|
|
4
7
|
export type ParsedAssetsJson = Record<string, {
|
|
5
8
|
dependencies: string[];
|
|
6
9
|
version: string;
|
|
@@ -54,16 +57,19 @@ export type StandardLocationNameMeta = {
|
|
|
54
57
|
};
|
|
55
58
|
};
|
|
56
59
|
export type StandardLocationNames = keyof typeof standardLocationNamesMeta;
|
|
60
|
+
export declare function isStandardLocationName(name: string): name is StandardLocationNames;
|
|
57
61
|
type LocationWithHookNameSupport = boolean | number | string | string[] | {
|
|
58
62
|
hook_name?: string | string[];
|
|
59
63
|
priority?: number;
|
|
60
64
|
};
|
|
61
65
|
type InputRegisterScriptArgs = ScriptArgsObject | boolean | 'lazy' | 'eager' | 'inline';
|
|
62
|
-
export
|
|
66
|
+
export declare function isRegisterScriptArgsShorthandName(name: string): name is Extract<InputRegisterScriptArgs, string>;
|
|
67
|
+
export type RealUsageLocations = {
|
|
63
68
|
[K in StandardLocationNames]?: typeof standardLocationNamesMeta[K] extends {
|
|
64
69
|
supports_hook_name: true;
|
|
65
70
|
} ? LocationWithHookNameSupport : boolean | number;
|
|
66
|
-
}
|
|
71
|
+
};
|
|
72
|
+
export type UsageLocations = RealUsageLocations & {
|
|
67
73
|
register?: boolean | number;
|
|
68
74
|
inline?: number;
|
|
69
75
|
handle?: string | ((generatedHandle: string) => string);
|
|
@@ -74,16 +80,11 @@ export type NormalizedUsageLocations = Omit<UsageLocations, 'registerScriptArgs'
|
|
|
74
80
|
};
|
|
75
81
|
export declare function isNormalizedUsageLocations(usageLocations: UsageLocations): usageLocations is NormalizedUsageLocations;
|
|
76
82
|
export declare function constantKeys<K extends string, V>(object: {
|
|
77
|
-
[k in K]
|
|
83
|
+
[k in K]?: V;
|
|
78
84
|
}): K[];
|
|
79
85
|
export declare function constantEntries<K extends string, V>(object: {
|
|
80
86
|
[k in K]: V;
|
|
81
87
|
}): [K, V][];
|
|
82
|
-
export declare const enum SourceType {
|
|
83
|
-
blocks = "blocks",
|
|
84
|
-
extensions = "extensions",
|
|
85
|
-
plain = "plain"
|
|
86
|
-
}
|
|
87
88
|
export declare function determineCurrentSourceType(dest: string | AdvancedOutputConfig, srcIsDirectory: boolean): SourceType;
|
|
88
89
|
export interface WebpackPlugin {
|
|
89
90
|
apply(compiler: Compiler): void;
|
|
@@ -107,17 +108,20 @@ export type AdvancedOutputConfig = {
|
|
|
107
108
|
locations?: UsageLocations | UsageLocations['handle'];
|
|
108
109
|
lazyLoader?: string;
|
|
109
110
|
pathQueryParameters?: PathQueryParameters;
|
|
111
|
+
enqueuingFlags?: NormalizedEnqueuingControlFlags;
|
|
110
112
|
};
|
|
111
113
|
type OptionalCfgFields = 'directoryLayout' | 'externalize' | 'lazyLoader' | 'pathQueryParameters';
|
|
112
|
-
export type VerifiedAdvancedOutputConfig = Required<Omit<AdvancedOutputConfig, 'locations' | OptionalCfgFields>> & Pick<AdvancedOutputConfig, OptionalCfgFields> & {
|
|
114
|
+
export type VerifiedAdvancedOutputConfig = Required<Omit<AdvancedOutputConfig, 'locations' | 'enqueuingFlags' | OptionalCfgFields>> & Pick<AdvancedOutputConfig, OptionalCfgFields> & {
|
|
115
|
+
enqueuingFlags: NormalizedEnqueuingControlFlags | undefined;
|
|
113
116
|
locations: NormalizedUsageLocations;
|
|
114
117
|
};
|
|
115
118
|
export type SourcesObject = Record<string, string | AdvancedOutputConfig | boolean>;
|
|
116
119
|
export type PlauditWordpressWebpackConfig = {
|
|
120
|
+
standard?: '2026-03-13';
|
|
117
121
|
standaloneBlocks?: boolean;
|
|
118
122
|
variables?: Record<string, any>;
|
|
119
123
|
verbose?: boolean;
|
|
120
|
-
src
|
|
124
|
+
src?: string[] | SourcesObject;
|
|
121
125
|
stats?: Configuration['stats'];
|
|
122
126
|
postcss?: {
|
|
123
127
|
functions?: (variables: (name: string) => unknown) => PostcssFunctionsOptions['functions'];
|
|
@@ -138,6 +142,41 @@ export type PlauditWordpressWebpackConfig = {
|
|
|
138
142
|
omitDistDev?: boolean;
|
|
139
143
|
onlyRunPostCSSOnPCSS?: boolean;
|
|
140
144
|
};
|
|
145
|
+
export declare function applyStandards(config: PlauditWordpressWebpackConfig): {
|
|
146
|
+
readonly standard?: "2026-03-13";
|
|
147
|
+
readonly standaloneBlocks?: boolean;
|
|
148
|
+
readonly variables?: Record<string, any>;
|
|
149
|
+
readonly verbose?: boolean;
|
|
150
|
+
readonly src?: string[] | SourcesObject;
|
|
151
|
+
readonly stats?: Configuration["stats"];
|
|
152
|
+
readonly postcss?: {
|
|
153
|
+
functions?: (variables: (name: string) => unknown) => PostcssFunctionsOptions["functions"];
|
|
154
|
+
};
|
|
155
|
+
readonly externals?: Externals;
|
|
156
|
+
readonly assumeGlobalizedPlauditLibraries?: boolean;
|
|
157
|
+
readonly processTranslationConfigs?: boolean;
|
|
158
|
+
readonly combineAssetMetadata?: boolean;
|
|
159
|
+
useWebpackResourceFiltering?: boolean;
|
|
160
|
+
outputDir?: string;
|
|
161
|
+
extensionsVersion?: 1 | 2 | 3;
|
|
162
|
+
readonly targetHandlePrefix?: string;
|
|
163
|
+
plainEntrypointsVersion?: 1 | 2;
|
|
164
|
+
srcDir?: string;
|
|
165
|
+
readonly srcPrefixes?: string[];
|
|
166
|
+
useUnifiedLoader?: boolean;
|
|
167
|
+
readonly includePostInitFallback?: boolean;
|
|
168
|
+
readonly omitDistDev?: boolean;
|
|
169
|
+
onlyRunPostCSSOnPCSS?: boolean;
|
|
170
|
+
};
|
|
171
|
+
export declare function resolveStandard(standard: PlauditWordpressWebpackConfig['standard']): {
|
|
172
|
+
readonly useWebpackResourceFiltering: true;
|
|
173
|
+
readonly extensionsVersion: 3;
|
|
174
|
+
readonly plainEntrypointsVersion: 2;
|
|
175
|
+
readonly srcDir: "src";
|
|
176
|
+
readonly outputDir: "dist";
|
|
177
|
+
readonly useUnifiedLoader: true;
|
|
178
|
+
readonly onlyRunPostCSSOnPCSS: true;
|
|
179
|
+
} | undefined;
|
|
141
180
|
export type FileSegmentBlockEntrypointInfo = {
|
|
142
181
|
blockJsonOrigin: string;
|
|
143
182
|
entrypointField: EntrypointFields[number];
|
|
@@ -148,6 +187,7 @@ export type FileSegmentBlockEntrypointInfo = {
|
|
|
148
187
|
dest: VerifiedAdvancedOutputConfig;
|
|
149
188
|
absoluteSrc: string;
|
|
150
189
|
pathQueryParameters: PathQueryParameters | undefined;
|
|
190
|
+
enqueuingFlags: NormalizedEnqueuingControlFlags | undefined;
|
|
151
191
|
};
|
|
152
192
|
export type PathQueryParameters = Record<string, unknown | [unknown, ...unknown[]]>;
|
|
153
193
|
export type BlockEntrypointInfo = FileSegmentBlockEntrypointInfo | {
|
|
@@ -169,7 +209,7 @@ export declare const scriptExtension: RegExp;
|
|
|
169
209
|
export declare const scriptWithoutModuleExtension: RegExp;
|
|
170
210
|
export declare const scriptWithModuleExtension: RegExp;
|
|
171
211
|
export declare const styleExtension: RegExp;
|
|
172
|
-
export declare function scriptOrStyleTest(entryPath: string, scriptExtension: RegExp): "
|
|
212
|
+
export declare function scriptOrStyleTest(entryPath: string, scriptExtension: RegExp): "script" | "style" | "";
|
|
173
213
|
export declare function isStyleField(field: string): field is 'style' | 'viewStyle' | 'editorStyle';
|
|
174
214
|
export declare function isScriptModuleField(field: string): field is 'viewScriptModule';
|
|
175
215
|
export declare function getHandleGroup(field: string): 'styleHandles' | 'scriptHandles' | 'scriptModuleHandles';
|
|
@@ -208,4 +248,3 @@ export declare function resolveLegacyBlockScriptsInFolder(folder: string): strin
|
|
|
208
248
|
* @param file something that represents the file that is being inlined (this is purely for error-reporting purposes)
|
|
209
249
|
*/
|
|
210
250
|
export declare function appendAddInlineAssetCall(compilation: Compilation, writer: PHPWriter, handle: string, type: 'script' | 'style' | 'script_module', inlinedAsset: InlinedAsset, handleData: HandleData, file: string): void;
|
|
211
|
-
export {};
|
package/build/shared.js
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
18
|
};
|
|
5
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
20
|
exports.styleExtension = exports.scriptWithModuleExtension = exports.scriptWithoutModuleExtension = exports.scriptExtension = exports.entrypointFields = exports.standardLocationNamesMeta = void 0;
|
|
7
21
|
exports.isParsedAssetsJson = isParsedAssetsJson;
|
|
22
|
+
exports.isStandardLocationName = isStandardLocationName;
|
|
23
|
+
exports.isRegisterScriptArgsShorthandName = isRegisterScriptArgsShorthandName;
|
|
8
24
|
exports.isNormalizedUsageLocations = isNormalizedUsageLocations;
|
|
9
25
|
exports.constantKeys = constantKeys;
|
|
10
26
|
exports.constantEntries = constantEntries;
|
|
11
27
|
exports.determineCurrentSourceType = determineCurrentSourceType;
|
|
28
|
+
exports.applyStandards = applyStandards;
|
|
29
|
+
exports.resolveStandard = resolveStandard;
|
|
12
30
|
exports.convertUsageLocationsHandleToEmittableHandle = convertUsageLocationsHandleToEmittableHandle;
|
|
13
31
|
exports.makeEmittableConfigPHP = makeEmittableConfigPHP;
|
|
14
32
|
exports.convertEntrypointFieldForAssetType = convertEntrypointFieldForAssetType;
|
|
@@ -30,13 +48,14 @@ exports.emitPHPWriterAsAsset = emitPHPWriterAsAsset;
|
|
|
30
48
|
exports.dedent = dedent;
|
|
31
49
|
exports.resolveLegacyBlockScriptsInFolder = resolveLegacyBlockScriptsInFolder;
|
|
32
50
|
exports.appendAddInlineAssetCall = appendAddInlineAssetCall;
|
|
51
|
+
const node_crypto_1 = require("node:crypto");
|
|
33
52
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
34
53
|
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
35
54
|
const node_path_1 = __importDefault(require("node:path"));
|
|
36
55
|
const php_writer_1 = require("@plaudit/php-writer");
|
|
37
56
|
const expressions_1 = require("@plaudit/php-writer/expressions");
|
|
38
57
|
const webpack_1 = require("webpack");
|
|
39
|
-
|
|
58
|
+
__exportStar(require("./utils/entrypoint-resolution-logic"), exports);
|
|
40
59
|
function isParsedAssetsJson(thing) {
|
|
41
60
|
if (!thing || typeof thing !== 'object') {
|
|
42
61
|
return false;
|
|
@@ -59,6 +78,12 @@ exports.standardLocationNamesMeta = {
|
|
|
59
78
|
customizer: { action: "customize_controls_enqueue_scripts" },
|
|
60
79
|
analytics: { action: "plaudit_enqueue_analytics" },
|
|
61
80
|
};
|
|
81
|
+
function isStandardLocationName(name) {
|
|
82
|
+
return name in exports.standardLocationNamesMeta;
|
|
83
|
+
}
|
|
84
|
+
function isRegisterScriptArgsShorthandName(name) {
|
|
85
|
+
return ['lazy', 'eager', 'inline'].includes(name);
|
|
86
|
+
}
|
|
62
87
|
function isNormalizedUsageLocations(usageLocations) {
|
|
63
88
|
return typeof usageLocations.registerScriptArgs !== 'string';
|
|
64
89
|
}
|
|
@@ -84,6 +109,35 @@ function determineCurrentSourceType(dest, srcIsDirectory) {
|
|
|
84
109
|
return dest.directoryLayout;
|
|
85
110
|
}
|
|
86
111
|
}
|
|
112
|
+
function applyStandards(config) {
|
|
113
|
+
switch (config.standard) {
|
|
114
|
+
case '2026-03-13':
|
|
115
|
+
return {
|
|
116
|
+
...resolveStandard('2026-03-13'),
|
|
117
|
+
...config
|
|
118
|
+
};
|
|
119
|
+
case undefined:
|
|
120
|
+
return config;
|
|
121
|
+
default:
|
|
122
|
+
throw `Invalid standard: ${config.standard}`;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function resolveStandard(standard) {
|
|
126
|
+
switch (standard) {
|
|
127
|
+
case "2026-03-13":
|
|
128
|
+
return {
|
|
129
|
+
useWebpackResourceFiltering: true,
|
|
130
|
+
extensionsVersion: 3,
|
|
131
|
+
plainEntrypointsVersion: 2,
|
|
132
|
+
srcDir: "src",
|
|
133
|
+
outputDir: "dist",
|
|
134
|
+
useUnifiedLoader: true,
|
|
135
|
+
onlyRunPostCSSOnPCSS: true,
|
|
136
|
+
};
|
|
137
|
+
default:
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
87
141
|
function convertUsageLocationsHandleToEmittableHandle(handle, generatedHandle) {
|
|
88
142
|
const emittableHandle = typeof handle === 'string' ? handle : handle?.(generatedHandle) ?? generatedHandle;
|
|
89
143
|
return emittableHandle.replaceAll("{basename}", generatedHandle);
|
|
@@ -107,7 +161,7 @@ function leadingSlashIt(pathOrSomething) {
|
|
|
107
161
|
exports.scriptExtension = /(?<filename>.+)(?<extension>\.m?[jt]sx?)$/i;
|
|
108
162
|
exports.scriptWithoutModuleExtension = /(?<filename>.+)(?<extension>\.[jt]sx?)($|\?)/i;
|
|
109
163
|
exports.scriptWithModuleExtension = /(?<filename>.+)(?<extension>\.m[jt]sx?)($|\?)/i;
|
|
110
|
-
exports.styleExtension = /(?<filename>.+)(?<extension>\.(
|
|
164
|
+
exports.styleExtension = /(?<filename>.+)(?<extension>\.([ps]?c|sa)ss)($|\?)/i;
|
|
111
165
|
function scriptOrStyleTest(entryPath, scriptExtension) {
|
|
112
166
|
return scriptExtension.test(entryPath) ? "script" : (exports.styleExtension.test(entryPath) ? "style" : "");
|
|
113
167
|
}
|
|
@@ -3,7 +3,7 @@ import type { AdditionalDependencyInjectorPlugin } from "../plugins/AdditionalDe
|
|
|
3
3
|
import { EntrypointFields, PlauditWordpressWebpackConfig, BlockEntrypointInfo, VerifiedAdvancedOutputConfig, MinimumViableMetadata, WebpackPlugin } from "../shared";
|
|
4
4
|
import type { Compiler, Configuration, DynamicEntryPlugin, WebpackPluginInstance } from "webpack";
|
|
5
5
|
import type WebpackRemoveEmptyScriptsPlugin from "webpack-remove-empty-scripts";
|
|
6
|
-
export type VerifiedPlauditWordpressWebpackConfig = Required<Omit<PlauditWordpressWebpackConfig, 'variables' | 'src' | 'externals'>> & {
|
|
6
|
+
export type VerifiedPlauditWordpressWebpackConfig = Required<Omit<PlauditWordpressWebpackConfig, 'variables' | 'src' | 'externals' | 'standard'>> & {
|
|
7
7
|
variablesFilePath?: string;
|
|
8
8
|
currentVariables: Record<string, any>;
|
|
9
9
|
} & Pick<PlauditWordpressWebpackConfig, 'externals'>;
|
|
@@ -10,6 +10,7 @@ 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 location_encoding_filename_parser_1 = require("./location-encoding-filename-parser");
|
|
13
14
|
const path_query_and_related_helpers_1 = require("./path-query-and-related-helpers");
|
|
14
15
|
const shared_1 = require("../shared");
|
|
15
16
|
const css_minimizer_webpack_plugin_1 = __importDefault(require("css-minimizer-webpack-plugin"));
|
|
@@ -36,9 +37,10 @@ function mapToRealEntrypoints(entrypoint, dir, supportedExtensions, args) {
|
|
|
36
37
|
.map(ep => joinPossiblyAbsolutePaths(dir, mapper(ep)))
|
|
37
38
|
.filter(ep => supportedExtensions(ep) && node_fs_1.default.statSync(ep, { throwIfNoEntry: false })?.isFile())
|
|
38
39
|
.map(path_query_and_related_helpers_1.unpackPotentiallyPrefixedFilePath)
|
|
39
|
-
.map(([ep,
|
|
40
|
+
.map(([ep, rawPathQueryParameters]) => {
|
|
40
41
|
const parsedEntrypoint = node_path_1.default.parse(ep);
|
|
41
42
|
const entrypointField = shared_1.styleExtension.test(ep) ? 'style' : shared_1.scriptWithModuleExtension.test(ep) ? 'viewScriptModule' : 'script';
|
|
43
|
+
const { flags: enqueuingFlags, remainder: pathQueryParameters } = (0, path_query_and_related_helpers_1.unpackEnqueuingControlFlagsFromPathQueryParameters)(rawPathQueryParameters, ep, 'path query parameters');
|
|
42
44
|
const fakeEntrypointInfo = {
|
|
43
45
|
blockJsonOrigin: args.entrypointJsonOrigin,
|
|
44
46
|
entrypointField,
|
|
@@ -48,7 +50,8 @@ function mapToRealEntrypoints(entrypoint, dir, supportedExtensions, args) {
|
|
|
48
50
|
handleGroup: (0, shared_1.getHandleGroup)(entrypointField),
|
|
49
51
|
dest,
|
|
50
52
|
absoluteSrc: ep,
|
|
51
|
-
pathQueryParameters
|
|
53
|
+
pathQueryParameters,
|
|
54
|
+
enqueuingFlags,
|
|
52
55
|
};
|
|
53
56
|
return [joinPossiblyAbsolutePaths(dest.destination, node_path_1.default.basename(parsedEntrypoint.dir), parsedEntrypoint.name),
|
|
54
57
|
{ import: [ep], plauditMetadata: fakeEntrypointInfo }];
|
|
@@ -133,6 +136,7 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
|
|
|
133
136
|
const blockJsonOrigin = node_path_1.default.join(dir, 'block.json');
|
|
134
137
|
const blockJson = JSON.parse(await promises_1.default.readFile(blockJsonOrigin, 'utf8'));
|
|
135
138
|
const blockJsonChunkName = node_path_1.default.join(dest.destination, node_path_1.default.relative(srcRoot, dir), "block");
|
|
139
|
+
const filesRegisteredByJson = [];
|
|
136
140
|
const presentEntrypoints = (await Promise.all(entrypointFields
|
|
137
141
|
.filter(entrypointField => entrypointField in blockJson)
|
|
138
142
|
.flatMap(entrypointField => {
|
|
@@ -140,16 +144,19 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
|
|
|
140
144
|
.filter(originalValue => typeof originalValue === 'string')
|
|
141
145
|
.filter(originalValue => originalValue?.startsWith("file:"))
|
|
142
146
|
.map(originalValue => {
|
|
143
|
-
const [entrypointPath,
|
|
147
|
+
const [entrypointPath, rawLocalPathQueryParameters] = (0, path_query_and_related_helpers_1.unpackPotentiallyPrefixedFilePath)(originalValue);
|
|
144
148
|
const absoluteSrc = node_path_1.default.normalize(node_path_1.default.join(dir, entrypointPath));
|
|
145
|
-
|
|
149
|
+
filesRegisteredByJson.push(absoluteSrc);
|
|
150
|
+
const { flags: localEnqueuingFlags, remainder: localPathQueryParameters } = (0, path_query_and_related_helpers_1.unpackEnqueuingControlFlagsFromPathQueryParameters)(rawLocalPathQueryParameters, absoluteSrc, "path query parameters");
|
|
151
|
+
const enqueuingFlags = (0, path_query_and_related_helpers_1.mergeTwoScriptEnqueuingControlFlagSets)(absoluteSrc, localEnqueuingFlags, dest.enqueuingFlags);
|
|
152
|
+
const pathQueryParameters = { ...dest.pathQueryParameters, ...localPathQueryParameters };
|
|
146
153
|
return promises_1.default.stat(absoluteSrc)
|
|
147
154
|
.then(stats => {
|
|
148
155
|
if (stats.isFile()) {
|
|
149
156
|
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)));
|
|
150
157
|
const extensionlessExpectedSrc = node_path_1.default.normalize(node_path_1.default.join(parsedEntrypoint.dir, parsedEntrypoint.name));
|
|
151
158
|
const entrypointName = node_path_1.default.normalize(joinPossiblyAbsolutePaths(parsedEntrypoint.dir, parsedEntrypoint.name));
|
|
152
|
-
return { entrypointField, originalValue, entrypointName, extensionlessExpectedSrc, absoluteSrc, pathQueryParameters };
|
|
159
|
+
return { entrypointField, originalValue, entrypointName, extensionlessExpectedSrc, absoluteSrc, pathQueryParameters, enqueuingFlags };
|
|
153
160
|
}
|
|
154
161
|
else {
|
|
155
162
|
return undefined;
|
|
@@ -157,6 +164,56 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
|
|
|
157
164
|
}, () => undefined);
|
|
158
165
|
});
|
|
159
166
|
}))).filter(pe => pe !== undefined);
|
|
167
|
+
for await (const dirent of await promises_1.default.opendir(dir)) {
|
|
168
|
+
if (!dirent.isFile()) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const absoluteSrc = node_path_1.default.normalize(node_path_1.default.join(dir, dirent.name));
|
|
172
|
+
if (filesRegisteredByJson.includes(absoluteSrc)) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const parsedFilename = (0, location_encoding_filename_parser_1.parseLocationEncodingFilenameForBlock)(absoluteSrc);
|
|
176
|
+
if (!parsedFilename) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
const { type, locations, flags } = parsedFilename;
|
|
180
|
+
let entrypointField;
|
|
181
|
+
if (Object.keys(locations).length === 2) {
|
|
182
|
+
if (type === 'script-module') {
|
|
183
|
+
console.error(`Blocks cannot have script modules enqueued in editor mode. Found one enqueued in both editor and view in ${dirent.parentPath}. It will be enqueued in view alone.`);
|
|
184
|
+
entrypointField = 'viewScriptModule';
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
entrypointField = type;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
const location = (0, shared_1.constantKeys)(locations)[0];
|
|
192
|
+
if (type === 'script-module') {
|
|
193
|
+
if (location !== 'clientView') {
|
|
194
|
+
console.error(`Blocks cannot have script modules enqueued in editor mode. Found one in ${dirent.parentPath}. It will be ignored`);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
entrypointField = 'viewScriptModule';
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
entrypointField = (location.substring(6).toLowerCase() + type.substring(0, 1).toUpperCase() + type.substring(1));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
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), `./${dirent.name}`)));
|
|
204
|
+
const extensionlessExpectedSrc = node_path_1.default.normalize(node_path_1.default.join(parsedEntrypoint.dir, parsedEntrypoint.name));
|
|
205
|
+
const entrypointName = node_path_1.default.normalize(joinPossiblyAbsolutePaths(parsedEntrypoint.dir, parsedEntrypoint.name));
|
|
206
|
+
const enqueuingFlags = (0, path_query_and_related_helpers_1.mergeTwoScriptEnqueuingControlFlagSets)(absoluteSrc, flags, dest.enqueuingFlags);
|
|
207
|
+
presentEntrypoints.push({
|
|
208
|
+
entrypointField,
|
|
209
|
+
originalValue: dirent.name,
|
|
210
|
+
entrypointName,
|
|
211
|
+
extensionlessExpectedSrc,
|
|
212
|
+
absoluteSrc,
|
|
213
|
+
pathQueryParameters: dest.pathQueryParameters,
|
|
214
|
+
enqueuingFlags
|
|
215
|
+
});
|
|
216
|
+
}
|
|
160
217
|
const entrypointNamesWithEffectiveDuplicates = presentEntrypoints
|
|
161
218
|
.reduce((a, entry) => {
|
|
162
219
|
// 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
|
|
@@ -201,7 +258,7 @@ function resolveEntryFromDirectory(commonConfig, srcRoot, dest) {
|
|
|
201
258
|
}
|
|
202
259
|
];
|
|
203
260
|
}));
|
|
204
|
-
rawEntrypoints.push([blockJsonChunkName, { import: [blockJsonOrigin], plauditMetadata: { purpose: "block-json-inclusion-assurance", dest, absoluteSrc: blockJsonOrigin
|
|
261
|
+
rawEntrypoints.push([blockJsonChunkName, { import: [blockJsonOrigin], plauditMetadata: { purpose: "block-json-inclusion-assurance", dest, absoluteSrc: blockJsonOrigin } }]);
|
|
205
262
|
wpmlFiles.push(node_path_1.default.join(dir, 'block.json'));
|
|
206
263
|
}
|
|
207
264
|
catch (e) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AdvancedOutputConfig, PlauditWordpressWebpackConfig } from "../shared";
|
|
2
|
+
export declare const enum SourceType {
|
|
3
|
+
blocks = "blocks",
|
|
4
|
+
extensions = "extensions",
|
|
5
|
+
plain = "plain"
|
|
6
|
+
}
|
|
7
|
+
export declare function isSourceType(str: string): str is SourceType;
|
|
8
|
+
type Entrypoints = [string, AdvancedOutputConfig][];
|
|
9
|
+
export declare function resolveAllConfigLevelEntrypoints(config: PlauditWordpressWebpackConfig, projectRoot?: string): Record<'staticEntrypoints' | 'dynamicEntrypoints', Entrypoints>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isSourceType = isSourceType;
|
|
4
|
+
exports.resolveAllConfigLevelEntrypoints = resolveAllConfigLevelEntrypoints;
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
const location_encoding_filename_parser_1 = require("./location-encoding-filename-parser");
|
|
8
|
+
const path_query_and_related_helpers_1 = require("./path-query-and-related-helpers");
|
|
9
|
+
function isSourceType(str) {
|
|
10
|
+
return str === "blocks" /* SourceType.blocks */ || str === "extensions" /* SourceType.extensions */ || str === "plain" /* SourceType.plain */;
|
|
11
|
+
}
|
|
12
|
+
function resolveAllConfigLevelEntrypoints(config, projectRoot = process.cwd()) {
|
|
13
|
+
const srcDir = config.srcDir ?? "";
|
|
14
|
+
const normalizeSrcAndDestination = ([rawSrc, dest]) => {
|
|
15
|
+
let [src, pathQueryParameters] = (0, path_query_and_related_helpers_1.unpackPotentiallyPrefixedFilePath)(rawSrc);
|
|
16
|
+
if (srcDir) {
|
|
17
|
+
src = (0, node_path_1.join)(srcDir, src);
|
|
18
|
+
}
|
|
19
|
+
src = (0, node_path_1.isAbsolute)(src) ? (0, node_path_1.relative)(projectRoot, src) : src;
|
|
20
|
+
let resultObject;
|
|
21
|
+
if (dest.destination !== undefined && (0, node_path_1.isAbsolute)(dest.destination)) {
|
|
22
|
+
resultObject = { ...dest, destination: (0, node_path_1.relative)(projectRoot, dest.destination) };
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
resultObject = { ...dest };
|
|
26
|
+
}
|
|
27
|
+
return [src, pathQueryParameters ? { ...resultObject, pathQueryParameters } : resultObject];
|
|
28
|
+
};
|
|
29
|
+
if (Array.isArray(config.src)) {
|
|
30
|
+
return {
|
|
31
|
+
staticEntrypoints: config.src.map(s => normalizeSrcAndDestination([s, { destination: s }])),
|
|
32
|
+
dynamicEntrypoints: []
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const configSrc = config.src ?? {};
|
|
37
|
+
// We check for files with location-encoding filenames and add the pertinent ones to the sources
|
|
38
|
+
const dynamicallyIncludedEntrypoints = [];
|
|
39
|
+
if (srcDir) { // This will only work if we have a unified src root
|
|
40
|
+
const dynamicallyIncludedEntrypointsRoot = (0, node_path_1.isAbsolute)(srcDir) ? srcDir : (0, node_path_1.join)(projectRoot, srcDir);
|
|
41
|
+
using dir = (0, node_fs_1.opendirSync)(dynamicallyIncludedEntrypointsRoot);
|
|
42
|
+
for (let dirent; (dirent = dir.readSync()) !== null;) {
|
|
43
|
+
if (dirent.name in configSrc || `./${dirent.name}` in configSrc) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (dirent.isDirectory()) {
|
|
47
|
+
// If it's a directory that does not have an existing config entry, but does correspond to one of the non-plain SourceTypes, assume that it matches that source type
|
|
48
|
+
if (isSourceType(dirent.name) && dirent.name !== "plain" /* SourceType.plain */) {
|
|
49
|
+
dynamicallyIncludedEntrypoints.push([dirent.name, { directoryLayout: dirent.name }]);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
using nestedDir = (0, node_fs_1.opendirSync)((0, node_path_1.join)(dynamicallyIncludedEntrypointsRoot, dirent.name));
|
|
53
|
+
for (let nestedDirent; (nestedDirent = nestedDir.readSync()) !== null;) {
|
|
54
|
+
if (!nestedDirent.isFile()) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const cfgName = (0, node_path_1.join)(dirent.name, nestedDirent.name);
|
|
58
|
+
if (cfgName in configSrc || `./${cfgName}` in configSrc) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const parsedFilename = (0, location_encoding_filename_parser_1.parseLocationEncodingFilename)(cfgName);
|
|
62
|
+
if (parsedFilename === undefined) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
dynamicallyIncludedEntrypoints.push([cfgName, { locations: parsedFilename.locations, enqueuingFlags: parsedFilename.flags }]);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (dirent.isFile()) {
|
|
69
|
+
const parsedFilename = (0, location_encoding_filename_parser_1.parseLocationEncodingFilename)(dirent.name);
|
|
70
|
+
if (parsedFilename === undefined) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
dynamicallyIncludedEntrypoints.push([dirent.name, { locations: parsedFilename.locations, enqueuingFlags: parsedFilename.flags }]);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
staticEntrypoints: Object.entries(configSrc).map(([k, v]) => {
|
|
79
|
+
return normalizeSrcAndDestination([k, typeof v === 'boolean' ? {} : (typeof v === 'string' ? { destination: v } : v)]);
|
|
80
|
+
}),
|
|
81
|
+
dynamicEntrypoints: dynamicallyIncludedEntrypoints.map(normalizeSrcAndDestination)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { RealUsageLocations } from "../shared";
|
|
2
|
+
import { NormalizedEnqueuingControlFlags } from "./path-query-and-related-helpers";
|
|
3
|
+
export type ParsedLocationEncodingFilename = {
|
|
4
|
+
type: 'script' | 'style' | 'script-module';
|
|
5
|
+
locations: RealUsageLocations & {
|
|
6
|
+
register?: boolean | number;
|
|
7
|
+
};
|
|
8
|
+
flags: NormalizedEnqueuingControlFlags;
|
|
9
|
+
niceName?: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function parseLocationEncodingFilename(filename: string): ParsedLocationEncodingFilename | undefined;
|
|
12
|
+
export declare function parseLocationEncodingFilenameForBlock(filename: string, errorBuilder?: (message: string, filename: string) => unknown): Omit<ParsedLocationEncodingFilename, 'locations'> & {
|
|
13
|
+
locations: Pick<RealUsageLocations, 'clientEditor' | 'clientView'>;
|
|
14
|
+
} | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* This handles detecting all keys of standardLocationNamesMeta as well as "view", "client-view", "editor", "client-editor", and "block-assets".
|
|
17
|
+
* It MUST be kept in sync with standardLocationNamesMeta
|
|
18
|
+
* @param segment
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractLocationFromPropertyEncodingFilenameSegment(segment: string): {
|
|
21
|
+
readonly locationName: "clientView" | "clientEditor" | "blockAssets" | "admin" | "login" | "customizer" | "analytics" | "register";
|
|
22
|
+
readonly priority: number | true;
|
|
23
|
+
} | {
|
|
24
|
+
readonly locationName: false;
|
|
25
|
+
readonly priority?: undefined;
|
|
26
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseLocationEncodingFilename = parseLocationEncodingFilename;
|
|
4
|
+
exports.parseLocationEncodingFilenameForBlock = parseLocationEncodingFilenameForBlock;
|
|
5
|
+
exports.extractLocationFromPropertyEncodingFilenameSegment = extractLocationFromPropertyEncodingFilenameSegment;
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
7
|
+
const shared_1 = require("../shared");
|
|
8
|
+
function parseLocationEncodingFilename(filename) {
|
|
9
|
+
const { name, ext } = (0, node_path_1.parse)(filename);
|
|
10
|
+
if (name.startsWith("~")) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
let type = /^\.(?:s[ac]|p?c)ss$/i.test(ext) ? 'style' : /^\.m[jt]sx?/i.test(ext) ? 'script-module' : /^\.[jt]sx?/i.test(ext) ? 'script' : false;
|
|
14
|
+
if (type === false) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
const locations = {};
|
|
18
|
+
const flags = {};
|
|
19
|
+
const nameSegments = name.split("."); //Split always returns at least one string
|
|
20
|
+
const typeOverrideMatch = /^(?<enqueuePosition>.+)-(?<typeOverride>script|style|script-module)$|^(?<typeOverride>script|style|script-module)$/.exec(nameSegments[0]);
|
|
21
|
+
if (typeOverrideMatch) {
|
|
22
|
+
nameSegments[0] = typeOverrideMatch.groups?.["enqueuePosition"] ?? "both"; // We override the first segment with the version without the type override
|
|
23
|
+
type = typeOverrideMatch.groups?.["typeOverride"];
|
|
24
|
+
}
|
|
25
|
+
const inlinePattern = /^(?<inline>inline)(?:[-=](?<position>before|after))?$|^strategy[-=](?<inline>inline)(?:-(?<position>before|after))?$/;
|
|
26
|
+
const strategyPattern = /^strategy[-=](?<strategy>eager|lazy|defer|async)$|^(?<strategy>lazy|eager)$/;
|
|
27
|
+
const fetchpriorityPattern = /^fetchpriority[-=](auto|low|high)$/;
|
|
28
|
+
const bothViewAndEditorLocationPattern = /^(?:client-)?(?<both>both)(?:[-=](?<priority>-?\d+))?$/;
|
|
29
|
+
let niceName = undefined;
|
|
30
|
+
for (const segment of nameSegments) {
|
|
31
|
+
const { locationName, priority } = extractLocationFromPropertyEncodingFilenameSegment(segment);
|
|
32
|
+
if (locationName) {
|
|
33
|
+
locations[locationName] = priority;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const lcSegment = segment.toLowerCase();
|
|
37
|
+
const { both, priority: bothPriority } = bothViewAndEditorLocationPattern.exec(lcSegment)?.groups ?? {};
|
|
38
|
+
if (both) {
|
|
39
|
+
const priority = bothPriority !== undefined ? parseInt(bothPriority) : true;
|
|
40
|
+
locations.clientView = priority;
|
|
41
|
+
locations.clientEditor = priority;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const { inline, position: inlinePosition } = (inlinePattern.exec(lcSegment)?.groups ?? {});
|
|
45
|
+
if (inline) {
|
|
46
|
+
flags.inline = true;
|
|
47
|
+
flags.position = inlinePosition;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const strategy = strategyPattern.exec(lcSegment)?.groups?.['strategy']?.toLowerCase();
|
|
51
|
+
if (strategy) {
|
|
52
|
+
flags.strategy = strategy;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const fetchpriority = fetchpriorityPattern.exec(lcSegment)?.[1];
|
|
56
|
+
if (fetchpriority !== undefined) {
|
|
57
|
+
flags.fetchpriority = fetchpriority;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
switch (segment.toLowerCase()) {
|
|
61
|
+
// Loading flags
|
|
62
|
+
case "in-footer":
|
|
63
|
+
case "in_footer":
|
|
64
|
+
flags.in_footer = true;
|
|
65
|
+
break;
|
|
66
|
+
case "in-header":
|
|
67
|
+
case "in_header":
|
|
68
|
+
flags.in_footer = false;
|
|
69
|
+
break;
|
|
70
|
+
default:
|
|
71
|
+
if (niceName === undefined) {
|
|
72
|
+
niceName = segment;
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// This means that it wasn't a location-encoding filename
|
|
78
|
+
if (Object.values(locations).length === 0) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
return { type, locations, flags, niceName };
|
|
82
|
+
}
|
|
83
|
+
function parseLocationEncodingFilenameForBlock(filename, errorBuilder = shared_1.newWebpackErrorForFile) {
|
|
84
|
+
const parsedFilename = parseLocationEncodingFilename(filename);
|
|
85
|
+
if (parsedFilename !== undefined) {
|
|
86
|
+
if ((0, shared_1.constantKeys)(parsedFilename.locations).some(value => value !== 'clientView' && value !== 'clientEditor')) {
|
|
87
|
+
throw errorBuilder(`Block assets cannot be enqueued anywhere other than view, editor, or both. Saw: ${(0, shared_1.constantKeys)(parsedFilename).join(", ")}`, filename);
|
|
88
|
+
}
|
|
89
|
+
if (Object.values(parsedFilename.locations).some(value => typeof value === 'number')) {
|
|
90
|
+
throw errorBuilder(`Block assets cannot be enqueued with a priority`, filename);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return parsedFilename;
|
|
94
|
+
}
|
|
95
|
+
const standardLocationNamesAndPriorityPatternInFilenameSegment = /^(?:(?<view>clientView|client-view|view)|(?<editor>clientEditor|client-editor|editor)|(?<blockAssets>blockAssets|block-assets)|(?<locationName>admin|login|customizer|analytics|register))(?:[-=](?<priority>-?\d+))?$/;
|
|
96
|
+
/**
|
|
97
|
+
* This handles detecting all keys of standardLocationNamesMeta as well as "view", "client-view", "editor", "client-editor", and "block-assets".
|
|
98
|
+
* It MUST be kept in sync with standardLocationNamesMeta
|
|
99
|
+
* @param segment
|
|
100
|
+
*/
|
|
101
|
+
function extractLocationFromPropertyEncodingFilenameSegment(segment) {
|
|
102
|
+
const { view, editor, blockAssets, locationName, priority: rawPriority } = standardLocationNamesAndPriorityPatternInFilenameSegment.exec(segment)
|
|
103
|
+
?.groups ?? {};
|
|
104
|
+
const priority = rawPriority !== undefined ? parseInt(rawPriority) : true;
|
|
105
|
+
if (view) {
|
|
106
|
+
return { locationName: "clientView", priority };
|
|
107
|
+
}
|
|
108
|
+
if (editor) {
|
|
109
|
+
return { locationName: "clientEditor", priority };
|
|
110
|
+
}
|
|
111
|
+
if (blockAssets) {
|
|
112
|
+
return { locationName: "blockAssets", priority };
|
|
113
|
+
}
|
|
114
|
+
if (locationName) {
|
|
115
|
+
return { locationName, priority };
|
|
116
|
+
}
|
|
117
|
+
return { locationName: false };
|
|
118
|
+
}
|