@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/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 type UsageLocations = {
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]: V;
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: string[] | SourcesObject;
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): "style" | "script" | "";
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
- const node_crypto_1 = require("node:crypto");
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>\.(p?c|sa)ss)($|\?)/i;
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, pathQueryParameters]) => {
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, localPathQueryParameters] = (0, path_query_and_related_helpers_1.unpackPotentiallyPrefixedFilePath)(originalValue);
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
- const pathQueryParameters = (0, path_query_and_related_helpers_1.mergeInPathQueryParameters)(absoluteSrc, localPathQueryParameters, dest.pathQueryParameters);
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, pathQueryParameters: undefined } }]);
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
+ }