wxt 0.16.9 → 0.16.11-alpha1

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.
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.16.9";
2
+ var version = "0.16.11-alpha1";
3
3
 
4
4
  // src/core/utils/paths.ts
5
5
  import systemPath from "node:path";
@@ -212,6 +212,9 @@ function resolvePerBrowserOptions(options, browser) {
212
212
  ])
213
213
  );
214
214
  }
215
+ function isHtmlEntrypoint(entrypoint) {
216
+ return entrypoint.inputPath.endsWith(".html");
217
+ }
215
218
 
216
219
  // src/core/utils/constants.ts
217
220
  var VIRTUAL_NOOP_BACKGROUND_MODULE_ID = "virtual:user-background";
@@ -724,7 +727,7 @@ async function writePathsDeclarationFile(entrypoints) {
724
727
  (entry) => getEntrypointBundlePath(
725
728
  entry,
726
729
  wxt.config.outDir,
727
- entry.inputPath.endsWith(".html") ? ".html" : ".js"
730
+ isHtmlEntrypoint(entry) ? ".html" : ".js"
728
731
  )
729
732
  ).concat(await getPublicFiles()).map(normalizePath).map((path7) => ` | "/${path7}"`).sort().join("\n");
730
733
  const template = `// Generated by wxt
@@ -1520,6 +1523,9 @@ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
1520
1523
  return libMode;
1521
1524
  };
1522
1525
  const getMultiPageConfig = (entrypoints) => {
1526
+ const htmlEntrypoints = new Set(
1527
+ entrypoints.filter(isHtmlEntrypoint).map((e) => e.name)
1528
+ );
1523
1529
  return {
1524
1530
  mode: wxtConfig.mode,
1525
1531
  plugins: [
@@ -1535,10 +1541,11 @@ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
1535
1541
  output: {
1536
1542
  // Include a hash to prevent conflicts
1537
1543
  chunkFileNames: "chunks/[name]-[hash].js",
1538
- // Place JS entrypoints in main directory without a hash. (popup.html & popup.js are
1539
- // next to each other). The unique entrypoint name requirement prevents conflicts with
1540
- // scripts of the same name
1541
- entryFileNames: "[name].js",
1544
+ entryFileNames: ({ name }) => {
1545
+ if (htmlEntrypoints.has(name))
1546
+ return "chunks/[name]-[hash].js";
1547
+ return "[name].js";
1548
+ },
1542
1549
  // We can't control the "name", so we need a hash to prevent conflicts
1543
1550
  assetFileNames: "assets/[name]-[hash].[ext]"
1544
1551
  }
@@ -1671,6 +1678,7 @@ async function resolveConfig(inlineConfig, command, server) {
1671
1678
  let userConfigMetadata;
1672
1679
  if (inlineConfig.configFile !== false) {
1673
1680
  const { config: loadedConfig, ...metadata } = await loadConfig({
1681
+ configFile: inlineConfig.configFile,
1674
1682
  name: "wxt",
1675
1683
  cwd: inlineConfig.root ?? process.cwd(),
1676
1684
  rcFile: false,
@@ -2049,7 +2057,12 @@ function getEsbuildOptions(opts) {
2049
2057
  return {
2050
2058
  format: "cjs",
2051
2059
  loader: isJsx ? "tsx" : "ts",
2052
- jsx: isJsx ? "automatic" : void 0
2060
+ ...isJsx ? {
2061
+ // `h` and `Fragment` are undefined, but that's OK because JSX is never evaluated while
2062
+ // grabbing the entrypoint's options.
2063
+ jsxFactory: "h",
2064
+ jsxFragment: "Fragment"
2065
+ } : void 0
2053
2066
  };
2054
2067
  }
2055
2068
 
@@ -2528,17 +2541,13 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
2528
2541
  if (contentScripts?.length) {
2529
2542
  const cssMap = getContentScriptsCssMap(buildOutput, contentScripts);
2530
2543
  if (wxt.config.command === "serve" && wxt.config.manifestVersion === 3) {
2531
- const hostPermissions = new Set(manifest.host_permissions ?? []);
2532
2544
  contentScripts.forEach((script) => {
2533
2545
  script.options.matches.forEach((matchPattern) => {
2534
- hostPermissions.add(matchPattern);
2546
+ addHostPermission(manifest, matchPattern);
2535
2547
  });
2536
2548
  });
2537
- hostPermissions.forEach(
2538
- (permission) => addHostPermission(manifest, permission)
2539
- );
2540
2549
  } else {
2541
- const hashToEntrypointsMap = contentScripts.reduce((map, script) => {
2550
+ const hashToEntrypointsMap = contentScripts.filter((cs) => cs.options.registration !== "runtime").reduce((map, script) => {
2542
2551
  const hash = hashContentScriptOptions(script.options);
2543
2552
  if (map.has(hash))
2544
2553
  map.get(hash)?.push(script);
@@ -2546,8 +2555,10 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
2546
2555
  map.set(hash, [script]);
2547
2556
  return map;
2548
2557
  }, /* @__PURE__ */ new Map());
2549
- const newContentScripts = Array.from(hashToEntrypointsMap.entries()).map(
2550
- ([, scripts]) => mapWxtOptionsToContentScript(
2558
+ const manifestContentScripts = Array.from(
2559
+ hashToEntrypointsMap.values()
2560
+ ).map(
2561
+ (scripts) => mapWxtOptionsToContentScript(
2551
2562
  scripts[0].options,
2552
2563
  scripts.map(
2553
2564
  (entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".js")
@@ -2555,10 +2566,23 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
2555
2566
  getContentScriptCssFiles(scripts, cssMap)
2556
2567
  )
2557
2568
  );
2558
- if (newContentScripts.length >= 0) {
2569
+ if (manifestContentScripts.length >= 0) {
2559
2570
  manifest.content_scripts ??= [];
2560
- manifest.content_scripts.push(...newContentScripts);
2571
+ manifest.content_scripts.push(...manifestContentScripts);
2561
2572
  }
2573
+ const runtimeContentScripts = contentScripts.filter(
2574
+ (cs) => cs.options.registration === "runtime"
2575
+ );
2576
+ if (runtimeContentScripts.length > 0 && wxt.config.manifestVersion === 2) {
2577
+ throw Error(
2578
+ 'Cannot use `registration: "runtime"` with MV2 content scripts, it is a MV3-only feature.'
2579
+ );
2580
+ }
2581
+ runtimeContentScripts.forEach((script) => {
2582
+ script.options.matches.forEach((matchPattern) => {
2583
+ addHostPermission(manifest, matchPattern);
2584
+ });
2585
+ });
2562
2586
  }
2563
2587
  const contentScriptCssResources = getContentScriptCssWebAccessibleResources(
2564
2588
  contentScripts,
@@ -2959,6 +2983,7 @@ export {
2959
2983
  registerWxt,
2960
2984
  detectDevChanges,
2961
2985
  getEntrypointBundlePath,
2986
+ isHtmlEntrypoint,
2962
2987
  findEntrypoints,
2963
2988
  generateTypesDir,
2964
2989
  formatDuration,
package/dist/cli.js CHANGED
@@ -237,6 +237,9 @@ function resolvePerBrowserOptions(options, browser) {
237
237
  ])
238
238
  );
239
239
  }
240
+ function isHtmlEntrypoint(entrypoint) {
241
+ return entrypoint.inputPath.endsWith(".html");
242
+ }
240
243
 
241
244
  // src/core/utils/constants.ts
242
245
  var VIRTUAL_NOOP_BACKGROUND_MODULE_ID = "virtual:user-background";
@@ -749,7 +752,7 @@ async function writePathsDeclarationFile(entrypoints) {
749
752
  (entry) => getEntrypointBundlePath(
750
753
  entry,
751
754
  wxt.config.outDir,
752
- entry.inputPath.endsWith(".html") ? ".html" : ".js"
755
+ isHtmlEntrypoint(entry) ? ".html" : ".js"
753
756
  )
754
757
  ).concat(await getPublicFiles()).map(normalizePath).map((path8) => ` | "/${path8}"`).sort().join("\n");
755
758
  const template = `// Generated by wxt
