wxt 0.20.14 → 0.20.15

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.
Files changed (47) hide show
  1. package/dist/builtin-modules/unimport.mjs +1 -1
  2. package/dist/cli/cli-utils.mjs +3 -1
  3. package/dist/cli/commands.mjs +1 -0
  4. package/dist/core/builders/vite/index.mjs +4 -3
  5. package/dist/core/builders/vite/plugins/devHtmlPrerender.mjs +1 -0
  6. package/dist/core/builders/vite/plugins/download.mjs +2 -2
  7. package/dist/core/builders/vite/plugins/removeEntrypointMainFunction.mjs +1 -0
  8. package/dist/core/builders/vite/plugins/resolveAppConfig.mjs +2 -2
  9. package/dist/core/builders/vite/plugins/resolveVirtualModules.mjs +1 -0
  10. package/dist/core/builders/vite/plugins/wxtPluginLoader.mjs +1 -0
  11. package/dist/core/create-server.mjs +2 -2
  12. package/dist/core/generate-wxt-dir.mjs +2 -1
  13. package/dist/core/index.d.mts +2 -1
  14. package/dist/core/index.mjs +2 -0
  15. package/dist/core/resolve-config.mjs +4 -4
  16. package/dist/core/runners/index.mjs +5 -5
  17. package/dist/core/runners/manual.mjs +3 -6
  18. package/dist/core/runners/safari.mjs +3 -6
  19. package/dist/core/runners/web-ext.mjs +1 -1
  20. package/dist/core/runners/wsl.mjs +3 -6
  21. package/dist/core/utils/building/find-entrypoints.mjs +11 -8
  22. package/dist/core/utils/building/internal-build.mjs +4 -5
  23. package/dist/core/utils/eslint.mjs +1 -1
  24. package/dist/core/utils/fs.mjs +1 -1
  25. package/dist/core/utils/index.mjs +3 -0
  26. package/dist/core/utils/log/printHeader.mjs +1 -2
  27. package/dist/core/utils/manifest.mjs +8 -6
  28. package/dist/core/utils/network.mjs +1 -4
  29. package/dist/core/utils/paths.d.mts +8 -0
  30. package/dist/core/utils/paths.mjs +2 -2
  31. package/dist/core/utils/wsl.mjs +4 -3
  32. package/dist/core/wxt.mjs +1 -2
  33. package/dist/core/zip.mjs +2 -0
  34. package/dist/index.d.mts +3 -2
  35. package/dist/index.mjs +2 -1
  36. package/dist/modules.d.mts +1 -1
  37. package/dist/modules.mjs +1 -3
  38. package/dist/types.d.mts +26 -4
  39. package/dist/utils/content-script-context.d.mts +3 -6
  40. package/dist/utils/content-script-context.mjs +17 -22
  41. package/dist/utils/content-script-ui/iframe.mjs +1 -1
  42. package/dist/utils/content-script-ui/integrated.mjs +1 -1
  43. package/dist/utils/content-script-ui/shared.mjs +2 -4
  44. package/dist/version.mjs +1 -1
  45. package/dist/virtual/background-entrypoint.mjs +0 -3
  46. package/dist/virtual/reload-html.mjs +0 -3
  47. package/package.json +10 -2
@@ -25,7 +25,7 @@ var unimport_default = defineWxtModule({
25
25
  entries.push(await getImportsModuleEntry(wxt, unimport));
26
26
  if (!isEnabled()) return;
27
27
  entries.push(await getImportsDeclarationEntry(unimport));
28
- if (wxt.config.imports.eslintrc.enabled === false) return;
28
+ if (!wxt.config.imports.eslintrc.enabled) return;
29
29
  entries.push(await getEslintConfigEntry(unimport, wxt.config.imports.eslintrc.enabled, wxt.config.imports));
30
30
  });
31
31
  addViteConfig(wxt, () => ({ plugins: [UnimportPlugin.vite(wxt.config.imports)] }));
@@ -13,6 +13,8 @@ import spawn from "nano-spawn";
13
13
  */
