wxt 0.6.6 → 0.7.1-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.
package/dist/index.d.cts CHANGED
@@ -14,8 +14,9 @@ import { PluginVisualizerOptions } from 'rollup-plugin-visualizer';
14
14
  declare class ContentScriptContext extends AbortController {
15
15
  #private;
16
16
  private readonly contentScriptName;
17
+ readonly options?: Omit<ContentScriptDefinition, "main"> | undefined;
17
18
  static SCRIPT_STARTED_MESSAGE_TYPE: string;
18
- constructor(contentScriptName: string);
19
+ constructor(contentScriptName: string, options?: Omit<ContentScriptDefinition, "main"> | undefined);
19
20
  get isInvalid(): boolean;
20
21
  get isValid(): boolean;
21
22
  /**
@@ -444,6 +445,18 @@ interface ContentScriptDefinition extends ExcludableEntrypoint {
444
445
  * @default "ISOLATED"
445
446
  */
446
447
  world?: 'ISOLATED' | 'MAIN';
448
+ /**
449
+ * Customize how imported/generated styles are injected with the content script. Regardless of the
450
+ * mode selected, CSS will always be built and included in the output directory.
451
+ *
452
+ * - `"manifest"` - Include the CSS in the manifest, under the content script's `css` array.
453
+ * - `"manual"` - Exclude the CSS from the manifest. You are responsible for manually loading it
454
+ * onto the page. Use `browser.runtime.getURL("content-scripts/<name>.css")` to get the file's
455
+ * URL
456
+ *
457
+ * @default "manifest"
458
+ */
459
+ cssInjectionMode?: 'manifest' | 'manual' | 'ui';
447
460
  /**
448
461
  * Main function executed when the content script is loaded.
449
462
  */
@@ -548,7 +561,7 @@ type EntrypointGroup = Entrypoint | Entrypoint[];
548
561
  */
549
562
  declare function clean(root?: string): Promise<void>;
550
563
 
551
- var version = "0.6.6";
564
+ var version = "0.7.1-alpha1";
552
565
 
553
566
  declare function defineConfig(config: UserConfig): UserConfig;
554
567
 
package/dist/index.d.ts CHANGED
@@ -14,8 +14,9 @@ import { PluginVisualizerOptions } from 'rollup-plugin-visualizer';
14
14
  declare class ContentScriptContext extends AbortController {
15
15
  #private;
16
16
  private readonly contentScriptName;
17
+ readonly options?: Omit<ContentScriptDefinition, "main"> | undefined;
17
18
  static SCRIPT_STARTED_MESSAGE_TYPE: string;
18
- constructor(contentScriptName: string);
19
+ constructor(contentScriptName: string, options?: Omit<ContentScriptDefinition, "main"> | undefined);
19
20
  get isInvalid(): boolean;
20
21
  get isValid(): boolean;
21
22
  /**
@@ -444,6 +445,18 @@ interface ContentScriptDefinition extends ExcludableEntrypoint {
444
445
  * @default "ISOLATED"
445
446
  */
446
447
  world?: 'ISOLATED' | 'MAIN';
448
+ /**
449
+ * Customize how imported/generated styles are injected with the content script. Regardless of the
450
+ * mode selected, CSS will always be built and included in the output directory.
451
+ *
452
+ * - `"manifest"` - Include the CSS in the manifest, under the content script's `css` array.
453
+ * - `"manual"` - Exclude the CSS from the manifest. You are responsible for manually loading it
454
+ * onto the page. Use `browser.runtime.getURL("content-scripts/<name>.css")` to get the file's
455
+ * URL
456
+ *
457
+ * @default "manifest"
458
+ */
459
+ cssInjectionMode?: 'manifest' | 'manual' | 'ui';
447
460
  /**
448
461
  * Main function executed when the content script is loaded.
449
462
  */
@@ -548,7 +561,7 @@ type EntrypointGroup = Entrypoint | Entrypoint[];
548
561
  */
549
562
  declare function clean(root?: string): Promise<void>;
550
563
 
551
- var version = "0.6.6";
564
+ var version = "0.7.1-alpha1";
552
565
 
553
566
  declare function defineConfig(config: UserConfig): UserConfig;
554
567
 
package/dist/index.js CHANGED
@@ -1347,13 +1347,15 @@ function getEntrypointGlobals(config, entrypointName) {
1347
1347
  // src/core/utils/getInternalConfig.ts
1348
1348
  async function getInternalConfig(inlineConfig, command) {
1349
1349
  let userConfig = {};
1350
+ let userConfigMetadata;
1350
1351
  if (inlineConfig.configFile !== false) {
1351
- const loaded = await loadConfig({
1352
+ const { config: loadedConfig, ...metadata } = await loadConfig({
1352
1353
  name: "wxt",
1353
1354
  cwd: inlineConfig.root ?? process.cwd(),
1354
1355
  rcFile: false
1355
1356
  });
1356
- userConfig = loaded.config ?? {};
1357
+ userConfig = loadedConfig ?? {};
1358
+ userConfigMetadata = metadata;
1357
1359
  }
1358
1360
  const mergedConfig = mergeInlineConfig(inlineConfig, userConfig);
1359
1361
  const debug = mergedConfig.debug ?? false;
@@ -1415,7 +1417,8 @@ async function getInternalConfig(inlineConfig, command) {
1415
1417
  analysis: {
1416
1418
  enabled: mergedConfig.analysis?.enabled ?? false,
1417
1419
  template: mergedConfig.analysis?.template ?? "treemap"
1418
- }
1420
+ },
1421
+ userConfigMetadata: userConfigMetadata ?? {}
1419
1422
  };
1420
1423
  finalConfig.vite = (env2) => resolveInternalViteConfig(env2, mergedConfig, finalConfig);
1421
1424
  return finalConfig;
@@ -1701,10 +1704,15 @@ async function buildSingleEntrypoint(entrypoint, config) {
1701
1704
  config.outDir,
1702
1705
  ".js"
1703
1706
  ),
1704
- // Output content script CSS to assets/ with a hash to prevent conflicts. Defaults to
1705
- // "[name].[ext]" in lib mode, which usually results in "style.css". That means multiple
1706
- // content scripts with styles would overwrite each other if it weren't changed below.
1707
- assetFileNames: `assets/${entrypoint.name}.[ext]`
1707
+ // Output content script CSS to `content-scripts/`, but all other scripts are written to
1708
+ // `assets/`.
1709
+ assetFileNames: ({ name }) => {
1710
+ if (entrypoint.type === "content-script" && name?.endsWith("css")) {
1711
+ return `content-scripts/${entrypoint.name}.[ext]`;
1712
+ } else {
1713
+ return `assets/${entrypoint.name}.[ext]`;
1714
+ }
1715
+ }
1708
1716
  }
1709
1717
  }
1710
1718
  },
@@ -2331,14 +2339,14 @@ async function writeTsConfigFile(mainReference, config) {
2331
2339
  "lib": ["DOM", "WebWorker"],
2332
2340
  "skipLibCheck": true,
2333
2341
  "paths": {
2334
- "@@": ["${rootPath}"],
2335
- "@@/*": ["${rootPath}/*"],
2336
- "~~": ["${rootPath}"],
2337
- "~~/*": ["${rootPath}/*"],
2338
2342
  "@": ["${srcPath}"],
2339
2343
  "@/*": ["${srcPath}/*"],
2340
2344
  "~": ["${srcPath}"],
2341
- "~/*": ["${srcPath}/*"]
2345
+ "~/*": ["${srcPath}/*"],
2346
+ "@@": ["${rootPath}"],
2347
+ "@@/*": ["${rootPath}/*"],
2348
+ "~~": ["${rootPath}"],
2349
+ "~~/*": ["${rootPath}/*"]
2342
2350
  }
2343
2351
  },
2344
2352
  "include": [
@@ -2452,6 +2460,7 @@ async function getPackageJson(config) {
2452
2460
 
2453
2461
  // src/core/utils/manifest.ts
2454
2462
  import { produce } from "immer";
2463
+ import * as vite4 from "vite";
2455
2464
  async function writeManifest(manifest, output, config) {
2456
2465
  const str = config.mode === "production" ? JSON.stringify(manifest) : JSON.stringify(manifest, null, 2);
2457
2466
  await fs12.ensureDir(config.outDir);
@@ -2466,34 +2475,37 @@ async function writeManifest(manifest, output, config) {
2466
2475
  }
2467
2476
  async function generateMainfest(entrypoints, buildOutput, config) {
2468
2477
  const pkg = await getPackageJson(config);
2469
- const manifest = Object.assign(
2470
- {
2471
- manifest_version: config.manifestVersion,
2472
- name: pkg?.name,
2473
- description: pkg?.description,
2474
- version: pkg?.version && simplifyVersion(pkg.version),
2475
- // Only add the version name to chromium and if the user hasn't specified a custom version.
2476
- version_name: config.browser !== "firefox" && !config.manifest.version ? pkg?.version : void 0,
2477
- short_name: pkg?.shortName,
2478
- icons: discoverIcons(buildOutput)
2479
- },
2480
- config.manifest
2478
+ const baseManifest = {
2479
+ manifest_version: config.manifestVersion,
2480
+ name: pkg?.name,
2481
+ description: pkg?.description,
2482
+ version: pkg?.version && simplifyVersion(pkg.version),
2483
+ // Only add the version name to chromium and if the user hasn't specified a custom version.
2484
+ version_name: config.browser !== "firefox" && !config.manifest.version ? pkg?.version : void 0,
2485
+ short_name: pkg?.shortName,
2486
+ icons: discoverIcons(buildOutput)
2487
+ };
2488
+ const userManifest = config.manifest;
2489
+ const manifest = vite4.mergeConfig(
2490
+ baseManifest,
2491
+ userManifest
2481
2492
  );
2482
2493
  addEntrypoints(manifest, entrypoints, buildOutput, config);
2483
2494
  if (config.command === "serve")
2484
2495
  addDevModeCsp(manifest, config);
2485
2496
  if (config.command === "serve")
2486
2497
  addDevModePermissions(manifest, config);
2487
- if (manifest.name == null)
2498
+ const finalManifest = produce(manifest, config.transformManifest);
2499
+ if (finalManifest.name == null)
2488
2500
  throw Error(
2489
2501
  "Manifest 'name' is missing. Either:\n1. Set the name in your <rootDir>/package.json\n2. Set a name via the manifest option in your wxt.config.ts"
2490
2502
  );
2491
- if (manifest.version == null) {
2503
+ if (finalManifest.version == null) {
2492
2504
  throw Error(
2493
2505
  "Manifest 'version' is missing. Either:\n1. Add a version in your <rootDir>/package.json\n2. Pass the version via the manifest option in your wxt.config.ts"
2494
2506
  );
2495
2507
  }
2496
- return produce(manifest, config.transformManifest);
2508
+ return finalManifest;
2497
2509
  }
2498
2510
  function simplifyVersion(versionName) {
2499
2511
  const version3 = /^((0|[1-9][0-9]{0,8})([.](0|[1-9][0-9]{0,8})){0,3}).*$/.exec(
@@ -2646,6 +2658,7 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2646
2658
  }
2647
2659
  }
2648
2660
  if (contentScripts?.length) {
2661
+ const cssMap = getContentScriptsCssMap(buildOutput, contentScripts);
2649
2662
  if (config.command === "serve" && config.manifestVersion === 3) {
2650
2663
  const hostPermissions = new Set(manifest.host_permissions ?? []);
2651
2664
  contentScripts.forEach((script) => {
@@ -2670,7 +2683,7 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2670
2683
  ...mapWxtOptionsToContentScript(scripts[0].options),
2671
2684
  // TOOD: Sorting css and js arrays here so we get consistent test results... but we
2672
2685
  // shouldn't have to. Where is the inconsistency coming from?
2673
- css: getContentScriptCssFiles(scripts, buildOutput)?.sort(),
2686
+ css: getContentScriptCssFiles(scripts, cssMap)?.sort(),
2674
2687
  js: scripts.map(
2675
2688
  (entry) => getEntrypointBundlePath(entry, config.outDir, ".js")
2676
2689
  ).sort()
@@ -2681,6 +2694,15 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2681
2694
  manifest.content_scripts.push(...newContentScripts);
2682
2695
  }
2683
2696
  }
2697
+ const contentScriptCssResources = getContentScriptCssWebAccessibleResources(
2698
+ config,
2699
+ contentScripts,
2700
+ cssMap
2701
+ );
2702
+ if (contentScriptCssResources.length > 0) {
2703
+ manifest.web_accessible_resources ??= [];
2704
+ manifest.web_accessible_resources.push(...contentScriptCssResources);
2705
+ }
2684
2706
  }
2685
2707
  }
2686
2708
  function discoverIcons(buildOutput) {
@@ -2745,20 +2767,52 @@ function addDevModePermissions(manifest, config) {
2745
2767
  if (config.manifestVersion === 3)
2746
2768
  addPermission(manifest, "scripting");
2747
2769
  }
2748
- function getContentScriptCssFiles(contentScripts, buildOutput) {
2770
+ function getContentScriptCssFiles(contentScripts, contentScriptCssMap) {
2749
2771
  const css = [];
2750
- const allChunks = buildOutput.steps.flatMap((step) => step.chunks);
2751
2772
  contentScripts.forEach((script) => {
2752
- const relatedCss = allChunks.find(
2753
- (chunk) => chunk.fileName === `assets/${script.name}.css`
2754
- );
2755
- if (relatedCss)
2756
- css.push(relatedCss.fileName);
2773
+ if (script.options.cssInjectionMode === "manual" || script.options.cssInjectionMode === "ui")
2774
+ return;
2775
+ const cssFile = contentScriptCssMap[script.name];
2776
+ if (cssFile == null)
2777
+ return;
2778
+ if (cssFile)
2779
+ css.push(cssFile);
2757
2780
  });
2758
2781
  if (css.length > 0)
2759
2782
  return css;
2760
2783
  return void 0;
2761
2784
  }
2785
+ function getContentScriptCssWebAccessibleResources(config, contentScripts, contentScriptCssMap) {
2786
+ const resources = [];
2787
+ contentScripts.forEach((script) => {
2788
+ if (script.options.cssInjectionMode !== "ui")
2789
+ return;
2790
+ const cssFile = contentScriptCssMap[script.name];
2791
+ if (cssFile == null)
2792
+ return;
2793
+ if (config.manifestVersion === 2) {
2794
+ resources.push(cssFile);
2795
+ } else {
2796
+ resources.push({
2797
+ resources: [cssFile],
2798
+ matches: script.options.matches
2799
+ });
2800
+ }
2801
+ });
2802
+ return resources;
2803
+ }
2804
+ function getContentScriptsCssMap(buildOutput, scripts) {
2805
+ const map = {};
2806
+ const allChunks = buildOutput.steps.flatMap((step) => step.chunks);
2807
+ scripts.forEach((script) => {
2808
+ const relatedCss = allChunks.find(
2809
+ (chunk) => chunk.fileName === `content-scripts/${script.name}.css`
2810
+ );
2811
+ if (relatedCss != null)
2812
+ map[script.name] = relatedCss.fileName;
2813
+ });
2814
+ return map;
2815
+ }
2762
2816
  function addPermission(manifest, permission) {
2763
2817
  manifest.permissions ??= [];
2764
2818
  if (manifest.permissions.includes(permission))
@@ -2774,7 +2828,7 @@ function addHostPermission(manifest, hostPermission) {
2774
2828
 
2775
2829
  // src/core/build.ts
2776
2830
  import pc3 from "picocolors";
2777
- import * as vite4 from "vite";
2831
+ import * as vite5 from "vite";
2778
2832
  import fs14 from "fs-extra";
2779
2833
 
2780
2834
  // src/core/utils/groupEntrypoints.ts
@@ -4078,7 +4132,7 @@ async function buildInternal(config) {
4078
4132
  const target = `${config.browser}-mv${config.manifestVersion}`;
4079
4133
  config.logger.info(
4080
4134
  `${verb} ${pc3.cyan(target)} for ${pc3.cyan(config.mode)} with ${pc3.green(
4081
- `Vite ${vite4.version}`
4135
+ `Vite ${vite5.version}`
4082
4136
  )}`
4083
4137
  );
4084
4138
  const startTime = Date.now();
@@ -4156,7 +4210,7 @@ async function combineAnalysisStats(config) {
4156
4210
  }
4157
4211
 
4158
4212
  // src/core/server.ts
4159
- import * as vite5 from "vite";
4213
+ import * as vite6 from "vite";
4160
4214
 
4161
4215
  // src/core/runners/wsl.ts
4162
4216
  import { relative as relative5 } from "node:path";
@@ -4301,8 +4355,8 @@ async function getServerInfo() {
4301
4355
  }
4302
4356
  async function setupServer(serverInfo, config) {
4303
4357
  const runner = await createExtensionRunner(config);
4304
- const viteServer = await vite5.createServer(
4305
- vite5.mergeConfig(serverInfo, await config.vite(config.env))
4358
+ const viteServer = await vite6.createServer(
4359
+ vite6.mergeConfig(serverInfo, await config.vite(config.env))
4306
4360
  );
4307
4361
  const start = async () => {
4308
4362
  await viteServer.listen(server.port);
@@ -4347,10 +4401,15 @@ function reloadContentScripts(steps, config, server) {
4347
4401
  if (Array.isArray(entry) || entry.type !== "content-script")
4348
4402
  return;
4349
4403
  const js = [getEntrypointBundlePath(entry, config.outDir, ".js")];
4350
- const css = getContentScriptCssFiles([entry], server.currentOutput);
4351
- const { include: _1, exclude: _2, ...options } = entry.options;
4404
+ const cssMap = getContentScriptsCssMap(server.currentOutput, [entry]);
4405
+ const css = getContentScriptCssFiles([entry], cssMap);
4352
4406
  server.reloadContentScript({
4353
- ...options,
4407
+ allFrames: entry.options.allFrames,
4408
+ excludeMatches: entry.options.excludeMatches,
4409
+ matches: entry.options.matches,
4410
+ runAt: entry.options.runAt,
4411
+ // @ts-expect-error: Chrome accepts this, not typed in webextension-polyfill (https://developer.chrome.com/docs/extensions/reference/scripting/#type-RegisteredContentScript)
4412
+ world: entry.options.world,
4354
4413
  js,
4355
4414
  css
4356
4415
  });
@@ -4402,7 +4461,7 @@ async function clean(root = process.cwd()) {
4402
4461
  }
4403
4462
 
4404
4463
  // package.json
4405
- var version2 = "0.6.6";
4464
+ var version2 = "0.7.1-alpha1";
4406
4465
 
4407
4466
  // src/core/utils/defineConfig.ts
4408
4467
  function defineConfig(config) {