wxt 0.17.7 → 0.17.9

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/README.md CHANGED
@@ -35,14 +35,14 @@
35
35
 
36
36
  ## Demo
37
37
 
38
- https://github.com/wxt-dev/wxt/assets/10101283/07359e53-f491-43b6-8e8f-fae94aec8063
38
+ https://github.com/wxt-dev/wxt/assets/10101283/4d678939-1bdb-495c-9c36-3aa281d84c94
39
39
 
40
40
  ## Quick Start
41
41
 
42
42
  Bootstrap a new project:
43
43
 
44
44
  ```sh
45
- pnpx wxt@latest init <project-name>
45
+ pnpm dlx wxt@latest init <project-name>
46
46
  ```
47
47
 
48
48
  Or see the [installation guide](https://wxt.dev/guide/installation.html) to get started with WXT.
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-VBXJIVYU.js";
4
4
 
5
5
  // package.json
6
- var version = "0.17.7";
6
+ var version = "0.17.9";
7
7
 
8
8
  // src/core/utils/paths.ts
9
9
  import systemPath from "node:path";
@@ -47,6 +47,7 @@ async function buildEntrypoints(groups, spinner) {
47
47
  try {
48
48
  steps.push(await wxt.config.builder.build(group));
49
49
  } catch (err) {
50
+ spinner.stop().clear();
50
51
  wxt.logger.error(err);
51
52
  throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
52
53
  }
@@ -1698,7 +1699,7 @@ async function resolveConfig(inlineConfig, command, server) {
1698
1699
  logger.level = LogLevels.debug;
1699
1700
  const browser = mergedConfig.browser ?? "chrome";
1700
1701
  const manifestVersion = mergedConfig.manifestVersion ?? (browser === "firefox" || browser === "safari" ? 2 : 3);
1701
- const mode = mergedConfig.mode ?? (command === "build" ? "production" : "development");
1702
+ const mode = mergedConfig.mode ?? COMMAND_MODES[command];
1702
1703
  const env = { browser, command, manifestVersion, mode };
1703
1704
  const root = path5.resolve(
1704
1705
  inlineConfig.root ?? userConfig.root ?? process.cwd()
@@ -1739,12 +1740,6 @@ async function resolveConfig(inlineConfig, command, server) {
1739
1740
  "~~": root
1740
1741
  }).map(([key, value]) => [key, path5.resolve(root, value)])
1741
1742
  );
1742
- const analysisOutputFile = path5.resolve(
1743
- root,
1744
- mergedConfig.analysis?.outputFile ?? "stats.html"
1745
- );
1746
- const analysisOutputDir = path5.dirname(analysisOutputFile);
1747
- const analysisOutputName = path5.parse(analysisOutputFile).name;
1748
1743
  const finalConfig = {
1749
1744
  browser,
1750
1745
  command,
@@ -1767,24 +1762,14 @@ async function resolveConfig(inlineConfig, command, server) {
1767
1762
  srcDir,
1768
1763
  typesDir,
1769
1764
  wxtDir,
1770
- zip: resolveInternalZipConfig(root, mergedConfig),
1771
- transformManifest(manifest) {
1772
- userConfig.transformManifest?.(manifest);
1773
- inlineConfig.transformManifest?.(manifest);
1774
- },
1775
- analysis: {
1776
- enabled: mergedConfig.analysis?.enabled ?? false,
1777
- template: mergedConfig.analysis?.template ?? "treemap",
1778
- outputFile: analysisOutputFile,
1779
- outputDir: analysisOutputDir,
1780
- outputName: analysisOutputName,
1781
- keepArtifacts: mergedConfig.analysis?.keepArtifacts ?? false
1782
- },
1765
+ zip: resolveZipConfig(root, mergedConfig),
1766
+ transformManifest: mergedConfig.transformManifest,
1767
+ analysis: resolveAnalysisConfig(root, mergedConfig),
1783
1768
  userConfigMetadata: userConfigMetadata ?? {},
1784
1769
  alias,
1785
- experimental: {
1786
- includeBrowserPolyfill: mergedConfig.experimental?.includeBrowserPolyfill ?? true
1787
- },
1770
+ experimental: defu(mergedConfig.experimental, {
1771
+ includeBrowserPolyfill: true
1772
+ }),
1788
1773
  server,
1789
1774
  dev: {
1790
1775
  reloadCommand
@@ -1805,70 +1790,27 @@ async function resolveManifestConfig(env, manifest) {
1805
1790
  return await (typeof manifest === "function" ? manifest(env) : manifest ?? {});
1806
1791
  }
1807
1792
  function mergeInlineConfig(inlineConfig, userConfig) {
1808
- let imports;
1809
- if (inlineConfig.imports === false || userConfig.imports === false) {
1810
- imports = false;
1811
- } else if (userConfig.imports == null && inlineConfig.imports == null) {
1812
- imports = void 0;
1813
- } else {
1814
- imports = defu(inlineConfig.imports ?? {}, userConfig.imports ?? {});
1815
- }
1793
+ const imports = inlineConfig.imports === false || userConfig.imports === false ? false : userConfig.imports == null && inlineConfig.imports == null ? void 0 : defu(inlineConfig.imports ?? {}, userConfig.imports ?? {});
1816
1794
  const manifest = async (env) => {
1817
1795
  const user = await resolveManifestConfig(env, userConfig.manifest);
1818
1796
  const inline = await resolveManifestConfig(env, inlineConfig.manifest);
1819
1797
  return defu(inline, user);
1820
1798
  };
1821
- const runner = defu(
1822
- inlineConfig.runner ?? {},
1823
- userConfig.runner ?? {}
1824
- );
1825
- const zip = defu(
1826
- inlineConfig.zip ?? {},
1827
- userConfig.zip ?? {}
1828
- );
1829
- const hooks = defu(
1830
- inlineConfig.hooks ?? {},
1831
- userConfig.hooks ?? {}
1832
- );
1799
+ const transformManifest = (manifest2) => {
1800
+ userConfig.transformManifest?.(manifest2);
1801
+ inlineConfig.transformManifest?.(manifest2);
1802
+ };
1833
1803
  return {
1834
- root: inlineConfig.root ?? userConfig.root,
1835
- browser: inlineConfig.browser ?? userConfig.browser,
1836
- manifestVersion: inlineConfig.manifestVersion ?? userConfig.manifestVersion,
1837
- configFile: inlineConfig.configFile,
1838
- debug: inlineConfig.debug ?? userConfig.debug,
1839
- entrypointsDir: inlineConfig.entrypointsDir ?? userConfig.entrypointsDir,
1840
- filterEntrypoints: inlineConfig.filterEntrypoints ?? userConfig.filterEntrypoints,
1804
+ ...defu(inlineConfig, userConfig),
1805
+ // Custom merge values
1806
+ transformManifest,
1841
1807
  imports,
1842
- logger: inlineConfig.logger ?? userConfig.logger,
1843
1808
  manifest,
1844
- mode: inlineConfig.mode ?? userConfig.mode,
1845
- publicDir: inlineConfig.publicDir ?? userConfig.publicDir,
1846
- runner,
1847
- srcDir: inlineConfig.srcDir ?? userConfig.srcDir,
1848
- outDir: inlineConfig.outDir ?? userConfig.outDir,
1849
- zip,
1850
- analysis: {
1851
- ...userConfig.analysis,
1852
- ...inlineConfig.analysis
1853
- },
1854
- alias: {
1855
- ...userConfig.alias,
1856
- ...inlineConfig.alias
1857
- },
1858
- experimental: {
1859
- ...userConfig.experimental,
1860
- ...inlineConfig.experimental
1861
- },
1862
- vite: void 0,
1863
- transformManifest: void 0,
1864
- dev: {
1865
- ...userConfig.dev,
1866
- ...inlineConfig.dev
1867
- },
1868
- hooks
1809
+ // Vite builder handles merging vite config internally
1810
+ vite: void 0
1869
1811
  };
1870
1812
  }
1871
- function resolveInternalZipConfig(root, mergedConfig) {
1813
+ function resolveZipConfig(root, mergedConfig) {
1872
1814
  const downloadedPackagesDir = path5.resolve(root, ".wxt/local_modules");
1873
1815
  return {
1874
1816
  name: void 0,
@@ -1893,6 +1835,23 @@ function resolveInternalZipConfig(root, mergedConfig) {
1893
1835
  downloadedPackagesDir
1894
1836
  };
1895
1837
  }
1838
+ function resolveAnalysisConfig(root, mergedConfig) {
1839
+ const analysisOutputFile = path5.resolve(
1840
+ root,
1841
+ mergedConfig.analysis?.outputFile ?? "stats.html"
1842
+ );
1843
+ const analysisOutputDir = path5.dirname(analysisOutputFile);
1844
+ const analysisOutputName = path5.parse(analysisOutputFile).name;
1845
+ return {
1846
+ enabled: mergedConfig.analysis?.enabled ?? false,
1847
+ open: mergedConfig.analysis?.open ?? false,
1848
+ template: mergedConfig.analysis?.template ?? "treemap",
1849
+ outputFile: analysisOutputFile,
1850
+ outputDir: analysisOutputDir,
1851
+ outputName: analysisOutputName,
1852
+ keepArtifacts: mergedConfig.analysis?.keepArtifacts ?? false
1853
+ };
1854
+ }
1896
1855
  async function getUnimportOptions(wxtDir, logger, config) {
1897
1856
  if (config.imports === false)
1898
1857
  return false;
@@ -1945,6 +1904,10 @@ function logMissingDir(logger, name, expected) {
1945
1904
  )}`
1946
1905
  );
1947
1906
  }
1907
+ var COMMAND_MODES = {
1908
+ build: "production",
1909
+ serve: "development"
1910
+ };
1948
1911
 
1949
1912
  // src/core/utils/building/group-entrypoints.ts
1950
1913
  function groupEntrypoints(entrypoints) {
@@ -2377,7 +2340,7 @@ async function generateManifest(entrypoints, buildOutput) {
2377
2340
  addDevModeCsp(manifest);
2378
2341
  if (wxt.config.command === "serve")
2379
2342
  addDevModePermissions(manifest);
2380
- wxt.config.transformManifest(manifest);
2343
+ wxt.config.transformManifest?.(manifest);
2381
2344
  await wxt.hooks.callHook("build:manifestGenerated", wxt, manifest);
2382
2345
  if (wxt.config.manifestVersion === 2) {
2383
2346
  convertWebAccessibleResourcesToMv2(manifest);
@@ -2925,6 +2888,7 @@ var ValidationError = class extends Error {
2925
2888
  // src/core/utils/building/internal-build.ts
2926
2889
  import consola3 from "consola";
2927
2890
  import { mergeJsonOutputs } from "@aklinker1/rollup-plugin-visualizer";
2891
+ import { isCI } from "ci-info";
2928
2892
  async function internalBuild() {
2929
2893
  await wxt.hooks.callHook("build:before", wxt);
2930
2894
  const verb = wxt.config.command === "serve" ? "Pre-rendering" : "Building";
@@ -2967,6 +2931,15 @@ async function internalBuild() {
2967
2931
  `Analysis complete:
2968
2932
  ${pc5.gray("\u2514\u2500")} ${pc5.yellow(statsPath)}`
2969
2933
  );
2934
+ if (wxt.config.analysis.open) {
2935
+ if (isCI) {
2936
+ wxt.logger.debug(`Skipped opening ${pc5.yellow(statsPath)} in CI`);
2937
+ } else {
2938
+ wxt.logger.info(`Opening ${pc5.yellow(statsPath)} in browser...`);
2939
+ const { default: open } = await import("open");
2940
+ open(wxt.config.analysis.outputFile);
2941
+ }
2942
+ }
2970
2943
  }
2971
2944
  return output;
2972
2945
  }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/cli.js CHANGED
@@ -279,6 +279,7 @@ async function buildEntrypoints(groups, spinner) {
279
279
  try {
280
280
  steps.push(await wxt.config.builder.build(group));
281
281
  } catch (err) {
282
+ spinner.stop().clear();
282
283
  wxt.logger.error(err);
283
284
  throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
284
285
  }
@@ -1905,7 +1906,7 @@ async function resolveConfig(inlineConfig, command, server) {
1905
1906
  logger.level = LogLevels.debug;
1906
1907
  const browser = mergedConfig.browser ?? "chrome";
1907
1908
  const manifestVersion = mergedConfig.manifestVersion ?? (browser === "firefox" || browser === "safari" ? 2 : 3);
1908
- const mode = mergedConfig.mode ?? (command === "build" ? "production" : "development");
1909
+ const mode = mergedConfig.mode ?? COMMAND_MODES[command];
1909
1910
  const env = { browser, command, manifestVersion, mode };
1910
1911
  const root = path5.resolve(
1911
1912
  inlineConfig.root ?? userConfig.root ?? process.cwd()
@@ -1946,12 +1947,6 @@ async function resolveConfig(inlineConfig, command, server) {
1946
1947
  "~~": root
1947
1948
  }).map(([key, value]) => [key, path5.resolve(root, value)])
1948
1949
  );
1949
- const analysisOutputFile = path5.resolve(
1950
- root,
1951
- mergedConfig.analysis?.outputFile ?? "stats.html"
1952
- );
1953
- const analysisOutputDir = path5.dirname(analysisOutputFile);
1954
- const analysisOutputName = path5.parse(analysisOutputFile).name;
1955
1950
  const finalConfig = {
1956
1951
  browser,
1957
1952
  command,
@@ -1974,24 +1969,14 @@ async function resolveConfig(inlineConfig, command, server) {
1974
1969
  srcDir,
1975
1970
  typesDir,
1976
1971
  wxtDir,
1977
- zip: resolveInternalZipConfig(root, mergedConfig),
1978
- transformManifest(manifest) {
1979
- userConfig.transformManifest?.(manifest);
1980
- inlineConfig.transformManifest?.(manifest);
1981
- },
1982
- analysis: {
1983
- enabled: mergedConfig.analysis?.enabled ?? false,
1984
- template: mergedConfig.analysis?.template ?? "treemap",
1985
- outputFile: analysisOutputFile,
1986
- outputDir: analysisOutputDir,
1987
- outputName: analysisOutputName,
1988
- keepArtifacts: mergedConfig.analysis?.keepArtifacts ?? false
1989
- },
1972
+ zip: resolveZipConfig(root, mergedConfig),
1973
+ transformManifest: mergedConfig.transformManifest,
1974
+ analysis: resolveAnalysisConfig(root, mergedConfig),
1990
1975
  userConfigMetadata: userConfigMetadata ?? {},
1991
1976
  alias,
1992
- experimental: {
1993
- includeBrowserPolyfill: mergedConfig.experimental?.includeBrowserPolyfill ?? true
1994
- },
1977
+ experimental: defu(mergedConfig.experimental, {
1978
+ includeBrowserPolyfill: true
1979
+ }),
1995
1980
  server,
1996
1981
  dev: {
1997
1982
  reloadCommand
@@ -2012,70 +1997,27 @@ async function resolveManifestConfig(env, manifest) {
2012
1997
  return await (typeof manifest === "function" ? manifest(env) : manifest ?? {});
2013
1998
  }
2014
1999
  function mergeInlineConfig(inlineConfig, userConfig) {
2015
- let imports;
2016
- if (inlineConfig.imports === false || userConfig.imports === false) {
2017
- imports = false;
2018
- } else if (userConfig.imports == null && inlineConfig.imports == null) {
2019
- imports = void 0;
2020
- } else {
2021
- imports = defu(inlineConfig.imports ?? {}, userConfig.imports ?? {});
2022
- }
2000
+ const imports = inlineConfig.imports === false || userConfig.imports === false ? false : userConfig.imports == null && inlineConfig.imports == null ? void 0 : defu(inlineConfig.imports ?? {}, userConfig.imports ?? {});
2023
2001
  const manifest = async (env) => {
2024
2002
  const user = await resolveManifestConfig(env, userConfig.manifest);
2025
2003
  const inline = await resolveManifestConfig(env, inlineConfig.manifest);
2026
2004
  return defu(inline, user);
2027
2005
  };
2028
- const runner = defu(
2029
- inlineConfig.runner ?? {},
2030
- userConfig.runner ?? {}
2031
- );
2032
- const zip2 = defu(
2033
- inlineConfig.zip ?? {},
2034
- userConfig.zip ?? {}
2035
- );
2036
- const hooks = defu(
2037
- inlineConfig.hooks ?? {},
2038
- userConfig.hooks ?? {}
2039
- );
2006
+ const transformManifest = (manifest2) => {
2007
+ userConfig.transformManifest?.(manifest2);
2008
+ inlineConfig.transformManifest?.(manifest2);
2009
+ };
2040
2010
  return {
2041
- root: inlineConfig.root ?? userConfig.root,
2042
- browser: inlineConfig.browser ?? userConfig.browser,
2043
- manifestVersion: inlineConfig.manifestVersion ?? userConfig.manifestVersion,
2044
- configFile: inlineConfig.configFile,
2045
- debug: inlineConfig.debug ?? userConfig.debug,
2046
- entrypointsDir: inlineConfig.entrypointsDir ?? userConfig.entrypointsDir,
2047
- filterEntrypoints: inlineConfig.filterEntrypoints ?? userConfig.filterEntrypoints,
2011
+ ...defu(inlineConfig, userConfig),
2012
+ // Custom merge values
2013
+ transformManifest,
2048
2014
  imports,
2049
- logger: inlineConfig.logger ?? userConfig.logger,
2050
2015
  manifest,
2051
- mode: inlineConfig.mode ?? userConfig.mode,
2052
- publicDir: inlineConfig.publicDir ?? userConfig.publicDir,
2053
- runner,
2054
- srcDir: inlineConfig.srcDir ?? userConfig.srcDir,
2055
- outDir: inlineConfig.outDir ?? userConfig.outDir,
2056
- zip: zip2,
2057
- analysis: {
2058
- ...userConfig.analysis,
2059
- ...inlineConfig.analysis
2060
- },
2061
- alias: {
2062
- ...userConfig.alias,
2063
- ...inlineConfig.alias
2064
- },
2065
- experimental: {
2066
- ...userConfig.experimental,
2067
- ...inlineConfig.experimental
2068
- },
2069
- vite: void 0,
2070
- transformManifest: void 0,
2071
- dev: {
2072
- ...userConfig.dev,
2073
- ...inlineConfig.dev
2074
- },
2075
- hooks
2016
+ // Vite builder handles merging vite config internally
2017
+ vite: void 0
2076
2018
  };
2077
2019
  }
2078
- function resolveInternalZipConfig(root, mergedConfig) {
2020
+ function resolveZipConfig(root, mergedConfig) {
2079
2021
  const downloadedPackagesDir = path5.resolve(root, ".wxt/local_modules");
2080
2022
  return {
2081
2023
  name: void 0,
@@ -2100,6 +2042,23 @@ function resolveInternalZipConfig(root, mergedConfig) {
2100
2042
  downloadedPackagesDir
2101
2043
  };
2102
2044
  }
2045
+ function resolveAnalysisConfig(root, mergedConfig) {
2046
+ const analysisOutputFile = path5.resolve(
2047
+ root,
2048
+ mergedConfig.analysis?.outputFile ?? "stats.html"
2049
+ );
2050
+ const analysisOutputDir = path5.dirname(analysisOutputFile);
2051
+ const analysisOutputName = path5.parse(analysisOutputFile).name;
2052
+ return {
2053
+ enabled: mergedConfig.analysis?.enabled ?? false,
2054
+ open: mergedConfig.analysis?.open ?? false,
2055
+ template: mergedConfig.analysis?.template ?? "treemap",
2056
+ outputFile: analysisOutputFile,
2057
+ outputDir: analysisOutputDir,
2058
+ outputName: analysisOutputName,
2059
+ keepArtifacts: mergedConfig.analysis?.keepArtifacts ?? false
2060
+ };
2061
+ }
2103
2062
  async function getUnimportOptions(wxtDir, logger, config) {
2104
2063
  if (config.imports === false)
2105
2064
  return false;
@@ -2152,6 +2111,10 @@ function logMissingDir(logger, name, expected) {
2152
2111
  )}`
2153
2112
  );
2154
2113
  }
2114
+ var COMMAND_MODES = {
2115
+ build: "production",
2116
+ serve: "development"
2117
+ };
2155
2118
 
2156
2119
  // src/core/utils/building/group-entrypoints.ts
2157
2120
  function groupEntrypoints(entrypoints) {
@@ -2415,7 +2378,7 @@ function getChunkSortWeight(filename) {
2415
2378
  import pc4 from "picocolors";
2416
2379
 
2417
2380
  // package.json
2418
- var version = "0.17.7";
2381
+ var version = "0.17.9";
2419
2382
 
2420
2383
  // src/core/utils/log/printHeader.ts
2421
2384
  import { consola as consola2 } from "consola";
@@ -2593,7 +2556,7 @@ async function generateManifest(entrypoints, buildOutput) {
2593
2556
  addDevModeCsp(manifest);
2594
2557
  if (wxt.config.command === "serve")
2595
2558
  addDevModePermissions(manifest);
2596
- wxt.config.transformManifest(manifest);
2559
+ wxt.config.transformManifest?.(manifest);
2597
2560
  await wxt.hooks.callHook("build:manifestGenerated", wxt, manifest);
2598
2561
  if (wxt.config.manifestVersion === 2) {
2599
2562
  convertWebAccessibleResourcesToMv2(manifest);
@@ -3141,6 +3104,7 @@ var ValidationError = class extends Error {
3141
3104
  // src/core/utils/building/internal-build.ts
3142
3105
  import consola3 from "consola";
3143
3106
  import { mergeJsonOutputs } from "@aklinker1/rollup-plugin-visualizer";
3107
+ import { isCI } from "ci-info";
3144
3108
  async function internalBuild() {
3145
3109
  await wxt.hooks.callHook("build:before", wxt);
3146
3110
  const verb = wxt.config.command === "serve" ? "Pre-rendering" : "Building";
@@ -3183,6 +3147,15 @@ async function internalBuild() {
3183
3147
  `Analysis complete:
3184
3148
  ${pc5.gray("\u2514\u2500")} ${pc5.yellow(statsPath)}`
3185
3149
  );
3150
+ if (wxt.config.analysis.open) {
3151
+ if (isCI) {
3152
+ wxt.logger.debug(`Skipped opening ${pc5.yellow(statsPath)} in CI`);
3153
+ } else {
3154
+ wxt.logger.info(`Opening ${pc5.yellow(statsPath)} in browser...`);
3155
+ const { default: open } = await import("open");
3156
+ open(wxt.config.analysis.outputFile);
3157
+ }
3158
+ }
3186
3159
  }
3187
3160
  return output;
3188
3161
  }
@@ -3529,30 +3502,33 @@ function createFileReloader(server) {
3529
3502
  `Changed: ${Array.from(new Set(fileChanges)).map((file) => pc7.dim(relative10(wxt.config.root, file))).join(", ")}`
3530
3503
  );
3531
3504
  const allEntrypoints = await findEntrypoints();
3532
- const { output: newOutput } = await rebuild(
3533
- allEntrypoints,
3534
- // TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
3535
- changes.rebuildGroups,
3536
- changes.cachedOutput
3537
- );
3538
- server.currentOutput = newOutput;
3539
- switch (changes.type) {
3540
- case "extension-reload":
3541
- server.reloadExtension();
3542
- consola5.success(`Reloaded extension`);
3543
- break;
3544
- case "html-reload":
3545
- const { reloadedNames } = reloadHtmlPages(
3546
- changes.rebuildGroups,
3547
- server
3548
- );
3549
- consola5.success(`Reloaded: ${getFilenameList(reloadedNames)}`);
3550
- break;
3551
- case "content-script-reload":
3552
- reloadContentScripts(changes.changedSteps, server);
3553
- const rebuiltNames = changes.rebuildGroups.flat().map((entry) => entry.name);
3554
- consola5.success(`Reloaded: ${getFilenameList(rebuiltNames)}`);
3555
- break;
3505
+ try {
3506
+ const { output: newOutput } = await rebuild(
3507
+ allEntrypoints,
3508
+ // TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
3509
+ changes.rebuildGroups,
3510
+ changes.cachedOutput
3511
+ );
3512
+ server.currentOutput = newOutput;
3513
+ switch (changes.type) {
3514
+ case "extension-reload":
3515
+ server.reloadExtension();
3516
+ consola5.success(`Reloaded extension`);
3517
+ break;
3518
+ case "html-reload":
3519
+ const { reloadedNames } = reloadHtmlPages(
3520
+ changes.rebuildGroups,
3521
+ server
3522
+ );
3523
+ consola5.success(`Reloaded: ${getFilenameList(reloadedNames)}`);
3524
+ break;
3525
+ case "content-script-reload":
3526
+ reloadContentScripts(changes.changedSteps, server);
3527
+ const rebuiltNames = changes.rebuildGroups.flat().map((entry) => entry.name);
3528
+ consola5.success(`Reloaded: ${getFilenameList(rebuiltNames)}`);
3529
+ break;
3530
+ }
3531
+ } catch (err) {
3556
3532
  }
3557
3533
  });
3558
3534
  };
@@ -3663,6 +3639,16 @@ async function initialize(options) {
3663
3639
  input.directory ??= options.directory;
3664
3640
  input.template ??= defaultTemplate;
3665
3641
  input.packageManager ??= options.packageManager;
3642
+ const isExists = await fs15.pathExists(input.directory);
3643
+ if (isExists) {
3644
+ const isEmpty = (await fs15.readdir(input.directory)).length === 0;
3645
+ if (!isEmpty) {
3646
+ consola6.error(
3647
+ `The directory ${path8.resolve(input.directory)} is not empty. Aborted.`
3648
+ );
3649
+ process.exit(1);
3650
+ }
3651
+ }
3666
3652
  await cloneProject(input);
3667
3653
  const cdPath = path8.relative(process.cwd(), path8.resolve(input.directory));
3668
3654
  console.log();
@@ -3692,7 +3678,8 @@ async function listTemplates() {
3692
3678
  return l.name.localeCompare(r.name);
3693
3679
  });
3694
3680
  } catch (err) {
3695
- throw Error(`Cannot load templates: ${JSON.stringify(err, null, 2)}`);
3681
+ consola6.error(err);
3682
+ throw Error(`Failed to load templates`);
3696
3683
  }
3697
3684
  }
3698
3685
  async function cloneProject({
@@ -3758,7 +3745,7 @@ async function zip(config) {
3758
3745
  const applyTemplate = (template) => template.replaceAll("{{name}}", projectName).replaceAll("{{browser}}", wxt.config.browser).replaceAll(
3759
3746
  "{{version}}",
3760
3747
  output.manifest.version_name ?? output.manifest.version
3761
- ).replaceAll("{{manifestVersion}}", `mv${wxt.config.manifestVersion}`);
3748
+ ).replaceAll("{{mode}}", wxt.config.mode).replaceAll("{{manifestVersion}}", `mv${wxt.config.manifestVersion}`);
3762
3749
  await fs16.ensureDir(wxt.config.outBaseDir);
3763
3750
  const outZipFilename = applyTemplate(wxt.config.zip.artifactTemplate);
3764
3751
  const outZipPath = path9.resolve(wxt.config.outBaseDir, outZipFilename);
@@ -3953,7 +3940,7 @@ cli.command("build [root]", "build for production").option("-c, --config <file>"
3953
3940
  {
3954
3941
  type: []
3955
3942
  }
3956
- ).option("--mv3", "target manifest v3").option("--mv2", "target manifest v2").option("--analyze", "visualize extension bundle").action(
3943
+ ).option("--mv3", "target manifest v3").option("--mv2", "target manifest v2").option("--analyze", "visualize extension bundle").option("--analyze-open", "automatically open stats.html in browser").action(
3957
3944
  wrapAction(async (root, flags) => {
3958
3945
  await build({
3959
3946
  root,
@@ -3962,7 +3949,10 @@ cli.command("build [root]", "build for production").option("-c, --config <file>"
3962
3949
  manifestVersion: flags.mv3 ? 3 : flags.mv2 ? 2 : void 0,
3963
3950
  configFile: flags.config,
3964
3951
  debug: flags.debug,
3965
- analysis: flags.analyze ? { enabled: true } : void 0,
3952
+ analysis: flags.analyze ? {
3953
+ enabled: true,
3954
+ open: flags.analyzeOpen
3955
+ } : void 0,
3966
3956
  filterEntrypoints: getArrayFromFlags(flags, "filterEntrypoint")
3967
3957
  });
3968
3958
  })
package/dist/client.d.ts CHANGED
@@ -167,7 +167,7 @@ interface ContentScriptAnchoredOptions {
167
167
  * In combination with `anchor`, decide how to add the UI to the DOM.
168
168
  *
169
169
  * - `"last"` (default) - Add the UI as the last child of the `anchor` element
170
- * - `"first"` - Add the UI as the last child of the `anchor` element
170
+ * - `"first"` - Add the UI as the first child of the `anchor` element
171
171
  * - `"replace"` - Replace the `anchor` element with the UI.
172
172
  * - `"before"` - Add the UI as the sibling before the `anchor` element
173
173
  * - `"after"` - Add the UI as the sibling after the `anchor` element
@@ -235,10 +235,11 @@ interface InlineConfig {
235
235
  *
236
236
  * Available template variables:
237
237
  *
238
- * - `{{name}}` - The project's name converted to kebab-case
239
- * - `{{version}}` - The version_name or version from the manifest
240
- * - `{{browser}}` - The target browser from the `--browser` CLI flag
241
- * - `{{manifestVersion}}` - Either "2" or "3"
238
+ * - <span v-pre>`{{name}}`</span> - The project's name converted to kebab-case
239
+ * - <span v-pre>`{{version}}`</span> - The version_name or version from the manifest
240
+ * - <span v-pre>`{{browser}}`</span> - The target browser from the `--browser` CLI flag
241
+ * - <span v-pre>`{{mode}}`</span> - The current mode
242
+ * - <span v-pre>`{{manifestVersion}}`</span> - Either "2" or "3"
242
243
  *
243
244
  * @default "{{name}}-{{version}}-{{browser}}.zip"
244
245
  */
@@ -248,10 +249,11 @@ interface InlineConfig {
248
249
  *
249
250
  * Available template variables:
250
251
  *
251
- * - `{{name}}` - The project's name converted to kebab-case
252
- * - `{{version}}` - The version_name or version from the manifest
253
- * - `{{browser}}` - The target browser from the `--browser` CLI flag
254
- * - `{{manifestVersion}}` - Either "2" or "3"
252
+ * - <span v-pre>`{{name}}`</span> - The project's name converted to kebab-case
253
+ * - <span v-pre>`{{version}}`</span> - The version_name or version from the manifest
254
+ * - <span v-pre>`{{browser}}`</span> - The target browser from the `--browser` CLI flag
255
+ * - <span v-pre>`{{mode}}`</span> - The current mode
256
+ * - <span v-pre>`{{manifestVersion}}`</span> - Either "2" or "3"
255
257
  *
256
258
  * @default "{{name}}-{{version}}-sources.zip"
257
259
  */
@@ -346,6 +348,12 @@ interface InlineConfig {
346
348
  * @default false
347
349
  */
348
350
  enabled?: boolean;
351
+ /**
352
+ * Set to true to automatically open the `stats.html` file when the build is finished. When building in CI, the browser will never open.
353
+ *
354
+ * @default false
355
+ */
356
+ open?: boolean;
349
357
  /**
350
358
  * When running `wxt build --analyze` or setting `analysis.enabled` to true, customize how the
351
359
  * bundle will be visualized. See
@@ -794,7 +802,7 @@ interface ConfigEnv {
794
802
  /**
795
803
  * The command used to run WXT. `"serve"` during development and `"build"` for any other command.
796
804
  */
797
- command: 'build' | 'serve';
805
+ command: WxtCommand;
798
806
  /**
799
807
  * Browser passed in from the CLI via the `-b` or `--browser` flag. Defaults to `"chrome"` when not passed.
800
808
  */
@@ -806,6 +814,7 @@ interface ConfigEnv {
806
814
  */
807
815
  manifestVersion: 2 | 3;
808
816
  }
817
+ type WxtCommand = 'build' | 'serve';
809
818
  /**
810
819
  * Configure how the browser starts up.
811
820
  */
@@ -1023,7 +1032,7 @@ interface ResolvedConfig {
1023
1032
  */
1024
1033
  wxtModuleDir: string;
1025
1034
  mode: string;
1026
- command: 'build' | 'serve';
1035
+ command: WxtCommand;
1027
1036
  browser: TargetBrowser;
1028
1037
  manifestVersion: TargetManifestVersion;
1029
1038
  env: ConfigEnv;
@@ -1043,9 +1052,13 @@ interface ResolvedConfig {
1043
1052
  downloadedPackagesDir: string;
1044
1053
  downloadPackages: string[];
1045
1054
  };
1046
- transformManifest: (manifest: Manifest.WebExtensionManifest) => void;
1055
+ /**
1056
+ * @deprecated Use `build:manifestGenerated` hook instead.
1057
+ */
1058
+ transformManifest?: (manifest: Manifest.WebExtensionManifest) => void;
1047
1059
  analysis: {
1048
1060
  enabled: boolean;
1061
+ open: boolean;
1049
1062
  template: NonNullable<PluginVisualizerOptions['template']>;
1050
1063
  /** Absolute file path to the `stats.html` file */
1051
1064
  outputFile: string;
@@ -1153,4 +1166,4 @@ interface Dependency {
1153
1166
  version: string;
1154
1167
  }
1155
1168
 
1156
- export type { EslintGlobalsPropValue as $, UserManifest as A, BuildOutput as B, ContentScriptEntrypoint as C, UserManifestFn as D, ExtensionRunnerConfig as E, ConfigEnv as F, GenericEntrypoint as G, WxtBuilder as H, InlineConfig as I, WxtBuilderServer as J, ServerInfo as K, Logger as L, MainWorldContentScriptEntrypointOptions as M, HookResult as N, OutputFile as O, PopupEntrypointOptions as P, WxtHooks as Q, ReloadContentScriptPayload as R, SidepanelEntrypointOptions as S, TargetBrowser as T, UserConfig as U, Wxt as V, WxtDevServer as W, ResolvedConfig as X, FsCache as Y, ExtensionRunner as Z, VirtualEntrypointType as _, WxtViteConfig as a, Eslintrc as a0, ResolvedEslintrc as a1, WxtUnimportOptions as a2, WxtResolvedUnimportOptions as a3, WxtPackageManager as a4, Dependency as a5, OutputChunk as b, OutputAsset as c, BuildStepOutput as d, TargetManifestVersion as e, BaseEntrypointOptions as f, BackgroundEntrypointOptions as g, BaseContentScriptEntrypointOptions as h, IsolatedWorldContentScriptEntrypointOptions as i, OptionsEntrypointOptions as j, BaseEntrypoint as k, BackgroundEntrypoint as l, PopupEntrypoint as m, OptionsEntrypoint as n, SidepanelEntrypoint as o, Entrypoint as p, EntrypointGroup as q, OnContentScriptStopped as r, IsolatedWorldContentScriptDefinition as s, MainWorldContentScriptDefinition as t, ContentScriptDefinition as u, BackgroundDefinition as v, UnlistedScriptDefinition as w, PerBrowserOption as x, PerBrowserMap as y, ResolvedPerBrowserOptions as z };
1169
+ export type { VirtualEntrypointType as $, UserManifest as A, BuildOutput as B, ContentScriptEntrypoint as C, UserManifestFn as D, ExtensionRunnerConfig as E, ConfigEnv as F, GenericEntrypoint as G, WxtCommand as H, InlineConfig as I, WxtBuilder as J, WxtBuilderServer as K, Logger as L, MainWorldContentScriptEntrypointOptions as M, ServerInfo as N, OutputFile as O, PopupEntrypointOptions as P, HookResult as Q, ReloadContentScriptPayload as R, SidepanelEntrypointOptions as S, TargetBrowser as T, UserConfig as U, WxtHooks as V, WxtDevServer as W, Wxt as X, ResolvedConfig as Y, FsCache as Z, ExtensionRunner as _, WxtViteConfig as a, EslintGlobalsPropValue as a0, Eslintrc as a1, ResolvedEslintrc as a2, WxtUnimportOptions as a3, WxtResolvedUnimportOptions as a4, WxtPackageManager as a5, Dependency as a6, OutputChunk as b, OutputAsset as c, BuildStepOutput as d, TargetManifestVersion as e, BaseEntrypointOptions as f, BackgroundEntrypointOptions as g, BaseContentScriptEntrypointOptions as h, IsolatedWorldContentScriptEntrypointOptions as i, OptionsEntrypointOptions as j, BaseEntrypoint as k, BackgroundEntrypoint as l, PopupEntrypoint as m, OptionsEntrypoint as n, SidepanelEntrypoint as o, Entrypoint as p, EntrypointGroup as q, OnContentScriptStopped as r, IsolatedWorldContentScriptDefinition as s, MainWorldContentScriptDefinition as t, ContentScriptDefinition as u, BackgroundDefinition as v, UnlistedScriptDefinition as w, PerBrowserOption as x, PerBrowserMap as y, ResolvedPerBrowserOptions as z };