14
14
  function wrapAction(cb, options) {
15
15
  return async (...args) => {
16
+ const level = args.find((arg) => arg?.level)?.level;
17
+ if (level && Object.keys(LogLevels).includes(level)) consola.level = LogLevels[level];
16
18
  if (!!args.find((arg) => arg?.debug)) consola.level = LogLevels.debug;
17
19
  const startTime = Date.now();
18
20
  try {
@@ -20,7 +22,7 @@ function wrapAction(cb, options) {
20
22
  if (!(await cb(...args))?.isOngoing && !options?.disableFinishedLog) consola.success(`Finished in ${formatDuration(Date.now() - startTime)}`);
21
23
  } catch (err) {
22
24
  consola.fail(`Command failed after ${formatDuration(Date.now() - startTime)}`);
23
- if (err instanceof ValidationError) {} else consola.error(err);
25
+ if (!(err instanceof ValidationError)) consola.error(err);
24
26
  process.exit(1);
25
27
  }
26
28
  };
@@ -11,6 +11,7 @@ import cac from "cac";
11
11
  //#region src/cli/commands.ts
12
12
  const cli = cac("wxt");
13
13
  cli.option("--debug", "enable debug mode");
14
+ cli.option("--level <level>", "specify log level (\"silent\" | \"fatal\" | \"error\" | \"warn\" | \"log\" | \"info\" | \"success\" | \"fail\" | \"ready\" | \"start\" | \"box\" | \"debug\" | \"trace\" | \"verbose\")");
14
15
  cli.command("[root]", "start dev server").option("-c, --config <file>", "use specified config file").option("-m, --mode <mode>", "set env mode").option("-b, --browser <browser>", "specify a browser").option("--host <host>", "specify a host for the dev server to bind to").option("-p, --port <port>", "specify a port for the dev server to bind to").option("-e, --filter-entrypoint <entrypoint>", "only build specific entrypoints", { type: [] }).option("--mv3", "target manifest v3").option("--mv2", "target manifest v2").action(wrapAction(async (root, flags) => {
15
16
  const serverOptions = {};
16
17
  if (flags.host) serverOptions.host = flags.host;
@@ -1,4 +1,5 @@
1
1
  import { normalizePath } from "../../utils/paths.mjs";
2
+ import "../../utils/index.mjs";
2
3
  import { getEntrypointBundlePath, isHtmlEntrypoint } from "../../utils/entrypoints.mjs";
3
4
  import { devHtmlPrerender } from "./plugins/devHtmlPrerender.mjs";
4
5
  import { devServerGlobals } from "./plugins/devServerGlobals.mjs";
@@ -77,8 +78,8 @@ async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
77
78
  },
78
79
  rollupOptions: { output: {
79
80
  entryFileNames: getEntrypointBundlePath(entrypoint, wxtConfig.outDir, ".js"),
80
- assetFileNames: ({ name }) => {
81
- if (entrypoint.type === "content-script" && name?.endsWith("css")) return `content-scripts/${entrypoint.name}.[ext]`;
81
+ assetFileNames: ({ names }) => {
82
+ if (entrypoint.type === "content-script" && names[0].endsWith("css")) return `content-scripts/${entrypoint.name}.[ext]`;
82
83
  else return `assets/${entrypoint.name}.[ext]`;
83
84
  }
84
85
  } }
@@ -284,7 +285,7 @@ async function moveHtmlFiles(config, group, chunks) {
284
285
  fileName: newBundlePath
285
286
  };
286
287
  }));
287
- removeEmptyDirs(config.outDir);
288
+ await removeEmptyDirs(config.outDir);
288
289
  return movedChunks;
289
290
  }
290
291
  /**
@@ -1,4 +1,5 @@
1
1
  import { normalizePath } from "../../../utils/paths.mjs";
2
+ import "../../../utils/index.mjs";
2
3
  import { getEntrypointName } from "../../../utils/entrypoints.mjs";
3
4
  import { dirname, relative, resolve } from "node:path";
4
5
  import { parseHTML } from "linkedom";
@@ -14,9 +14,9 @@ function download(config) {
14
14
  resolveId(id) {
15
15
  if (id.startsWith("url:")) return "\0" + id;
16
16
  },
17
- async load(id) {
17
+ load(id) {
18
18
  if (!id.startsWith("\0url:")) return;
19
- return await fetchCached(id.replace("\0url:", ""), config);
19
+ return fetchCached(id.replace("\0url:", ""), config);
20
20
  }
21
21
  };
22
22
  }
@@ -1,4 +1,5 @@
1
1
  import { normalizePath } from "../../../utils/paths.mjs";
2
+ import "../../../utils/index.mjs";
2
3
  import { removeMainFunctionCode } from "../../../utils/transform.mjs";
3
4
  import { resolve } from "node:path";
4
5
 
@@ -1,4 +1,4 @@
1
- import { exists } from "fs-extra";
1
+ import { pathExists } from "fs-extra";
2
2
  import { resolve } from "node:path";
3
3
 
4
4
  //#region src/core/builders/vite/plugins/resolveAppConfig.ts
@@ -16,7 +16,7 @@ function resolveAppConfig(config) {
16
16
  },
17
17
  async resolveId(id) {
18
18
  if (id !== virtualModuleId) return;
19
- return await exists(appConfigFile) ? appConfigFile : resolvedVirtualModuleId;
19
+ return await pathExists(appConfigFile) ? appConfigFile : resolvedVirtualModuleId;
20
20
  },
21
21
  load(id) {
22
22
  if (id === resolvedVirtualModuleId) return `export default {}`;
@@ -1,4 +1,5 @@
1
1
  import { normalizePath } from "../../../utils/paths.mjs";
2
+ import "../../../utils/index.mjs";
2
3
  import { virtualModuleNames } from "../../../utils/virtual-modules.mjs";
3
4
  import fs from "fs-extra";
4
5
  import { resolve } from "path";
@@ -1,4 +1,5 @@
1
1
  import { normalizePath } from "../../../utils/paths.mjs";
2
+ import "../../../utils/index.mjs";
2
3
  import { parseHTML } from "linkedom";
3
4
 
4
5
  //#region src/core/builders/vite/plugins/wxtPluginLoader.ts
@@ -87,7 +87,7 @@ async function createServerInternal() {
87
87
  async stop() {
88
88
  wasStopped = true;
89
89
  keyboardShortcuts.stop();
90
- await runner.closeBrowser();
90
+ await runner.closeBrowser?.();
91
91
  await builderServer.close();
92
92
  await wxt.hooks.callHook("server:closed", wxt, server);
93
93
  deinitWxtModules();
@@ -110,7 +110,7 @@ async function createServerInternal() {
110
110
  server.ws.send("wxt:reload-extension");
111
111
  },
112
112
  async restartBrowser() {
113
- await runner.closeBrowser();
113
+ await runner.closeBrowser?.();
114
114
  keyboardShortcuts.stop();
115
115
  await wxt.reloadConfig();
116
116
  runner = await createExtensionRunner();
@@ -1,4 +1,5 @@
1
1
  import { normalizePath } from "./utils/paths.mjs";
2
+ import "./utils/index.mjs";
2
3
  import { getEntrypointBundlePath, isHtmlEntrypoint } from "./utils/entrypoints.mjs";
3
4
  import { getEntrypointGlobals, getGlobals } from "./utils/globals.mjs";
4
5
  import { wxt } from "./wxt.mjs";
@@ -81,7 +82,7 @@ declare module "wxt/browser" {
81
82
  `;
82
83
  const defaultLocalePath = path.resolve(wxt.config.publicDir, "_locales", defaultLocale ?? "", "messages.json");
83
84
  let messages;
84
- if (await fs.exists(defaultLocalePath)) messages = parseI18nMessages(JSON.parse(await fs.readFile(defaultLocalePath, "utf-8")));
85
+ if (await fs.pathExists(defaultLocalePath)) messages = parseI18nMessages(JSON.parse(await fs.readFile(defaultLocalePath, "utf-8")));
85
86
  else messages = parseI18nMessages({});
86
87
  const renderGetMessageOverload = (keyType, description, translation) => {
87
88
  const commentLines = [];
@@ -5,4 +5,5 @@ import { defineRunnerConfig, defineWebExtConfig } from "./define-web-ext-config.
5
5
  import { createServer } from "./create-server.mjs";
6
6
  import { initialize } from "./initialize.mjs";
7
7
  import { prepare } from "./prepare.mjs";
8
- import { zip } from "./zip.mjs";
8
+ import { zip } from "./zip.mjs";
9
+ import { normalizePath } from "./utils/paths.mjs";
@@ -1,3 +1,5 @@
1
+ import { normalizePath } from "./utils/paths.mjs";
2
+ import "./utils/index.mjs";
1
3
  import { build } from "./build.mjs";
2
4
  import { clean } from "./clean.mjs";
3
5
  import { defineConfig } from "./define-config.mjs";
@@ -1,5 +1,6 @@
1
1
  import { normalizePath } from "./utils/paths.mjs";
2
2
  import { createFsCache } from "./utils/cache.mjs";
3
+ import "./utils/index.mjs";
3
4
  import { builtinModules } from "../builtin-modules/index.mjs";
4
5
  import { getEslintVersion } from "./utils/eslint.mjs";
5
6
  import { safeStringToNumber } from "./utils/number.mjs";
@@ -355,11 +356,11 @@ async function getUnimportEslintOptions(wxtDir, options) {
355
356
  * Returns the path to `node_modules/wxt`.
356
357
  */
357
358
  function resolveWxtModuleDir() {
358
- const url = resolve$1("wxt", typeof __filename === "string" ? pathToFileURL(__filename).href : import.meta.url);
359
+ const url = resolve$1("wxt", import.meta.url);
359
360
  return path.resolve(fileURLToPath(url), "../..");
360
361
  }
361
362
  async function isDirMissing(dir) {
362
- return !await fs.exists(dir);
363
+ return !await fs.pathExists(dir);
363
364
  }
364
365
  function logMissingDir(logger, name, expected) {
365
366
  logger.warn(`${name} directory not found: ./${normalizePath(path.relative(process.cwd(), expected))}`);
@@ -376,8 +377,7 @@ async function mergeBuilderConfig(logger, inlineConfig, userConfig) {
376
377
  logger.debug("Failed to import vite:", err);
377
378
  });
378
379
  if (vite) return { vite: async (env) => {
379
- const resolvedInlineConfig = await inlineConfig.vite?.(env) ?? {};
380
- const resolvedUserConfig = await userConfig.vite?.(env) ?? {};
380
+ const [resolvedInlineConfig = {}, resolvedUserConfig = {}] = await Promise.all([inlineConfig.vite?.(env), userConfig.vite?.(env)]);
381
381
  return vite.mergeConfig(resolvedUserConfig, resolvedInlineConfig);
382
382
  } };
383
383
  throw Error("Builder not found. Make sure vite is installed.");
@@ -1,14 +1,14 @@
1
1
  import { wxt } from "../wxt.mjs";
2
- import { createWslRunner } from "./wsl.mjs";
3
- import { createWebExtRunner } from "./web-ext.mjs";
4
- import { createSafariRunner } from "./safari.mjs";
5
- import { createManualRunner } from "./manual.mjs";
6
2
  import { isWsl } from "../utils/wsl.mjs";
3
+ import { createManualRunner } from "./manual.mjs";
4
+ import { createSafariRunner } from "./safari.mjs";
5
+ import { createWebExtRunner } from "./web-ext.mjs";
6
+ import { createWslRunner } from "./wsl.mjs";
7
7
 
8
8
  //#region src/core/runners/index.ts
9
9
  async function createExtensionRunner() {
10
10
  if (wxt.config.browser === "safari") return createSafariRunner();
11
- if (await isWsl()) return createWslRunner();
11
+ if (isWsl()) return createWslRunner();
12
12
  if (wxt.config.runnerConfig.config?.disabled) return createManualRunner();
13
13
  return createWebExtRunner();
14
14
  }
@@ -6,12 +6,9 @@ import { relative } from "node:path";
6
6
  * The manual runner tells the user to load the unpacked extension manually.
7
7
  */
8
8
  function createManualRunner() {
9
- return {
10
- async openBrowser() {
11
- wxt.logger.info(`Load "${relative(process.cwd(), wxt.config.outDir)}" as an unpacked extension manually`);
12
- },
13
- async closeBrowser() {}
14
- };
9
+ return { async openBrowser() {
10
+ wxt.logger.info(`Load "${relative(process.cwd(), wxt.config.outDir)}" as an unpacked extension manually`);
11
+ } };
15
12
  }
16
13
 
17
14
  //#endregion
@@ -6,12 +6,9 @@ import { relative } from "node:path";
6
6
  * The Safari runner just logs a warning message because `web-ext` doesn't work with Safari.
7
7
  */
8
8
  function createSafariRunner() {
9
- return {
10
- async openBrowser() {
11
- wxt.logger.warn(`Cannot Safari using web-ext. Load "${relative(process.cwd(), wxt.config.outDir)}" as an unpacked extension manually`);
12
- },
13
- async closeBrowser() {}
14
- };
9
+ return { async openBrowser() {
10
+ wxt.logger.warn(`Cannot Safari using web-ext. Load "${relative(process.cwd(), wxt.config.outDir)}" as an unpacked extension manually`);
11
+ } };
15
12
  }
16
13
 
17
14
  //#endregion
@@ -52,7 +52,7 @@ function createWebExtRunner() {
52
52
  wxt.logger.success(`Opened browser in ${formatDuration(duration)}`);
53
53
  },
54
54
  async closeBrowser() {
55
- return await runner?.exit();
55
+ await runner?.exit();
56
56
  }
57
57
  };