@@ -1520,6 +1523,9 @@ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
1520
1523
  return libMode;
1521
1524
  };
1522
1525
  const getMultiPageConfig = (entrypoints) => {
1526
+ const htmlEntrypoints = new Set(
1527
+ entrypoints.filter(isHtmlEntrypoint).map((e) => e.name)
1528
+ );
1523
1529
  return {
1524
1530
  mode: wxtConfig.mode,
1525
1531
  plugins: [
@@ -1535,10 +1541,11 @@ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
1535
1541
  output: {
1536
1542
  // Include a hash to prevent conflicts
1537
1543
  chunkFileNames: "chunks/[name]-[hash].js",
1538
- // Place JS entrypoints in main directory without a hash. (popup.html & popup.js are
1539
- // next to each other). The unique entrypoint name requirement prevents conflicts with
1540
- // scripts of the same name
1541
- entryFileNames: "[name].js",
1544
+ entryFileNames: ({ name }) => {
1545
+ if (htmlEntrypoints.has(name))
1546
+ return "chunks/[name]-[hash].js";
1547
+ return "[name].js";
1548
+ },
1542
1549
  // We can't control the "name", so we need a hash to prevent conflicts
1543
1550
  assetFileNames: "assets/[name]-[hash].[ext]"
1544
1551
  }
@@ -1671,6 +1678,7 @@ async function resolveConfig(inlineConfig, command, server) {
1671
1678
  let userConfigMetadata;
1672
1679
  if (inlineConfig.configFile !== false) {
1673
1680
  const { config: loadedConfig, ...metadata } = await loadConfig({
1681
+ configFile: inlineConfig.configFile,
1674
1682
  name: "wxt",
1675
1683
  cwd: inlineConfig.root ?? process.cwd(),
1676
1684
  rcFile: false,
@@ -2049,7 +2057,12 @@ function getEsbuildOptions(opts) {
2049
2057
  return {
2050
2058
  format: "cjs",
2051
2059
  loader: isJsx ? "tsx" : "ts",
2052
- jsx: isJsx ? "automatic" : void 0
2060
+ ...isJsx ? {
2061
+ // `h` and `Fragment` are undefined, but that's OK because JSX is never evaluated while
2062
+ // grabbing the entrypoint's options.
2063
+ jsxFactory: "h",
2064
+ jsxFragment: "Fragment"
2065
+ } : void 0
2053
2066
  };
2054
2067
  }
2055
2068
 
@@ -2168,7 +2181,7 @@ function getChunkSortWeight(filename) {
2168
2181
  import pc4 from "picocolors";
2169
2182
 
2170
2183
  // package.json
2171
- var version = "0.16.9";
2184
+ var version = "0.16.11-alpha1";
2172
2185
 
2173
2186
  // src/core/utils/log/printHeader.ts
2174
2187
  import { consola as consola2 } from "consola";
@@ -2537,17 +2550,13 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
2537
2550
  if (contentScripts?.length) {
2538
2551
  const cssMap = getContentScriptsCssMap(buildOutput, contentScripts);
2539
2552
  if (wxt.config.command === "serve" && wxt.config.manifestVersion === 3) {
2540
- const hostPermissions = new Set(manifest.host_permissions ?? []);
2541
2553
  contentScripts.forEach((script) => {
2542
2554
  script.options.matches.forEach((matchPattern) => {
2543
- hostPermissions.add(matchPattern);
2555
+ addHostPermission(manifest, matchPattern);
2544
2556
  });
2545
2557
  });
2546
- hostPermissions.forEach(
2547
- (permission) => addHostPermission(manifest, permission)
2548
- );
2549
2558
  } else {
2550
- const hashToEntrypointsMap = contentScripts.reduce((map, script) => {
2559
+ const hashToEntrypointsMap = contentScripts.filter((cs) => cs.options.registration !== "runtime").reduce((map, script) => {
2551
2560
  const hash = hashContentScriptOptions(script.options);
2552
2561
  if (map.has(hash))
2553
2562
  map.get(hash)?.push(script);
@@ -2555,8 +2564,10 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
2555
2564
  map.set(hash, [script]);
2556
2565
  return map;
2557
2566
  }, /* @__PURE__ */ new Map());
2558
- const newContentScripts = Array.from(hashToEntrypointsMap.entries()).map(
2559
- ([, scripts]) => mapWxtOptionsToContentScript(
2567
+ const manifestContentScripts = Array.from(
2568
+ hashToEntrypointsMap.values()
2569
+ ).map(
2570
+ (scripts) => mapWxtOptionsToContentScript(
2560
2571
  scripts[0].options,
2561
2572
  scripts.map(
2562
2573
  (entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".js")
@@ -2564,10 +2575,23 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
2564
2575
  getContentScriptCssFiles(scripts, cssMap)
2565
2576
  )
2566
2577
  );
2567
- if (newContentScripts.length >= 0) {
2578
+ if (manifestContentScripts.length >= 0) {
2568
2579
  manifest.content_scripts ??= [];
2569
- manifest.content_scripts.push(...newContentScripts);
2580
+ manifest.content_scripts.push(...manifestContentScripts);
2581
+ }
2582
+ const runtimeContentScripts = contentScripts.filter(
2583
+ (cs) => cs.options.registration === "runtime"
2584
+ );
2585
+ if (runtimeContentScripts.length > 0 && wxt.config.manifestVersion === 2) {
2586
+ throw Error(
2587
+ 'Cannot use `registration: "runtime"` with MV2 content scripts, it is a MV3-only feature.'
2588
+ );
2570
2589
  }
2590
+ runtimeContentScripts.forEach((script) => {
2591
+ script.options.matches.forEach((matchPattern) => {
2592
+ addHostPermission(manifest, matchPattern);
2593
+ });
2594
+ });
2571
2595
  }
2572
2596
  const contentScriptCssResources = getContentScriptCssWebAccessibleResources(
2573
2597
  contentScripts,
@@ -3291,7 +3315,7 @@ function reloadContentScripts(steps, server) {
3291
3315
  }
3292
3316
  }
3293
3317
  function reloadHtmlPages(groups, server) {
3294
- const htmlEntries = groups.flat().filter((entry) => entry.inputPath.endsWith(".html"));
3318
+ const htmlEntries = groups.flat().filter(isHtmlEntrypoint);
3295
3319
  htmlEntries.forEach((entry) => {
3296
3320
  const path8 = getEntrypointBundlePath(entry, wxt.config.outDir, ".html");
3297
3321
  server.reloadPage(path8);
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as ContentScriptContext } from './index-nSEE-7AX.js';
1
+ import { a as ContentScriptContext } from './index-v_64CCcw.js';
2
2
  import 'webextension-polyfill';
3
3
 
4
4
  interface IntegratedContentScriptUi<TMounted> extends ContentScriptUi<TMounted> {
@@ -571,6 +571,18 @@ interface BaseContentScriptEntrypointOptions extends BaseEntrypointOptions {
571
571
  * @default "manifest"
572
572
  */
573
573
  cssInjectionMode?: PerBrowserOption<'manifest' | 'manual' | 'ui'>;
574
+ /**
575
+ * Specify how the content script is registered.
576
+ *
577
+ * - `"manifest"`: The content script will be added to the `content_scripts` entry in the
578
+ * manifest. This is the normal and most well known way of registering a content script.
579
+ * - `"runtime"`: The content script's `matches` is added to `host_permissions` and you are
580
+ * responsible for using the scripting API to register the content script dynamically at
581
+ * runtime.
582
+ *
583
+ * @default "manifest"
584
+ */
585
+ registration?: PerBrowserOption<'manifest' | 'runtime'>;
574
586
  }
575
587
  interface MainWorldContentScriptEntrypointOptions extends BaseContentScriptEntrypointOptions {
576
588
  /**
@@ -571,6 +571,18 @@ interface BaseContentScriptEntrypointOptions extends BaseEntrypointOptions {
571
571
  * @default "manifest"
572
572
  */
573
573
  cssInjectionMode?: PerBrowserOption<'manifest' | 'manual' | 'ui'>;
574
+ /**
575
+ * Specify how the content script is registered.
576
+ *
577
+ * - `"manifest"`: The content script will be added to the `content_scripts` entry in the
578
+ * manifest. This is the normal and most well known way of registering a content script.
579
+ * - `"runtime"`: The content script's `matches` is added to `host_permissions` and you are
580
+ * responsible for using the scripting API to register the content script dynamically at
581
+ * runtime.
582
+ *
583
+ * @default "manifest"
584
+ */
585
+ registration?: PerBrowserOption<'manifest' | 'runtime'>;
574
586
  }
575
587
  interface MainWorldContentScriptEntrypointOptions extends BaseContentScriptEntrypointOptions {
576
588
  /**
@@ -176,6 +176,18 @@ interface BaseContentScriptEntrypointOptions extends BaseEntrypointOptions {
176
176
  * @default "manifest"
177
177
  */
178
178
  cssInjectionMode?: PerBrowserOption<'manifest' | 'manual' | 'ui'>;
179
+ /**
180
+ * Specify how the content script is registered.
181
+ *
182
+ * - `"manifest"`: The content script will be added to the `content_scripts` entry in the
183
+ * manifest. This is the normal and most well known way of registering a content script.
184
+ * - `"runtime"`: The content script's `matches` is added to `host_permissions` and you are
185
+ * responsible for using the scripting API to register the content script dynamically at
186
+ * runtime.
187
+ *
188
+ * @default "manifest"
189
+ */
190
+ registration?: PerBrowserOption<'manifest' | 'runtime'>;
179
191
  }
180
192
  interface MainWorldContentScriptEntrypointOptions extends BaseContentScriptEntrypointOptions {
181
193
  /**
package/dist/index.cjs CHANGED
@@ -2660,6 +2660,9 @@ function resolvePerBrowserOptions(options, browser) {
2660
2660
  ])
2661
2661
  );
2662
2662
  }
2663
+ function isHtmlEntrypoint(entrypoint) {
2664
+ return entrypoint.inputPath.endsWith(".html");
2665
+ }
2663
2666
 
2664
2667
  // src/core/utils/constants.ts
2665
2668
  var VIRTUAL_NOOP_BACKGROUND_MODULE_ID = "virtual:user-background";
@@ -3172,7 +3175,7 @@ async function writePathsDeclarationFile(entrypoints) {
3172
3175
  (entry) => getEntrypointBundlePath(
3173
3176
  entry,
3174
3177
  wxt.config.outDir,
3175
- entry.inputPath.endsWith(".html") ? ".html" : ".js"
3178
+ isHtmlEntrypoint(entry) ? ".html" : ".js"
3176
3179
  )
3177
3180
  ).concat(await getPublicFiles()).map(normalizePath).map((path11) => ` | "/${path11}"`).sort().join("\n");
3178
3181
  const template = `// Generated by wxt
@@ -3946,6 +3949,9 @@ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
3946
3949
  return libMode;
3947
3950
  };
3948
3951
  const getMultiPageConfig = (entrypoints) => {
3952
+ const htmlEntrypoints = new Set(
3953
+ entrypoints.filter(isHtmlEntrypoint).map((e) => e.name)
3954
+ );
3949
3955
  return {
3950
3956
  mode: wxtConfig.mode,
3951
3957
  plugins: [
@@ -3961,10 +3967,11 @@ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
3961
3967
  output: {
3962
3968
  // Include a hash to prevent conflicts
3963
3969
  chunkFileNames: "chunks/[name]-[hash].js",
3964
- // Place JS entrypoints in main directory without a hash. (popup.html & popup.js are
3965
- // next to each other). The unique entrypoint name requirement prevents conflicts with
3966
- // scripts of the same name
3967
- entryFileNames: "[name].js",
3970
+ entryFileNames: ({ name }) => {
3971
+ if (htmlEntrypoints.has(name))
3972
+ return "chunks/[name]-[hash].js";
3973
+ return "[name].js";
3974
+ },
3968
3975
  // We can't control the "name", so we need a hash to prevent conflicts
3969
3976
  assetFileNames: "assets/[name]-[hash].[ext]"
3970
3977
  }
@@ -4097,6 +4104,7 @@ async function resolveConfig(inlineConfig, command, server) {
4097
4104
  let userConfigMetadata;
4098
4105
  if (inlineConfig.configFile !== false) {
4099
4106
  const { config: loadedConfig, ...metadata } = await (0, import_c12.loadConfig)({
4107
+ configFile: inlineConfig.configFile,
4100
4108
  name: "wxt",
4101
4109
  cwd: inlineConfig.root ?? process.cwd(),
4102
4110
  rcFile: false,
@@ -4476,7 +4484,12 @@ function getEsbuildOptions(opts) {
4476
4484
  return {
4477
4485
  format: "cjs",
4478
4486
  loader: isJsx ? "tsx" : "ts",
4479
- jsx: isJsx ? "automatic" : void 0
4487
+ ...isJsx ? {
4488
+ // `h` and `Fragment` are undefined, but that's OK because JSX is never evaluated while
4489
+ // grabbing the entrypoint's options.
4490
+ jsxFactory: "h",
4491
+ jsxFragment: "Fragment"
4492
+ } : void 0
4480
4493
  };
4481
4494
  }
4482
4495
 
@@ -4595,7 +4608,7 @@ function getChunkSortWeight(filename) {
4595
4608
  var import_picocolors4 = __toESM(require("picocolors"), 1);
4596
4609
 
4597
4610
  // package.json
4598
- var version = "0.16.9";
4611
+ var version = "0.16.11-alpha1";
4599
4612
 
4600
4613
  // src/core/utils/log/printHeader.ts
4601
4614
  var import_consola2 = require("consola");
@@ -4960,17 +4973,13 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
4960
4973
  if (contentScripts?.length) {
4961
4974
  const cssMap = getContentScriptsCssMap(buildOutput, contentScripts);
4962
4975
  if (wxt.config.command === "serve" && wxt.config.manifestVersion === 3) {
4963
- const hostPermissions = new Set(manifest.host_permissions ?? []);
4964
4976
  contentScripts.forEach((script) => {
4965
4977
  script.options.matches.forEach((matchPattern) => {
4966
- hostPermissions.add(matchPattern);
4978
+ addHostPermission(manifest, matchPattern);
4967
4979
  });
4968
4980
  });
4969
- hostPermissions.forEach(
4970
- (permission) => addHostPermission(manifest, permission)
4971
- );
4972
4981
  } else {
4973
- const hashToEntrypointsMap = contentScripts.reduce((map, script) => {
4982
+ const hashToEntrypointsMap = contentScripts.filter((cs) => cs.options.registration !== "runtime").reduce((map, script) => {
4974
4983
  const hash = hashContentScriptOptions(script.options);
4975
4984
  if (map.has(hash))
4976
4985
  map.get(hash)?.push(script);
@@ -4978,8 +4987,10 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
4978
4987
  map.set(hash, [script]);
4979
4988
  return map;
4980
4989
  }, /* @__PURE__ */ new Map());
4981
- const newContentScripts = Array.from(hashToEntrypointsMap.entries()).map(
4982
- ([, scripts]) => mapWxtOptionsToContentScript(
4990
+ const manifestContentScripts = Array.from(
4991
+ hashToEntrypointsMap.values()
4992
+ ).map(
4993
+ (scripts) => mapWxtOptionsToContentScript(
4983
4994
  scripts[0].options,
4984
4995
  scripts.map(
4985
4996
  (entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".js")
@@ -4987,10 +4998,23 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
4987
4998
  getContentScriptCssFiles(scripts, cssMap)
4988
4999
  )
4989
5000
  );
4990
- if (newContentScripts.length >= 0) {
5001
+ if (manifestContentScripts.length >= 0) {
4991
5002
  manifest.content_scripts ??= [];
4992
- manifest.content_scripts.push(...newContentScripts);
5003
+ manifest.content_scripts.push(...manifestContentScripts);
5004
+ }
5005
+ const runtimeContentScripts = contentScripts.filter(
5006
+ (cs) => cs.options.registration === "runtime"
5007
+ );
5008
+ if (runtimeContentScripts.length > 0 && wxt.config.manifestVersion === 2) {
5009
+ throw Error(
5010
+ 'Cannot use `registration: "runtime"` with MV2 content scripts, it is a MV3-only feature.'
5011
+ );
4993
5012
  }
5013
+ runtimeContentScripts.forEach((script) => {
5014
+ script.options.matches.forEach((matchPattern) => {
5015
+ addHostPermission(manifest, matchPattern);
5016
+ });
5017
+ });
4994
5018
  }
4995
5019
  const contentScriptCssResources = getContentScriptCssWebAccessibleResources(
4996
5020
  contentScripts,
@@ -5724,7 +5748,7 @@ function reloadContentScripts(steps, server) {
5724
5748
  }
5725
5749
  }
5726
5750
  function reloadHtmlPages(groups, server) {
5727
- const htmlEntries = groups.flat().filter((entry) => entry.inputPath.endsWith(".html"));
5751
+ const htmlEntries = groups.flat().filter(isHtmlEntrypoint);
5728
5752
  htmlEntries.forEach((entry) => {
5729
5753
  const path11 = getEntrypointBundlePath(entry, wxt.config.outDir, ".html");
5730
5754
  server.reloadPage(path11);
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as InlineConfig, B as BuildOutput, U as UserConfig, E as ExtensionRunnerConfig, W as WxtDevServer } from './index-GDr2OfIq.cjs';
2
- export { v as BackgroundDefinition, l as BackgroundEntrypoint, g as BackgroundEntrypointOptions, h as BaseContentScriptEntrypointOptions, k as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, D as ConfigEnv, u as ContentScriptDefinition, C as ContentScriptEntrypoint, p as Entrypoint, q as EntrypointGroup, _ as EslintGlobalsPropValue, $ as Eslintrc, Y as ExtensionRunner, X as FsCache, G as GenericEntrypoint, K as HookResult, s as IsolatedWorldContentScriptDefinition, i as IsolatedWorldContentScriptEntrypointOptions, L as Logger, t as MainWorldContentScriptDefinition, M as MainWorldContentScriptEntrypointOptions, r as OnContentScriptStopped, n as OptionsEntrypoint, j as OptionsEntrypointOptions, c as OutputAsset, b as OutputChunk, O as OutputFile, y as PerBrowserMap, x as PerBrowserOption, m as PopupEntrypoint, P as PopupEntrypointOptions, V as ResolvedConfig, a0 as ResolvedEslintrc, R as ResolvedPerBrowserOptions, J as ServerInfo, o as SidepanelEntrypoint, S as SidepanelEntrypointOptions, T as TargetBrowser, e as TargetManifestVersion, w as UnlistedScriptDefinition, z as UserManifest, A as UserManifestFn, Z as VirtualEntrypointType, Q as Wxt, F as WxtBuilder, H as WxtBuilderServer, N as WxtHooks, a2 as WxtResolvedUnimportOptions, a1 as WxtUnimportOptions, a as WxtViteConfig } from './index-GDr2OfIq.cjs';
1
+ import { I as InlineConfig, B as BuildOutput, U as UserConfig, E as ExtensionRunnerConfig, W as WxtDevServer } from './index-h54vKikt.cjs';
2
+ export { v as BackgroundDefinition, l as BackgroundEntrypoint, g as BackgroundEntrypointOptions, h as BaseContentScriptEntrypointOptions, k as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, D as ConfigEnv, u as ContentScriptDefinition, C as ContentScriptEntrypoint, p as Entrypoint, q as EntrypointGroup, _ as EslintGlobalsPropValue, $ as Eslintrc, Y as ExtensionRunner, X as FsCache, G as GenericEntrypoint, K as HookResult, s as IsolatedWorldContentScriptDefinition, i as IsolatedWorldContentScriptEntrypointOptions, L as Logger, t as MainWorldContentScriptDefinition, M as MainWorldContentScriptEntrypointOptions, r as OnContentScriptStopped, n as OptionsEntrypoint, j as OptionsEntrypointOptions, c as OutputAsset, b as OutputChunk, O as OutputFile, y as PerBrowserMap, x as PerBrowserOption, m as PopupEntrypoint, P as PopupEntrypointOptions, V as ResolvedConfig, a0 as ResolvedEslintrc, R as ResolvedPerBrowserOptions, J as ServerInfo, o as SidepanelEntrypoint, S as SidepanelEntrypointOptions, T as TargetBrowser, e as TargetManifestVersion, w as UnlistedScriptDefinition, z as UserManifest, A as UserManifestFn, Z as VirtualEntrypointType, Q as Wxt, F as WxtBuilder, H as WxtBuilderServer, N as WxtHooks, a2 as WxtResolvedUnimportOptions, a1 as WxtUnimportOptions, a as WxtViteConfig } from './index-h54vKikt.cjs';
3
3
  import 'vite';
4
4
  import 'webextension-polyfill';
5
5
  import 'unimport';
@@ -64,6 +64,6 @@ declare function prepare(config: InlineConfig): Promise<void>;
64
64
  */
65
65
  declare function zip(config?: InlineConfig): Promise<string[]>;
66
66
 
67
- var version = "0.16.9";
67
+ var version = "0.16.11-alpha1";
68
68
 
69
69
  export { BuildOutput, ExtensionRunnerConfig, InlineConfig, UserConfig, WxtDevServer, build, clean, createServer, defineConfig, defineRunnerConfig, initialize, prepare, version, zip };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as InlineConfig, B as BuildOutput, U as UserConfig, E as ExtensionRunnerConfig, W as WxtDevServer } from './index-GDr2OfIq.js';
2
- export { v as BackgroundDefinition, l as BackgroundEntrypoint, g as BackgroundEntrypointOptions, h as BaseContentScriptEntrypointOptions, k as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, D as ConfigEnv, u as ContentScriptDefinition, C as ContentScriptEntrypoint, p as Entrypoint, q as EntrypointGroup, _ as EslintGlobalsPropValue, $ as Eslintrc, Y as ExtensionRunner, X as FsCache, G as GenericEntrypoint, K as HookResult, s as IsolatedWorldContentScriptDefinition, i as IsolatedWorldContentScriptEntrypointOptions, L as Logger, t as MainWorldContentScriptDefinition, M as MainWorldContentScriptEntrypointOptions, r as OnContentScriptStopped, n as OptionsEntrypoint, j as OptionsEntrypointOptions, c as OutputAsset, b as OutputChunk, O as OutputFile, y as PerBrowserMap, x as PerBrowserOption, m as PopupEntrypoint, P as PopupEntrypointOptions, V as ResolvedConfig, a0 as ResolvedEslintrc, R as ResolvedPerBrowserOptions, J as ServerInfo, o as SidepanelEntrypoint, S as SidepanelEntrypointOptions, T as TargetBrowser, e as TargetManifestVersion, w as UnlistedScriptDefinition, z as UserManifest, A as UserManifestFn, Z as VirtualEntrypointType, Q as Wxt, F as WxtBuilder, H as WxtBuilderServer, N as WxtHooks, a2 as WxtResolvedUnimportOptions, a1 as WxtUnimportOptions, a as WxtViteConfig } from './index-GDr2OfIq.js';
1
+ import { I as InlineConfig, B as BuildOutput, U as UserConfig, E as ExtensionRunnerConfig, W as WxtDevServer } from './index-h54vKikt.js';
2
+ export { v as BackgroundDefinition, l as BackgroundEntrypoint, g as BackgroundEntrypointOptions, h as BaseContentScriptEntrypointOptions, k as BaseEntrypoint, f as BaseEntrypointOptions, d as BuildStepOutput, D as ConfigEnv, u as ContentScriptDefinition, C as ContentScriptEntrypoint, p as Entrypoint, q as EntrypointGroup, _ as EslintGlobalsPropValue, $ as Eslintrc, Y as ExtensionRunner, X as FsCache, G as GenericEntrypoint, K as HookResult, s as IsolatedWorldContentScriptDefinition, i as IsolatedWorldContentScriptEntrypointOptions, L as Logger, t as MainWorldContentScriptDefinition, M as MainWorldContentScriptEntrypointOptions, r as OnContentScriptStopped, n as OptionsEntrypoint, j as OptionsEntrypointOptions, c as OutputAsset, b as OutputChunk, O as OutputFile, y as PerBrowserMap, x as PerBrowserOption, m as PopupEntrypoint, P as PopupEntrypointOptions, V as ResolvedConfig, a0 as ResolvedEslintrc, R as ResolvedPerBrowserOptions, J as ServerInfo, o as SidepanelEntrypoint, S as SidepanelEntrypointOptions, T as TargetBrowser, e as TargetManifestVersion, w as UnlistedScriptDefinition, z as UserManifest, A as UserManifestFn, Z as VirtualEntrypointType, Q as Wxt, F as WxtBuilder, H as WxtBuilderServer, N as WxtHooks, a2 as WxtResolvedUnimportOptions, a1 as WxtUnimportOptions, a as WxtViteConfig } from './index-h54vKikt.js';
3
3
  import 'vite';
4
4
  import 'webextension-polyfill';
5
5
  import 'unimport';
@@ -64,6 +64,6 @@ declare function prepare(config: InlineConfig): Promise<void>;
64
64
  */
65
65
  declare function zip(config?: InlineConfig): Promise<string[]>;
66
66
 
67
- var version = "0.16.9";
67
+ var version = "0.16.11-alpha1";
68
68
 
69
69
  export { BuildOutput, ExtensionRunnerConfig, InlineConfig, UserConfig, WxtDevServer, build, clean, createServer, defineConfig, defineRunnerConfig, initialize, prepare, version, zip };
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  getEntrypointBundlePath,
9
9
  getPackageJson,
10
10
  internalBuild,
11
+ isHtmlEntrypoint,
11
12
  kebabCaseAlphanumeric,
12
13
  mapWxtOptionsToRegisteredContentScript,
13
14
  printFileList,
@@ -16,7 +17,7 @@ import {
16
17
  unnormalizePath,
17
18
  version,
18
19
  wxt
19
- } from "./chunk-CKAPFUPR.js";
20
+ } from "./chunk-UNU4RJJA.js";
20
21
  import "./chunk-VBXJIVYU.js";
21
22
 
22
23
  // src/core/build.ts
@@ -378,7 +379,7 @@ function reloadContentScripts(steps, server) {
378
379
  }
379
380
  }
380
381
  function reloadHtmlPages(groups, server) {
381
- const htmlEntries = groups.flat().filter((entry) => entry.inputPath.endsWith(".html"));
382
+ const htmlEntries = groups.flat().filter(isHtmlEntrypoint);
382
383
  htmlEntries.forEach((entry) => {
383
384
  const path3 = getEntrypointBundlePath(entry, wxt.config.outDir, ".html");
384
385
  server.reloadPage(path3);
package/dist/sandbox.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { U as UnlistedScriptDefinition, B as BackgroundDefinition, C as ContentScriptDefinition } from './index-nSEE-7AX.js';
1
+ import { U as UnlistedScriptDefinition, B as BackgroundDefinition, C as ContentScriptDefinition } from './index-v_64CCcw.js';
2
2
  export * from '@webext-core/match-patterns';
3
3
  import 'webextension-polyfill';
4
4
 
package/dist/testing.cjs CHANGED
@@ -64,6 +64,9 @@ function getEntrypointBundlePath(entrypoint, outDir, ext) {
64
64
  (0, import_node_path2.relative)(outDir, getEntrypointOutputFile(entrypoint, ext))
65
65
  );
66
66
  }
67
+ function isHtmlEntrypoint(entrypoint) {
68
+ return entrypoint.inputPath.endsWith(".html");
69
+ }
67
70
 
68
71
  // src/core/builders/vite/plugins/devHtmlPrerender.ts
69
72
  var import_linkedom = require("linkedom");
@@ -837,6 +840,9 @@ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
837
840
  return libMode;
838
841
  };
839
842
  const getMultiPageConfig = (entrypoints) => {
843
+ const htmlEntrypoints = new Set(
844
+ entrypoints.filter(isHtmlEntrypoint).map((e) => e.name)
845
+ );
840
846
  return {
841
847
  mode: wxtConfig.mode,
842
848
  plugins: [
@@ -852,10 +858,11 @@ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
852
858
  output: {
853
859
  // Include a hash to prevent conflicts
854
860
  chunkFileNames: "chunks/[name]-[hash].js",
855
- // Place JS entrypoints in main directory without a hash. (popup.html & popup.js are
856
- // next to each other). The unique entrypoint name requirement prevents conflicts with
857
- // scripts of the same name
858
- entryFileNames: "[name].js",
861
+ entryFileNames: ({ name }) => {
862
+ if (htmlEntrypoints.has(name))
863
+ return "chunks/[name]-[hash].js";
864
+ return "[name].js";
865
+ },
859
866
  // We can't control the "name", so we need a hash to prevent conflicts
860
867
  assetFileNames: "assets/[name]-[hash].[ext]"
861
868
  }
@@ -977,6 +984,7 @@ async function resolveConfig(inlineConfig, command, server) {
977
984
  let userConfigMetadata;
978
985
  if (inlineConfig.configFile !== false) {
979
986
  const { config: loadedConfig, ...metadata } = await (0, import_c12.loadConfig)({
987
+ configFile: inlineConfig.configFile,
980
988
  name: "wxt",
981
989
  cwd: inlineConfig.root ?? process.cwd(),
982
990
  rcFile: false,
@@ -1,6 +1,6 @@
1
1
  export { FakeBrowser, fakeBrowser } from '@webext-core/fake-browser';
2
2
  import * as vite from 'vite';
3
- import { I as InlineConfig } from './index-GDr2OfIq.cjs';
3
+ import { I as InlineConfig } from './index-h54vKikt.cjs';
4
4
  import 'webextension-polyfill';
5
5
  import 'unimport';
6
6
  import 'consola';
package/dist/testing.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { FakeBrowser, fakeBrowser } from '@webext-core/fake-browser';
2
2
  import * as vite from 'vite';
3
- import { I as InlineConfig } from './index-GDr2OfIq.js';
3
+ import { I as InlineConfig } from './index-h54vKikt.js';
4
4
  import 'webextension-polyfill';
5
5
  import 'unimport';
6
6
  import 'consola';
package/dist/testing.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  tsconfigPaths,
6
6
  unimport,
7
7
  webextensionPolyfillMock
8
- } from "./chunk-CKAPFUPR.js";
8
+ } from "./chunk-UNU4RJJA.js";
9
9
  import "./chunk-VBXJIVYU.js";
10
10
 
11
11
  // src/testing/fake-browser.ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wxt",
3
3
  "type": "module",
4
- "version": "0.16.9",
4
+ "version": "0.16.11-alpha1",
5
5
  "description": "Next gen framework for developing web extensions",
6
6
  "engines": {
7
7
  "node": ">=18",