wxt 0.19.17 → 0.19.18

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.
@@ -99,11 +99,13 @@ export declare class ContentScriptContext implements AbortController {
99
99
  * ctx.addEventListener(document, "visibilitychange", () => {
100
100
  * // ...
101
101
  * });
102
- * ctx.addEventListener(document, "wxt:locationchange", () => {
102
+ * ctx.addEventListener(window, "wxt:locationchange", () => {
103
103
  * // ...
104
104
  * });
105
105
  */
106
- addEventListener<TTarget extends EventTarget, TType extends keyof WxtContentScriptEventMap>(target: TTarget, type: TType, handler: (event: WxtContentScriptEventMap[TType]) => void, options?: AddEventListenerOptions): void;
106
+ addEventListener<TType extends keyof WxtWindowEventMap>(target: Window, type: TType, handler: (event: WxtWindowEventMap[TType]) => void, options?: AddEventListenerOptions): void;
107
+ addEventListener<TType extends keyof DocumentEventMap>(target: Document, type: keyof DocumentEventMap, handler: (event: DocumentEventMap[TType]) => void, options?: AddEventListenerOptions): void;
108
+ addEventListener<TTarget extends EventTarget>(target: TTarget, ...params: Parameters<TTarget['addEventListener']>): void;
107
109
  /**
108
110
  * @internal
109
111
  * Abort the abort controller and execute all `onInvalidated` listeners.
@@ -114,7 +116,6 @@ export declare class ContentScriptContext implements AbortController {
114
116
  ignoreFirstEvent?: boolean;
115
117
  }): void;
116
118
  }
117
- interface WxtContentScriptEventMap extends WindowEventMap {
119
+ export interface WxtWindowEventMap extends WindowEventMap {
118
120
  'wxt:locationchange': WxtLocationChangeEvent;
119
121
  }
120
- export {};
@@ -109,30 +109,12 @@ export class ContentScriptContext {
109
109
  this.onInvalidated(() => cancelIdleCallback(id));
110
110
  return id;
111
111
  }
112
- /**
113
- * Call `target.addEventListener` and remove the event listener when the context is invalidated.
114
- *
115
- * Includes additional events useful for content scripts:
116
- *
117
- * - `"wxt:locationchange"` - Triggered when HTML5 history mode is used to change URL. Content
118
- * scripts are not reloaded when navigating this way, so this can be used to reset the content
119
- * script state on URL change, or run custom code.
120
- *
121
- * @example
122
- * ctx.addEventListener(document, "visibilitychange", () => {
123
- * // ...
124
- * });
125
- * ctx.addEventListener(document, "wxt:locationchange", () => {
126
- * // ...
127
- * });
128
- */
129
112
  addEventListener(target, type, handler, options) {
130
113
  if (type === "wxt:locationchange") {
131
114
  if (this.isValid) this.locationWatcher.run();
132
115
  }
133
116
  target.addEventListener?.(
134
117
  type.startsWith("wxt:") ? getUniqueEventName(type) : type,
135
- // @ts-expect-error: Event don't match, but that's OK, EventTarget doesn't allow custom types in the callback
136
118
  handler,
137
119
  {
138
120
  ...options,
@@ -39,12 +39,7 @@ export async function findEntrypoints() {
39
39
  );
40
40
  if (matchingGlob) {
41
41
  const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
42
- results.push({
43
- name,
44
- inputPath,
45
- type,
46
- skipped: wxt.config.filterEntrypoints != null && !wxt.config.filterEntrypoints.has(name)
47
- });
42
+ results.push({ name, inputPath, type });
48
43
  }
49
44
  return results;
50
45
  }, []);
@@ -52,7 +47,7 @@ export async function findEntrypoints() {
52
47
  preventDuplicateEntrypointNames(entrypointInfos);
53
48
  let hasBackground = false;
54
49
  const env = createExtensionEnvironment();
55
- const entrypoints = await env.run(
50
+ const entrypointsWithoutSkipped = await env.run(
56
51
  () => Promise.all(
57
52
  entrypointInfos.map(async (info) => {
58
53
  const { type } = info;
@@ -97,45 +92,32 @@ export async function findEntrypoints() {
97
92
  )
98
93
  );
99
94
  if (wxt.config.command === "serve" && !hasBackground) {
100
- entrypoints.push(
95
+ entrypointsWithoutSkipped.push(
101
96
  await getBackgroundEntrypoint({
102
97
  inputPath: VIRTUAL_NOOP_BACKGROUND_MODULE_ID,
103
98
  name: "background",
104
- type: "background",
105
- skipped: false
99
+ type: "background"
106
100
  })
107
101
  );
108
102
  }
103
+ const entrypoints = entrypointsWithoutSkipped.map((entry) => ({
104
+ ...entry,
105
+ skipped: isEntrypointSkipped(entry)
106
+ }));
109
107
  wxt.logger.debug("All entrypoints:", entrypoints);
110
- const skippedEntrypointNames = entrypointInfos.filter((item) => item.skipped).map((item) => item.name);
108
+ const skippedEntrypointNames = entrypoints.filter((item) => item.skipped).map((item) => item.name);
111
109
  if (skippedEntrypointNames.length) {
112
110
  wxt.logger.warn(
113
- `Filter excluded the following entrypoints:
114
- ${skippedEntrypointNames.map((item) => `${pc.dim("-")} ${pc.cyan(item)}`).join("\n")}`
111
+ [
112
+ "The following entrypoints have been skipped:",
113
+ ...skippedEntrypointNames.map(
114
+ (item) => `${pc.dim("-")} ${pc.cyan(item)}`
115
+ )
116
+ ].join("\n")
115
117
  );
116
118
  }
117
- const targetEntrypoints = entrypoints.filter((entry) => {
118
- const { include, exclude } = entry.options;
119
- if (include?.length && exclude?.length) {
120
- wxt.logger.warn(
121
- `The ${entry.name} entrypoint lists both include and exclude, but only one can be used per entrypoint. Entrypoint ignored.`
122
- );
123
- return false;
124
- }
125
- if (exclude?.length && !include?.length) {
126
- return !exclude.includes(wxt.config.browser);
127
- }
128
- if (include?.length && !exclude?.length) {
129
- return include.includes(wxt.config.browser);
130
- }
131
- if (skippedEntrypointNames.includes(entry.name)) {
132
- return false;
133
- }
134
- return true;
135
- });
136
- wxt.logger.debug(`${wxt.config.browser} entrypoints:`, targetEntrypoints);
137
- await wxt.hooks.callHook("entrypoints:resolved", wxt, targetEntrypoints);
138
- return targetEntrypoints;
119
+ await wxt.hooks.callHook("entrypoints:resolved", wxt, entrypoints);
120
+ return entrypoints;
139
121
  }
140
122
  function preventDuplicateEntrypointNames(files) {
141
123
  const namesToPaths = files.reduce(
@@ -196,8 +178,7 @@ async function getPopupEntrypoint(info) {
196
178
  name: "popup",
197
179
  options: resolvePerBrowserOptions(options, wxt.config.browser),
198
180
  inputPath: info.inputPath,
199
- outputDir: wxt.config.outDir,
200
- skipped: info.skipped
181
+ outputDir: wxt.config.outDir
201
182
  };
202
183
  }
203
184
  async function getOptionsEntrypoint(info) {
@@ -216,8 +197,7 @@ async function getOptionsEntrypoint(info) {
216
197
  name: "options",
217
198
  options: resolvePerBrowserOptions(options, wxt.config.browser),
218
199
  inputPath: info.inputPath,
219
- outputDir: wxt.config.outDir,
220
- skipped: info.skipped
200
+ outputDir: wxt.config.outDir
221
201
  };
222
202
  }
223
203
  async function getUnlistedPageEntrypoint(info) {
@@ -230,14 +210,12 @@ async function getUnlistedPageEntrypoint(info) {
230
210
  name: info.name,
231
211
  inputPath: info.inputPath,
232
212
  outputDir: wxt.config.outDir,
233
- options,
234
- skipped: info.skipped
213
+ options
235
214
  };
236
215
  }
237
216
  async function getUnlistedScriptEntrypoint({
238
217
  inputPath,
239
- name,
240
- skipped
218
+ name
241
219
  }) {
242
220
  const defaultExport = await wxt.builder.importEntrypoint(inputPath);
243
221
  if (defaultExport == null) {
@@ -251,14 +229,12 @@ async function getUnlistedScriptEntrypoint({
251
229
  name,
252
230
  inputPath,
253
231
  outputDir: wxt.config.outDir,
254
- options: resolvePerBrowserOptions(options, wxt.config.browser),
255
- skipped
232
+ options: resolvePerBrowserOptions(options, wxt.config.browser)
256
233
  };
257
234
  }
258
235
  async function getBackgroundEntrypoint({
259
236
  inputPath,
260
- name,
261
- skipped
237
+ name
262
238
  }) {
263
239
  let options = {};
264
240
  if (inputPath !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
@@ -279,14 +255,12 @@ async function getBackgroundEntrypoint({
279
255
  name,
280
256
  inputPath,
281
257
  outputDir: wxt.config.outDir,
282
- options: resolvePerBrowserOptions(options, wxt.config.browser),
283
- skipped
258
+ options: resolvePerBrowserOptions(options, wxt.config.browser)
284
259
  };
285
260
  }
286
261
  async function getContentScriptEntrypoint({
287
262
  inputPath,
288
- name,
289
- skipped
263
+ name
290
264
  }) {
291
265
  const defaultExport = await wxt.builder.importEntrypoint(inputPath);
292
266
  if (defaultExport == null) {
@@ -305,8 +279,7 @@ async function getContentScriptEntrypoint({
305
279
  name,
306
280
  inputPath,
307
281
  outputDir: resolve(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
308
- options: resolvePerBrowserOptions(options, wxt.config.browser),
309
- skipped
282
+ options: resolvePerBrowserOptions(options, wxt.config.browser)
310
283
  };
311
284
  }
312
285
  async function getSidepanelEntrypoint(info) {
@@ -332,8 +305,7 @@ async function getSidepanelEntrypoint(info) {
332
305
  name: info.name,
333
306
  options: resolvePerBrowserOptions(options, wxt.config.browser),
334
307
  inputPath: info.inputPath,
335
- outputDir: wxt.config.outDir,
336
- skipped: info.skipped
308
+ outputDir: wxt.config.outDir
337
309
  };
338
310
  }
339
311
  async function getHtmlEntrypointOptions(info, keyMap, queries, parsers) {
@@ -357,6 +329,25 @@ async function getHtmlEntrypointOptions(info, keyMap, queries, parsers) {
357
329
  });
358
330
  return options;
359
331
  }
332
+ function isEntrypointSkipped(entry) {
333
+ if (wxt.config.filterEntrypoints != null) {
334
+ return !wxt.config.filterEntrypoints.has(entry.name);
335
+ }
336
+ const { include, exclude } = entry.options;
337
+ if (include?.length && exclude?.length) {
338
+ wxt.logger.warn(
339
+ `The ${entry.name} entrypoint lists both include and exclude, but only one can be used per entrypoint. Entrypoint skipped.`
340
+ );
341
+ return true;
342
+ }
343
+ if (exclude?.length && !include?.length) {
344
+ return exclude.includes(wxt.config.browser);
345
+ }
346
+ if (include?.length && !exclude?.length) {
347
+ return !include.includes(wxt.config.browser);
348
+ }
349
+ return false;
350
+ }
360
351
  const PATH_GLOB_TO_TYPE_MAP = {
361
352
  "sandbox.html": "sandbox",
362
353
  "sandbox/index.html": "sandbox",
@@ -1,7 +1,7 @@
1
1
  import { Entrypoint, EntrypointGroup } from '../../../types';
2
2
  /**
3
- * Entrypoints can be build in groups. HTML pages can all be built together in a single step, while
4
- * content scripts must be build individually.
3
+ * Entrypoints are built in groups. HTML pages can all be built together in a single step,
4
+ * content scripts must be build individually, etc.
5
5
  *
6
6
  * This function returns the entrypoints put into these types of groups.
7
7
  */
@@ -2,6 +2,7 @@ export function groupEntrypoints(entrypoints) {
2
2
  const groupIndexMap = {};
3
3
  const groups = [];
4
4
  for (const entry of entrypoints) {
5
+ if (entry.skipped) continue;
5
6
  let group = ENTRY_TYPE_TO_GROUP_MAP[entry.type];
6
7
  if (entry.type === "background" && entry.options.type === "module") {
7
8
  group = "esm";
@@ -45,9 +45,13 @@ export async function generateManifest(entrypoints, buildOutput) {
45
45
  baseManifest
46
46
  );
47
47
  if (wxt.config.command === "serve" && wxt.config.dev.reloadCommand) {
48
- if (manifest.commands && Object.keys(manifest.commands).length >= 4) {
48
+ if (manifest.commands && // If the following limit is exceeded, Chrome will fail to load the extension.
49
+ // Error: "Too many commands specified for 'commands': The maximum is 4."
50
+ Object.values(manifest.commands).filter(
51
+ (command) => command.suggested_key
52
+ ).length >= 4) {
49
53
  warnings.push([
50
- "Extension already has 4 registered commands, WXT's reload command is disabled"
54
+ "Extension already has 4 registered commands with suggested keys, WXT's reload command is disabled"
51
55
  ]);
52
56
  } else {
53
57
  manifest.commands ??= {};
@@ -1,4 +1,4 @@
1
- import { type Manifest } from 'wxt/browser';
1
+ import type { Manifest } from 'wxt/browser';
2
2
  import { ResolvedConfig, WxtDevServer, BackgroundEntrypoint, ContentScriptEntrypoint, GenericEntrypoint, OptionsEntrypoint, PopupEntrypoint, OutputChunk, OutputFile, OutputAsset, BuildOutput, BuildStepOutput, UserManifest, Wxt, SidepanelEntrypoint } from '../../../types';
3
3
  type DeepPartial<T> = T extends object ? {
4
4
  [P in keyof T]?: DeepPartial<T[P]>;
@@ -8781,7 +8781,7 @@ export declare const fakeBuildStepOutput: (overrides?: {
8781
8781
  moduleIds?: (string | undefined)[] | undefined;
8782
8782
  } | undefined)[] | undefined;
8783
8783
  } | undefined) => BuildStepOutput;
8784
- export declare const fakeManifestCommand: (overrides?: any) => Commands.Command;
8784
+ export declare const fakeManifestCommand: (overrides?: any) => Manifest.WebExtensionManifestCommandsType;
8785
8785
  export declare const fakeDevServer: (overrides?: {
8786
8786
  currentOutput?: {
8787
8787
  manifest?: any;
@@ -301,10 +301,14 @@ export const fakeBuildStepOutput = fakeObjectCreator(() => ({
301
301
  }));
302
302
  export const fakeManifestCommand = fakeObjectCreator(() => ({
303
303
  description: faker.string.sample(),
304
- shortcut: `${faker.helpers.arrayElement(["ctrl", "alt"])}+${faker.number.int({
305
- min: 0,
306
- max: 9
307
- })}`
304
+ suggested_key: {
305
+ default: `${faker.helpers.arrayElement(["ctrl", "alt"])}+${faker.number.int(
306
+ {
307
+ min: 0,
308
+ max: 9
309
+ }
310
+ )}`
311
+ }
308
312
  }));
309
313
  export const fakeDevServer = fakeObjectCreator(() => ({
310
314
  hostname: "localhost",
package/dist/types.d.ts CHANGED
@@ -44,6 +44,7 @@ export interface InlineConfig {
44
44
  * A list of entrypoint names (`"popup"`, `"options"`, etc.) to build. Will speed up the build if
45
45
  * your extension has lots of entrypoints, and you don't need to build all of them to develop a
46
46
  * feature.
47
+ * If specified, this completely overrides the `include`/`exclude` option provided per-entrypoint.
47
48
  */
48
49
  filterEntrypoints?: string[];
49
50
  /**
@@ -682,7 +683,14 @@ export interface BaseEntrypoint {
682
683
  * subdirectory of it.
683
684
  */
684
685
  outputDir: string;
685
- skipped: boolean;
686
+ /**
687
+ * When true, the entrypoint will not be built by WXT. Normally this is set
688
+ * based on the `filterEntrypoints` config or the entrypoint's
689
+ * `include`/`exclude` options defined inside the file.
690
+ *
691
+ * See https://wxt.dev/guide/essentials/target-different-browsers.html#filtering-entrypoints
692
+ */
693
+ skipped?: boolean;
686
694
  }
687
695
  export interface GenericEntrypoint extends BaseEntrypoint {
688
696
  type: 'sandbox' | 'bookmarks' | 'history' | 'newtab' | 'devtools' | 'unlisted-page' | 'unlisted-script' | 'unlisted-style' | 'content-script-style';
package/dist/version.mjs CHANGED
@@ -1 +1 @@
1
- export const version = "0.19.17";
1
+ export const version = "0.19.18";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wxt",
3
3
  "type": "module",
4
- "version": "0.19.17",
4
+ "version": "0.19.18",
5
5
  "description": "Next gen framework for developing web extensions",
6
6
  "repository": {
7
7
  "type": "git",