58
58
  }
@@ -6,12 +6,9 @@ import { relative } from "node:path";
6
6
  * The WSL runner just logs a warning message because `web-ext` doesn't work in WSL.
7
7
  */
8
8
  function createWslRunner() {
9
- return {
10
- async openBrowser() {
11
- wxt.logger.warn(`Cannot open browser when using WSL. Load "${relative(process.cwd(), wxt.config.outDir)}" as an unpacked extension manually`);
12
- },
13
- async closeBrowser() {}
14
- };
9
+ return { async openBrowser() {
10
+ wxt.logger.warn(`Cannot open browser when using WSL. Load "${relative(process.cwd(), wxt.config.outDir)}" as an unpacked extension manually`);
11
+ } };
15
12
  }
16
13
 
17
14
  //#endregion
@@ -41,8 +41,7 @@ async function findEntrypoints() {
41
41
  }, []).filter(({ name, inputPath }, _, entrypointInfos) => {
42
42
  if (inputPath.endsWith(".html")) return true;
43
43
  if (!/index\..+$/.test(inputPath)) return true;
44
- if (entrypointInfos.some((entry) => entry.name === name && entry.inputPath.endsWith("index.html"))) return false;
45
- return true;
44
+ return !entrypointInfos.some((entry) => entry.name === name && entry.inputPath.endsWith("index.html"));
46
45
  });
47
46
  await wxt.hooks.callHook("entrypoints:found", wxt, entrypointInfos);
48
47
  preventNoEntrypoints(entrypointInfos);
@@ -103,8 +102,7 @@ async function importEntrypoints(infos) {
103
102
  const htmlInfos = infos.filter((info) => isHtmlEntrypoint(info));
104
103
  const jsInfos = infos.filter((info) => isJsEntrypoint(info));
105
104
  await Promise.all([...htmlInfos.map(async (info) => {
106
- const res = await importHtmlEntrypoint(info);
107
- resMap[info.inputPath] = res;
105
+ resMap[info.inputPath] = await importHtmlEntrypoint(info);
108
106
  }), (async () => {
109
107
  (await wxt.builder.importEntrypoints(jsInfos.map((info) => info.inputPath))).forEach((res, i) => {
110
108
  resMap[jsInfos[i].inputPath] = res;
@@ -153,19 +151,24 @@ function preventNoEntrypoints(files) {
153
151
  if (files.length === 0) throw Error(`No entrypoints found in ${wxt.config.entrypointsDir}`);
154
152
  }
155
153
  async function getPopupEntrypoint(info, options) {
156
- const stictOptions = resolvePerBrowserOptions({
154
+ const strictOptions = resolvePerBrowserOptions({
157
155
  browserStyle: options.browserStyle,
158
156
  exclude: options.exclude,
159
157
  include: options.include,
160
158
  defaultIcon: options.defaultIcon,
161
159
  defaultTitle: options.title,
162
- mv2Key: options.type
160
+ mv2Key: options.type,
161
+ defaultArea: options.defaultArea
163
162
  }, wxt.config.browser);
164
- if (stictOptions.mv2Key && stictOptions.mv2Key !== "page_action") stictOptions.mv2Key = "browser_action";
163
+ if (strictOptions.mv2Key && strictOptions.mv2Key !== "page_action") strictOptions.mv2Key = "browser_action";
164
+ const themeIcons = options.themeIcons;
165
165
  return {
166
166
  type: "popup",
167
167
  name: "popup",
168
- options: stictOptions,
168
+ options: {
169
+ ...strictOptions,
170
+ themeIcons
171
+ },
169
172
  inputPath: info.inputPath,
170
173
  outputDir: wxt.config.outDir
171
174
  };
@@ -55,7 +55,7 @@ async function internalBuild() {
55
55
  else {
56
56
  wxt.logger.info(`Opening ${pc.yellow(statsPath)} in browser...`);
57
57
  const { default: open } = await import("open");
58
- open(wxt.config.analysis.outputFile);
58
+ await open(wxt.config.analysis.outputFile);
59
59
  }
60
60
  }
61
61
  return output;
@@ -82,12 +82,11 @@ function printValidationResults({ errorCount, errors, warningCount }) {
82
82
  return map;
83
83
  }, /* @__PURE__ */ new Map());
84
84
  Array.from(entrypointErrors.entries()).forEach(([entrypoint, errors]) => {
85
- wxt.logger.log(relative(cwd, entrypoint.inputPath));
86
- console.log();
85
+ wxt.logger.log(relative(cwd, entrypoint.inputPath) + "\n");
87
86
  errors.forEach((err) => {
88
87
  const type = err.type === "error" ? pc.red("ERROR") : pc.yellow("WARN");
89
- const recieved = pc.dim(`(recieved: ${JSON.stringify(err.value)})`);
90
- wxt.logger.log(` - ${type} ${err.message} ${recieved}`);
88
+ const received = pc.dim(`(received: ${JSON.stringify(err.value)})`);
89
+ wxt.logger.log(` - ${type} ${err.message} ${received}`);
91
90
  });
92
91
  console.log();
93
92
  });
@@ -1,7 +1,7 @@
1
1
  //#region src/core/utils/eslint.ts
2
2
  async function getEslintVersion() {
3
3
  try {
4
- const { ESLint } = (await import("node:module")).default.createRequire(import.meta.url)("eslint");
4
+ const { ESLint } = await import("eslint");
5
5
  return ESLint.version?.split(".") ?? [];
6
6
  } catch {
7
7
  return [];
@@ -19,7 +19,7 @@ async function writeFileIfDifferent(file, newContents) {
19
19
  * `config.publicDir`.
20
20
  */
21
21
  async function getPublicFiles() {
22
- if (!await fs.exists(wxt.config.publicDir)) return [];
22
+ if (!await fs.pathExists(wxt.config.publicDir)) return [];
23
23
  return (await glob("**/*", { cwd: wxt.config.publicDir })).map(unnormalizePath);
24
24
  }
25
25
 
@@ -0,0 +1,3 @@
1
+ import { normalizePath } from "./paths.mjs";
2
+
3
+ export { };
@@ -4,8 +4,7 @@ import pc from "picocolors";
4
4
 
5
5
  //#region src/core/utils/log/printHeader.ts
6
6
  function printHeader() {
7
- console.log();
8
- consola$1.log(`${pc.gray("WXT")} ${pc.gray(pc.bold(version))}`);
7
+ consola$1.log(`\n${pc.gray("WXT")} ${pc.gray(pc.bold(version))}`);
9
8
  }
10
9
 
11
10
  //#endregion
@@ -138,6 +138,8 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
138
138
  if (popup.options.defaultIcon) options.default_icon = popup.options.defaultIcon;
139
139
  if (popup.options.defaultTitle) options.default_title = popup.options.defaultTitle;
140
140
  if (popup.options.browserStyle) options.browser_style = popup.options.browserStyle;
141
+ if (popup.options.defaultArea) options.default_area = popup.options.defaultArea;
142
+ if (popup.options.themeIcons) options.theme_icons = popup.options.themeIcons;
141
143
  if (manifest.manifest_version === 3) manifest.action = {
142
144
  ...manifest.action,
143
145
  ...options,
@@ -237,13 +239,13 @@ function discoverIcons(buildOutput) {
237
239
  return icons.length > 0 ? Object.fromEntries(icons) : void 0;
238
240
  }
239
241
  function addDevModeCsp(manifest) {
240
- let permissonUrl = wxt.server?.origin;
241
- if (permissonUrl) {
242
- const permissionUrlInstance = new URL(permissonUrl);
242
+ let permissionUrl = wxt.server?.origin;
243
+ if (permissionUrl) {
244
+ const permissionUrlInstance = new URL(permissionUrl);
243
245
  permissionUrlInstance.port = "";
244
- permissonUrl = permissionUrlInstance.toString();
246
+ permissionUrl = permissionUrlInstance.toString();
245
247
  }
246
- const permission = `${permissonUrl}*`;
248
+ const permission = `${permissionUrl}*`;
247
249
  const allowedCsp = wxt.server?.origin ?? "http://localhost:*";
248
250
  if (manifest.manifest_version === 3) addHostPermission(manifest, permission);
249
251
  else addPermission(manifest, permission);
@@ -353,7 +355,7 @@ function convertCspToMv2(manifest) {
353
355
  manifest.content_security_policy = manifest.content_security_policy.extension_pages;
354
356
  }
355
357
  /**
356
- * Make sure all resources are in MV3 format. If not, add a wanring
358
+ * Make sure all resources are in MV3 format. If not, add a warning.
357
359
  */
358
360
  function validateMv3WebAccessibleResources(manifest) {
359
361
  if (manifest.web_accessible_resources == null) return;
@@ -4,10 +4,7 @@ import dns from "node:dns";
4
4
  //#region src/core/utils/network.ts
5
5
  function isOffline() {
6
6
  return withTimeout(new Promise((res) => {
7
- dns.resolve("google.com", (err) => {
8
- if (err == null) res(false);
9
- else res(true);
10
- });
7
+ dns.resolve("google.com", (err) => res(err != null));
11
8
  }), 1e3).catch(() => true);
12
9
  }
13
10
  async function isOnline() {
@@ -0,0 +1,8 @@
1
+ //#region src/core/utils/paths.d.ts
2
+ /**
3
+ * Converts system paths to normalized bundler path.
4
+ * On Windows, this returns paths with `/` instead of `\`.
5
+ */
6
+ declare function normalizePath(path: string): string;
7
+ //#endregion
8
+ export { normalizePath };
@@ -3,8 +3,8 @@ import normalize from "normalize-path";
3
3
 
4
4
  //#region src/core/utils/paths.ts
5
5
  /**
6
- * Converts system paths to normalized bundler path. On windows and unix, this returns paths with /
7
- * instead of \.
6
+ * Converts system paths to normalized bundler path.
7
+ * On Windows, this returns paths with `/` instead of `\`.
8
8
  */
9
9
  function normalizePath(path) {
10
10
  return normalize(path);
@@ -1,10 +1,11 @@
1
+ import isWsl_ from "is-wsl";
2
+
1
3
  //#region src/core/utils/wsl.ts
2
4
  /**
3
5
  * Returns true when running on WSL or WSL2.
4
6
  */
5
- async function isWsl() {
6
- const { default: isWsl } = await import("is-wsl");
7
- return isWsl;
7
+ function isWsl() {
8
+ return isWsl_;
8
9
  }
9
10
 
10
11
  //#endregion
package/dist/core/wxt.mjs CHANGED
@@ -18,8 +18,7 @@ async function registerWxt(command, inlineConfig = {}) {
18
18
  process.env.NODE_ENV ??= inlineConfig.mode ?? (command === "serve" ? "development" : "production");
19
19
  const hooks = createHooks();
20
20
  const config = await resolveConfig(inlineConfig, command);
21
- const builder = await createViteBuilder(config, hooks, () => wxt.server);
22
- const pm = await createWxtPackageManager(config.root);
21
+ const [builder, pm] = await Promise.all([createViteBuilder(config, hooks, () => wxt.server), createWxtPackageManager(config.root)]);
23
22
  wxt = {
24
23
  config,
25
24
  hooks,
package/dist/core/zip.mjs CHANGED
@@ -1,9 +1,11 @@
1
1
  import { normalizePath } from "./utils/paths.mjs";
2
+ import "./utils/index.mjs";
2
3
  import { formatDuration } from "./utils/time.mjs";
3
4
  import { safeFilename } from "./utils/strings.mjs";
4
5
  import { registerWxt, wxt } from "./wxt.mjs";
5
6
  import { findEntrypoints } from "./utils/building/find-entrypoints.mjs";
6
7
  import { printFileList } from "./utils/log/printFileList.mjs";
8
+ import "./utils/log/index.mjs";
7
9
  import { getPackageJson } from "./utils/package.mjs";
8
10
  import { internalBuild } from "./utils/building/internal-build.mjs";
9
11
  import "./utils/building/index.mjs";
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, UnlistedScriptDefinition, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig } from "./types.mjs";
1
+ import { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig } from "./types.mjs";
2
2
  import { build } from "./core/build.mjs";
3
3
  import { clean } from "./core/clean.mjs";
4
4
  import { defineConfig } from "./core/define-config.mjs";
@@ -7,6 +7,7 @@ import { createServer } from "./core/create-server.mjs";
7
7
  import { initialize } from "./core/initialize.mjs";
8
8
  import { prepare } from "./core/prepare.mjs";
9
9
  import { zip } from "./core/zip.mjs";
10
+ import { normalizePath } from "./core/utils/paths.mjs";
10
11
  import "./core/index.mjs";
11
12
  import { version } from "./version.mjs";
12
- export { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, UnlistedScriptDefinition, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig, build, clean, createServer, defineConfig, defineRunnerConfig, defineWebExtConfig, initialize, prepare, version, zip };
13
+ export { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig, build, clean, createServer, defineConfig, defineRunnerConfig, defineWebExtConfig, initialize, normalizePath, prepare, version, zip };
package/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { normalizePath } from "./core/utils/paths.mjs";
1
2
  import { version } from "./version.mjs";
2
3
  import { build } from "./core/build.mjs";
3
4
  import { clean } from "./core/clean.mjs";
@@ -9,4 +10,4 @@ import { prepare } from "./core/prepare.mjs";
9
10
  import { zip } from "./core/zip.mjs";
10
11
  import "./core/index.mjs";
11
12
 
12
- export { build, clean, createServer, defineConfig, defineRunnerConfig, defineWebExtConfig, initialize, prepare, version, zip };
13
+ export { build, clean, createServer, defineConfig, defineRunnerConfig, defineWebExtConfig, initialize, normalizePath, prepare, version, zip };
@@ -1,6 +1,6 @@
1
1
  import { Entrypoint, Wxt, WxtModule, WxtModuleOptions, WxtModuleSetup } from "./types.mjs";
2
- import * as vite from "vite";
3
2
  import { UnimportOptions } from "unimport";
3
+ import * as vite from "vite";
4
4
 
5
5
  //#region src/modules.d.ts
6
6
  declare function defineWxtModule<TOptions extends WxtModuleOptions>(module: WxtModule<TOptions> | WxtModuleSetup<TOptions>): WxtModule<TOptions>;
package/dist/modules.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  import glob from "fast-glob";
2
2
  import { resolve } from "node:path";
3
- import * as vite from "vite";
4
3
 
5
4
  //#region src/modules.ts
6
5
  function defineWxtModule(module) {
@@ -89,7 +88,7 @@ function addViteConfig(wxt, viteConfig) {
89
88
  wxt.hooks.hook("config:resolved", (wxt) => {
90
89
  const userVite = wxt.config.vite;
91
90
  wxt.config.vite = async (env) => {
92
- const fromUser = await userVite(env);
91
+ const [vite, fromUser] = await Promise.all([import("vite"), userVite(env)]);
93
92
  const fromModule = viteConfig(env) ?? {};
94
93
  return vite.mergeConfig(fromModule, fromUser);
95
94
  };
@@ -142,7 +141,6 @@ function addWxtPlugin(wxt, plugin) {
142
141
  */
143
142
  function addImportPreset(wxt, preset) {
144
143
  wxt.hooks.hook("config:resolved", (wxt) => {
145
- if (!wxt.config.imports) return;
146
144
  wxt.config.imports.presets ??= [];
147
145
  if (wxt.config.imports.presets.includes(preset)) return;
148
146
  wxt.config.imports.presets.push(preset);
package/dist/types.d.mts CHANGED
@@ -27,12 +27,12 @@
27
27
  import { ManifestContentScript } from "./core/utils/types.mjs";
28
28
  import { ResolvedConfig } from "c12";
29
29
  import { LogLevel } from "consola";
30
- import * as vite from "vite";
31
30
  import { Import, UnimportOptions } from "unimport";
32
31
  import { Hookable, NestedHooks } from "hookable";
33
32
  import * as Nypm from "nypm";
34
33
  import { PluginVisualizerOptions } from "@aklinker1/rollup-plugin-visualizer";
35
34
  import { Browser } from "@wxt-dev/browser";
35
+ import * as vite from "vite";
36
36
 
37
37
  //#region src/types.d.ts
38
38
  interface InlineConfig {
@@ -47,7 +47,7 @@ interface InlineConfig {
47
47
  * Directory containing all source code. Set to `"src"` to move all source code to a `src/`
48
48
  * directory.
49
49
  *
50
- * After changing, don't forget to move the `public/` and `entrypoints/` directories into the new
50
+ * After changing, remember to move the `public/` and `entrypoints/` directories into the new
51
51
  * source dir.
52
52
  *
53
53
  * @default config.root
@@ -637,6 +637,18 @@ interface IsolatedWorldContentScriptEntrypointOptions extends BaseContentScriptE
637
637
  */
638
638
  world?: 'ISOLATED';
639
639
  }
640
+ /**
641
+ * Firefox theme icon definition for light/dark mode support.
642
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action#theme_icons
643
+ */
644
+ interface ThemeIcon {
645
+ /** Path to the icon shown when the browser uses a light theme. */
646
+ light: string;
647
+ /** Path to the icon shown when the browser uses a dark theme. */
648
+ dark: string;
649
+ /** Icon size in pixels. */
650
+ size: number;
651
+ }
640
652
  interface PopupEntrypointOptions extends BaseEntrypointOptions {
641
653
  /**
642
654
  * Defaults to "browser_action" to be equivalent to MV3's "action" key
@@ -645,6 +657,16 @@ interface PopupEntrypointOptions extends BaseEntrypointOptions {
645
657
  defaultIcon?: Record<string, string>;
646
658
  defaultTitle?: PerBrowserOption<string>;
647
659
  browserStyle?: PerBrowserOption<boolean>;
660
+ /**
661
+ * Firefox only. Defines the part of the browser in which the button is initially placed.
662
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/action#default_area
663
+ */
664
+ defaultArea?: PerBrowserOption<'navbar' | 'menupanel' | 'tabstrip' | 'personaltoolbar'>;
665
+ /**
666
+ * Firefox only. Icons for light and dark themes.
667
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/action#theme_icons
668
+ */
669
+ themeIcons?: ThemeIcon[];
648
670
  }
649
671
  interface OptionsEntrypointOptions extends BaseEntrypointOptions {
650
672
  openInTab?: PerBrowserOption<boolean>;
@@ -1281,7 +1303,7 @@ interface FsCache {
1281
1303
  }
1282
1304
  interface ExtensionRunner {
1283
1305
  openBrowser(): Promise<void>;
1284
- closeBrowser(): Promise<void>;
1306
+ closeBrowser?(): Promise<void>;
1285
1307
  /** Whether or not this runner actually opens the browser. */
1286
1308
  canOpen?(): boolean;
1287
1309
  }
@@ -1450,4 +1472,4 @@ interface WxtDirFileEntry {
1450
1472
  tsReference?: boolean;
1451
1473
  }
1452
1474
  //#endregion
1453
- export { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig$1 as ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, UnlistedScriptDefinition, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig };
1475
+ export { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig$1 as ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig };
@@ -36,10 +36,9 @@ declare class ContentScriptContext implements AbortController {
36
36
  private readonly contentScriptName;
37
37
  readonly options?: Omit<ContentScriptDefinition, "main"> | undefined;
38
38
  private static SCRIPT_STARTED_MESSAGE_TYPE;
39
- private isTopFrame;
39
+ private id;
40
40
  private abortController;
41
41
  private locationWatcher;
42
- private receivedMessageIds;
43
42
  constructor(contentScriptName: string, options?: Omit<ContentScriptDefinition, "main"> | undefined);
44
43
  get signal(): AbortSignal;
45
44
  abort(reason?: any): void;
@@ -125,10 +124,8 @@ declare class ContentScriptContext implements AbortController {
125
124
  */
126
125
  notifyInvalidated(): void;
127
126
  stopOldScripts(): void;
128
- verifyScriptStartedEvent(event: MessageEvent): boolean;
129
- listenForNewerScripts(options?: {
130
- ignoreFirstEvent?: boolean;
131
- }): void;
127
+ verifyScriptStartedEvent(event: CustomEvent): boolean;
128
+ listenForNewerScripts(): void;
132
129
  }
133
130
  interface WxtWindowEventMap extends WindowEventMap {
134
131
  'wxt:locationchange': WxtLocationChangeEvent;
@@ -36,18 +36,16 @@ import { browser } from "wxt/browser";
36
36
  */
37
37
  var ContentScriptContext = class ContentScriptContext {
38
38
  static SCRIPT_STARTED_MESSAGE_TYPE = getUniqueEventName("wxt:content-script-started");
39
- isTopFrame = window.self === window.top;
39
+ id;
40
40
  abortController;
41
41
  locationWatcher = createLocationWatcher(this);
42
- receivedMessageIds = /* @__PURE__ */ new Set();
43
42
  constructor(contentScriptName, options) {
44
43
  this.contentScriptName = contentScriptName;
45
44
  this.options = options;
45
+ this.id = Math.random().toString(36).slice(2);
46
46
  this.abortController = new AbortController();
47
- if (this.isTopFrame) {
48
- this.listenForNewerScripts({ ignoreFirstEvent: true });
49
- this.stopOldScripts();
50
- } else this.listenForNewerScripts();
47
+ this.stopOldScripts();
48
+ this.listenForNewerScripts();
51
49
  }
52
50
  get signal() {
53
51
  return this.abortController.signal;
@@ -161,31 +159,28 @@ var ContentScriptContext = class ContentScriptContext {
161
159
  logger.debug(`Content script "${this.contentScriptName}" context invalidated`);
162
160
  }
163
161
  stopOldScripts() {
162
+ document.dispatchEvent(new CustomEvent(ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE, { detail: {
163
+ contentScriptName: this.contentScriptName,
164
+ messageId: this.id
165
+ } }));
164
166
  window.postMessage({
165
167
  type: ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE,
166
168
  contentScriptName: this.contentScriptName,
167
- messageId: Math.random().toString(36).slice(2)
169
+ messageId: this.id
168
170
  }, "*");
169
171
  }
170
172
  verifyScriptStartedEvent(event) {
171
- const isScriptStartedEvent = event.data?.type === ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE;
172
- const isSameContentScript = event.data?.contentScriptName === this.contentScriptName;
173
- const isNotDuplicate = !this.receivedMessageIds.has(event.data?.messageId);
174
- return isScriptStartedEvent && isSameContentScript && isNotDuplicate;
173
+ const isSameContentScript = event.detail?.contentScriptName === this.contentScriptName;
174
+ const isFromSelf = event.detail?.messageId === this.id;
175
+ return isSameContentScript && !isFromSelf;
175
176
  }
176
- listenForNewerScripts(options) {
177
- let isFirst = true;
177
+ listenForNewerScripts() {
178
178
  const cb = (event) => {
179
- if (this.verifyScriptStartedEvent(event)) {
180
- this.receivedMessageIds.add(event.data.messageId);
181
- const wasFirst = isFirst;
182
- isFirst = false;
183
- if (wasFirst && options?.ignoreFirstEvent) return;
184
- this.notifyInvalidated();
185
- }
179
+ if (!(event instanceof CustomEvent) || !this.verifyScriptStartedEvent(event)) return;
180
+ this.notifyInvalidated();
186
181
  };
187
- addEventListener("message", cb);
188
- this.onInvalidated(() => removeEventListener("message", cb));
182
+ document.addEventListener(ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE, cb);
183
+ this.onInvalidated(() => document.removeEventListener(ContentScriptContext.SCRIPT_STARTED_MESSAGE_TYPE, cb));
189
184
  }
190
185
  };
191
186
 
@@ -13,7 +13,7 @@ function createIframeUi(ctx, options) {
13
13
  const iframe = document.createElement("iframe");
14
14
  iframe.src = browser.runtime.getURL(options.page);
15
15
  wrapper.appendChild(iframe);
16
- let mounted = void 0;
16
+ let mounted;
17
17
  const mount = () => {
18
18
  applyPosition(wrapper, iframe, options);
19
19
  options.onBeforeMount?.(wrapper, iframe);
@@ -8,7 +8,7 @@ import { applyPosition, createMountFunctions, mountUi } from "./shared.mjs";
8
8
  */
9
9
  function createIntegratedUi(ctx, options) {
10
10
  const wrapper = document.createElement(options.tag || "div");
11
- let mounted = void 0;
11
+ let mounted;
12
12
  const mount = () => {
13
13
  applyPosition(wrapper, void 0, options);
14
14
  mountUi(wrapper, options);
@@ -52,13 +52,11 @@ function mountUi(root, options) {
52
52
  case "before":
53
53
  anchor.parentElement?.insertBefore(root, anchor);
54
54
  break;
55
- default:
56
- options.append(anchor, root);
57
- break;
55
+ default: options.append(anchor, root);
58
56
  }
59
57
  }
60
58
  function createMountFunctions(baseFunctions, options) {
61
- let autoMountInstance = void 0;
59
+ let autoMountInstance;
62
60
  const stopAutoMount = () => {
63
61
  autoMountInstance?.stopAutoMount();
64
62
  autoMountInstance = void 0;
package/dist/version.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region src/version.ts
2
- const version = "0.20.14";
2
+ const version = "0.20.15";
3
3
 
4
4
  //#endregion
5
5
  export { version };
@@ -24,9 +24,6 @@ const logger = {
24
24
  let ws;
25
25
  /**
26
26
  * Connect to the websocket and listen for messages.
27
- *
28
- * @param onMessage Optional callback that is called when a message is recieved and we've verified
29
- * it's structure is what we expect.
30
27
  */
31
28
  function getDevServerWebSocket() {
32
29
  if (import.meta.env.COMMAND !== "serve") throw Error("Must be running WXT dev command to connect to call getDevServerWebSocket()");
@@ -19,9 +19,6 @@ const logger = {
19
19
  let ws;
20
20
  /**
21
21
  * Connect to the websocket and listen for messages.
22
- *
23
- * @param onMessage Optional callback that is called when a message is recieved and we've verified
24
- * it's structure is what we expect.
25
22
  */
26
23
  function getDevServerWebSocket() {
27
24
  if (import.meta.env.COMMAND !== "serve") throw Error("Must be running WXT dev command to connect to call getDevServerWebSocket()");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wxt",
3
3
  "type": "module",
4
- "version": "0.20.14",
4
+ "version": "0.20.15",
5
5
  "description": "⚡ Next-gen Web Extension Framework",
6
6
  "license": "MIT",
7
7
  "dependencies": {
@@ -51,6 +51,14 @@
51
51
  "web-ext-run": "^0.2.4",
52
52
  "@wxt-dev/browser": "^0.1.36"
53
53
  },
54
+ "peerDependencies": {
55
+ "eslint": "^8.57.0 || ^9.0.0"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "eslint": {
59
+ "optional": true
60
+ }
61
+ },
54
62
  "devDependencies": {
55
63
  "@faker-js/faker": "^10.2.0",
56
64
  "@types/fs-extra": "^11.0.4",
@@ -58,6 +66,7 @@
58
66
  "@types/node": "^20.17.6",
59
67
  "@types/normalize-path": "^3.0.2",
60
68
  "@types/prompts": "^2.4.9",
69
+ "eslint": "^9.38.0",
61
70
  "extract-zip": "^2.0.1",
62
71
  "happy-dom": "^20.5.0",
63
72
  "lodash.merge": "^4.6.2",
@@ -67,7 +76,6 @@
67
76
  "vitest": "^4.0.18",
68
77
  "vitest-plugin-random-seed": "^1.1.2"
69
78
  },
70
- "peerDependenciesMeta": {},
71
79
  "repository": {
72
80
  "type": "git",
73
81
  "url": "git+https://github.com/wxt-dev/wxt.git"