wxt 0.20.13 → 0.20.14

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 (278) hide show
  1. package/dist/browser.d.mts +20 -0
  2. package/dist/browser.mjs +18 -3
  3. package/dist/builtin-modules/index.mjs +7 -2
  4. package/dist/builtin-modules/unimport.mjs +69 -75
  5. package/dist/cli/cli-utils.mjs +52 -50
  6. package/dist/cli/commands.mjs +77 -103
  7. package/dist/cli/index.d.mts +1 -0
  8. package/dist/cli/index.mjs +9 -4
  9. package/dist/core/{build.d.ts → build.d.mts} +6 -2
  10. package/dist/core/build.mjs +23 -4
  11. package/dist/core/builders/vite/index.mjs +292 -343
  12. package/dist/core/builders/vite/plugins/bundleAnalysis.mjs +11 -12
  13. package/dist/core/builders/vite/plugins/cssEntrypoints.mjs +27 -20
  14. package/dist/core/builders/vite/plugins/defineImportMeta.mjs +17 -12
  15. package/dist/core/builders/vite/plugins/devHtmlPrerender.mjs +104 -136
  16. package/dist/core/builders/vite/plugins/devServerGlobals.mjs +15 -14
  17. package/dist/core/builders/vite/plugins/download.mjs +23 -12
  18. package/dist/core/builders/vite/plugins/entrypointGroupGlobals.mjs +18 -14
  19. package/dist/core/builders/vite/plugins/extensionApiMock.mjs +31 -33
  20. package/dist/core/builders/vite/plugins/globals.mjs +14 -13
  21. package/dist/core/builders/vite/plugins/iifeFooter.mjs +17 -11
  22. package/dist/core/builders/vite/plugins/index.mjs +18 -16
  23. package/dist/core/builders/vite/plugins/noopBackground.mjs +21 -15
  24. package/dist/core/builders/vite/plugins/removeEntrypointMainFunction.mjs +25 -23
  25. package/dist/core/builders/vite/plugins/resolveAppConfig.mjs +25 -23
  26. package/dist/core/builders/vite/plugins/resolveVirtualModules.mjs +27 -26
  27. package/dist/core/builders/vite/plugins/tsconfigPaths.mjs +11 -11
  28. package/dist/core/builders/vite/plugins/wxtPluginLoader.mjs +41 -47
  29. package/dist/core/{clean.d.ts → clean.d.mts} +7 -3
  30. package/dist/core/clean.mjs +38 -35
  31. package/dist/core/{create-server.d.ts → create-server.d.mts} +6 -2
  32. package/dist/core/create-server.mjs +236 -247
  33. package/dist/core/define-config.d.mts +6 -0
  34. package/dist/core/define-config.mjs +6 -2
  35. package/dist/core/define-web-ext-config.d.mts +13 -0
  36. package/dist/core/define-web-ext-config.mjs +16 -7
  37. package/dist/core/generate-wxt-dir.mjs +109 -148
  38. package/dist/core/index.d.mts +8 -0
  39. package/dist/core/index.mjs +10 -8
  40. package/dist/core/initialize.d.mts +8 -0
  41. package/dist/core/initialize.mjs +110 -124
  42. package/dist/core/keyboard-shortcuts.mjs +30 -28
  43. package/dist/core/package-managers/bun.mjs +18 -16
  44. package/dist/core/package-managers/deno.mjs +12 -8
  45. package/dist/core/package-managers/index.mjs +52 -60
  46. package/dist/core/package-managers/npm.mjs +51 -52
  47. package/dist/core/package-managers/pnpm.mjs +21 -18
  48. package/dist/core/package-managers/yarn.mjs +31 -28
  49. package/dist/core/prepare.d.mts +6 -0
  50. package/dist/core/prepare.mjs +12 -7
  51. package/dist/core/resolve-config.mjs +393 -462
  52. package/dist/core/runners/index.mjs +11 -6
  53. package/dist/core/runners/manual.mjs +16 -14
  54. package/dist/core/runners/safari.mjs +16 -14
  55. package/dist/core/runners/web-ext.mjs +62 -83
  56. package/dist/core/runners/wsl.mjs +16 -14
  57. package/dist/core/utils/arrays.mjs +23 -12
  58. package/dist/core/utils/building/build-entrypoints.mjs +44 -40
  59. package/dist/core/utils/building/detect-dev-changes.mjs +84 -105
  60. package/dist/core/utils/building/find-entrypoints.mjs +275 -359
  61. package/dist/core/utils/building/group-entrypoints.mjs +42 -35
  62. package/dist/core/utils/building/index.mjs +8 -6
  63. package/dist/core/utils/building/internal-build.mjs +87 -102
  64. package/dist/core/utils/building/rebuild.mjs +50 -30
  65. package/dist/core/utils/cache.mjs +29 -18
  66. package/dist/core/utils/constants.mjs +9 -1
  67. package/dist/core/utils/content-scripts.mjs +56 -54
  68. package/dist/core/utils/content-security-policy.mjs +36 -39
  69. package/dist/core/utils/entrypoints.mjs +51 -28
  70. package/dist/core/utils/env.mjs +22 -17
  71. package/dist/core/utils/environments/browser-environment.mjs +13 -12
  72. package/dist/core/utils/environments/environment.mjs +36 -33
  73. package/dist/core/utils/environments/extension-environment.mjs +15 -10
  74. package/dist/core/utils/environments/index.mjs +4 -2
  75. package/dist/core/utils/eslint.mjs +11 -10
  76. package/dist/core/utils/fs.mjs +23 -11
  77. package/dist/core/utils/globals.mjs +53 -51
  78. package/dist/core/utils/i18n.mjs +41 -32
  79. package/dist/core/utils/log/index.mjs +6 -4
  80. package/dist/core/utils/log/printBuildSummary.mjs +20 -25
  81. package/dist/core/utils/log/printFileList.mjs +30 -33
  82. package/dist/core/utils/log/printHeader.mjs +10 -5
  83. package/dist/core/utils/log/printTable.mjs +19 -21
  84. package/dist/core/utils/manifest.mjs +364 -479
  85. package/dist/core/utils/minimatch-multiple.mjs +26 -15
  86. package/dist/core/utils/network.mjs +30 -33
  87. package/dist/core/utils/number.mjs +7 -3
  88. package/dist/core/utils/package.mjs +20 -13
  89. package/dist/core/utils/paths.mjs +26 -7
  90. package/dist/core/utils/strings.mjs +19 -14
  91. package/dist/core/utils/syntax-errors.mjs +14 -16
  92. package/dist/core/utils/time.mjs +19 -15
  93. package/dist/core/utils/transform.mjs +129 -160
  94. package/dist/core/utils/types.d.mts +6 -0
  95. package/dist/core/utils/validation.mjs +43 -50
  96. package/dist/core/utils/virtual-modules.mjs +20 -12
  97. package/dist/core/utils/wsl.mjs +10 -3
  98. package/dist/core/wxt.mjs +66 -60
  99. package/dist/core/{zip.d.ts → zip.d.mts} +6 -2
  100. package/dist/core/zip.mjs +116 -140
  101. package/dist/index.d.mts +12 -0
  102. package/dist/index.mjs +12 -3
  103. package/dist/{modules.d.ts → modules.d.mts} +14 -16
  104. package/dist/modules.mjs +181 -51
  105. package/dist/testing/fake-browser.d.mts +2 -0
  106. package/dist/testing/fake-browser.mjs +3 -1
  107. package/dist/testing/index.d.mts +3 -0
  108. package/dist/testing/index.mjs +4 -2
  109. package/dist/testing/{wxt-vitest-plugin.d.ts → wxt-vitest-plugin.d.mts} +7 -9
  110. package/dist/testing/wxt-vitest-plugin.mjs +38 -19
  111. package/dist/types.d.mts +1453 -0
  112. package/dist/utils/app-config.d.mts +6 -0
  113. package/dist/utils/app-config.mjs +8 -2
  114. package/dist/utils/content-script-context.d.mts +137 -0
  115. package/dist/utils/content-script-context.mjs +192 -175
  116. package/dist/utils/content-script-ui/iframe.d.mts +42 -0
  117. package/dist/utils/content-script-ui/iframe.mjs +42 -27
  118. package/dist/utils/content-script-ui/integrated.d.mts +37 -0
  119. package/dist/utils/content-script-ui/integrated.mjs +36 -29
  120. package/dist/utils/content-script-ui/shadow-root.d.mts +80 -0
  121. package/dist/utils/content-script-ui/shadow-root.mjs +75 -82
  122. package/dist/utils/content-script-ui/shared.mjs +117 -150
  123. package/dist/utils/content-script-ui/types.d.mts +107 -0
  124. package/dist/utils/content-script-ui/types.mjs +1 -0
  125. package/dist/utils/{define-app-config.d.ts → define-app-config.d.mts} +5 -3
  126. package/dist/utils/define-app-config.mjs +22 -2
  127. package/dist/utils/define-background.d.mts +7 -0
  128. package/dist/utils/define-background.mjs +7 -3
  129. package/dist/utils/define-content-script.d.mts +6 -0
  130. package/dist/utils/define-content-script.mjs +6 -2
  131. package/dist/utils/define-unlisted-script.d.mts +7 -0
  132. package/dist/utils/define-unlisted-script.mjs +7 -3
  133. package/dist/utils/define-wxt-plugin.d.mts +6 -0
  134. package/dist/utils/define-wxt-plugin.mjs +6 -2
  135. package/dist/utils/inject-script.d.mts +41 -0
  136. package/dist/utils/inject-script.mjs +44 -34
  137. package/dist/utils/internal/custom-events.d.mts +9 -0
  138. package/dist/utils/internal/custom-events.mjs +18 -10
  139. package/dist/utils/internal/location-watcher.mjs +23 -20
  140. package/dist/utils/internal/logger.mjs +15 -12
  141. package/dist/utils/match-patterns.d.mts +1 -0
  142. package/dist/utils/match-patterns.mjs +3 -1
  143. package/dist/utils/{split-shadow-root-css.d.ts → split-shadow-root-css.d.mts} +6 -3
  144. package/dist/utils/split-shadow-root-css.mjs +16 -7
  145. package/dist/utils/storage.d.mts +1 -0
  146. package/dist/utils/storage.mjs +3 -1
  147. package/dist/version.d.mts +4 -0
  148. package/dist/version.mjs +5 -1
  149. package/dist/virtual/background-entrypoint.d.mts +4 -0
  150. package/dist/virtual/background-entrypoint.mjs +146 -161
  151. package/dist/virtual/content-script-isolated-world-entrypoint.d.mts +4 -0
  152. package/dist/virtual/content-script-isolated-world-entrypoint.mjs +26 -27
  153. package/dist/virtual/content-script-main-world-entrypoint.d.mts +4 -0
  154. package/dist/virtual/content-script-main-world-entrypoint.mjs +24 -24
  155. package/dist/virtual/mock-browser.d.mts +6 -0
  156. package/dist/virtual/mock-browser.mjs +5 -3
  157. package/dist/virtual/reload-html.d.mts +1 -0
  158. package/dist/virtual/reload-html.mjs +60 -53
  159. package/dist/virtual/unlisted-script-entrypoint.d.mts +4 -0
  160. package/dist/virtual/unlisted-script-entrypoint.mjs +35 -43
  161. package/package.json +47 -49
  162. package/dist/browser.d.ts +0 -30
  163. package/dist/builtin-modules/index.d.ts +0 -2
  164. package/dist/builtin-modules/unimport.d.ts +0 -5
  165. package/dist/cli/cli-utils.d.ts +0 -25
  166. package/dist/cli/commands.d.ts +0 -2
  167. package/dist/cli/index.d.ts +0 -1
  168. package/dist/core/builders/vite/index.d.ts +0 -7
  169. package/dist/core/builders/vite/plugins/bundleAnalysis.d.ts +0 -7
  170. package/dist/core/builders/vite/plugins/cssEntrypoints.d.ts +0 -13
  171. package/dist/core/builders/vite/plugins/defineImportMeta.d.ts +0 -14
  172. package/dist/core/builders/vite/plugins/devHtmlPrerender.d.ts +0 -7
  173. package/dist/core/builders/vite/plugins/devServerGlobals.d.ts +0 -6
  174. package/dist/core/builders/vite/plugins/download.d.ts +0 -10
  175. package/dist/core/builders/vite/plugins/entrypointGroupGlobals.d.ts +0 -6
  176. package/dist/core/builders/vite/plugins/extensionApiMock.d.ts +0 -6
  177. package/dist/core/builders/vite/plugins/globals.d.ts +0 -3
  178. package/dist/core/builders/vite/plugins/iifeFooter.d.ts +0 -8
  179. package/dist/core/builders/vite/plugins/index.d.ts +0 -16
  180. package/dist/core/builders/vite/plugins/noopBackground.d.ts +0 -6
  181. package/dist/core/builders/vite/plugins/removeEntrypointMainFunction.d.ts +0 -6
  182. package/dist/core/builders/vite/plugins/resolveAppConfig.d.ts +0 -6
  183. package/dist/core/builders/vite/plugins/resolveVirtualModules.d.ts +0 -6
  184. package/dist/core/builders/vite/plugins/tsconfigPaths.d.ts +0 -3
  185. package/dist/core/builders/vite/plugins/wxtPluginLoader.d.ts +0 -6
  186. package/dist/core/define-config.d.ts +0 -2
  187. package/dist/core/define-web-ext-config.d.ts +0 -9
  188. package/dist/core/generate-wxt-dir.d.ts +0 -5
  189. package/dist/core/index.d.ts +0 -8
  190. package/dist/core/initialize.d.ts +0 -5
  191. package/dist/core/keyboard-shortcuts.d.ts +0 -12
  192. package/dist/core/package-managers/bun.d.ts +0 -2
  193. package/dist/core/package-managers/deno.d.ts +0 -2
  194. package/dist/core/package-managers/index.d.ts +0 -2
  195. package/dist/core/package-managers/npm.d.ts +0 -17
  196. package/dist/core/package-managers/pnpm.d.ts +0 -2
  197. package/dist/core/package-managers/types.d.ts +0 -2
  198. package/dist/core/package-managers/types.mjs +0 -0
  199. package/dist/core/package-managers/yarn.d.ts +0 -2
  200. package/dist/core/prepare.d.ts +0 -2
  201. package/dist/core/resolve-config.d.ts +0 -11
  202. package/dist/core/runners/index.d.ts +0 -2
  203. package/dist/core/runners/manual.d.ts +0 -5
  204. package/dist/core/runners/safari.d.ts +0 -5
  205. package/dist/core/runners/web-ext.d.ts +0 -5
  206. package/dist/core/runners/wsl.d.ts +0 -5
  207. package/dist/core/utils/arrays.d.ts +0 -13
  208. package/dist/core/utils/building/build-entrypoints.d.ts +0 -3
  209. package/dist/core/utils/building/detect-dev-changes.d.ts +0 -61
  210. package/dist/core/utils/building/find-entrypoints.d.ts +0 -5
  211. package/dist/core/utils/building/group-entrypoints.d.ts +0 -8
  212. package/dist/core/utils/building/index.d.ts +0 -6
  213. package/dist/core/utils/building/internal-build.d.ts +0 -12
  214. package/dist/core/utils/building/rebuild.d.ts +0 -23
  215. package/dist/core/utils/cache.d.ts +0 -8
  216. package/dist/core/utils/cli.d.ts +0 -3
  217. package/dist/core/utils/cli.mjs +0 -26
  218. package/dist/core/utils/constants.d.ts +0 -5
  219. package/dist/core/utils/content-scripts.d.ts +0 -12
  220. package/dist/core/utils/content-security-policy.d.ts +0 -14
  221. package/dist/core/utils/entrypoints.d.ts +0 -31
  222. package/dist/core/utils/env.d.ts +0 -5
  223. package/dist/core/utils/environments/browser-environment.d.ts +0 -3
  224. package/dist/core/utils/environments/environment.d.ts +0 -8
  225. package/dist/core/utils/environments/extension-environment.d.ts +0 -6
  226. package/dist/core/utils/environments/index.d.ts +0 -2
  227. package/dist/core/utils/eslint.d.ts +0 -1
  228. package/dist/core/utils/fs.d.ts +0 -13
  229. package/dist/core/utils/globals.d.ts +0 -11
  230. package/dist/core/utils/i18n.d.ts +0 -11
  231. package/dist/core/utils/log/index.d.ts +0 -4
  232. package/dist/core/utils/log/printBuildSummary.d.ts +0 -2
  233. package/dist/core/utils/log/printFileList.d.ts +0 -1
  234. package/dist/core/utils/log/printHeader.d.ts +0 -1
  235. package/dist/core/utils/log/printTable.d.ts +0 -1
  236. package/dist/core/utils/manifest.d.ts +0 -40
  237. package/dist/core/utils/minimatch-multiple.d.ts +0 -15
  238. package/dist/core/utils/network.d.ts +0 -7
  239. package/dist/core/utils/number.d.ts +0 -1
  240. package/dist/core/utils/package.d.ts +0 -6
  241. package/dist/core/utils/paths.d.ts +0 -11
  242. package/dist/core/utils/strings.d.ts +0 -14
  243. package/dist/core/utils/syntax-errors.d.ts +0 -11
  244. package/dist/core/utils/testing/fake-objects.d.ts +0 -11665
  245. package/dist/core/utils/testing/fake-objects.mjs +0 -326
  246. package/dist/core/utils/time.d.ts +0 -9
  247. package/dist/core/utils/transform.d.ts +0 -11
  248. package/dist/core/utils/types.d.ts +0 -13
  249. package/dist/core/utils/types.mjs +0 -0
  250. package/dist/core/utils/validation.d.ts +0 -15
  251. package/dist/core/utils/virtual-modules.d.ts +0 -22
  252. package/dist/core/utils/wsl.d.ts +0 -4
  253. package/dist/core/wxt.d.ts +0 -24
  254. package/dist/index.d.ts +0 -11
  255. package/dist/testing/fake-browser.d.ts +0 -10
  256. package/dist/testing/index.d.ts +0 -10
  257. package/dist/types.d.ts +0 -1459
  258. package/dist/types.mjs +0 -0
  259. package/dist/utils/app-config.d.ts +0 -2
  260. package/dist/utils/content-script-context.d.ts +0 -134
  261. package/dist/utils/content-script-ui/iframe.d.ts +0 -32
  262. package/dist/utils/content-script-ui/integrated.d.ts +0 -34
  263. package/dist/utils/content-script-ui/shadow-root.d.ts +0 -76
  264. package/dist/utils/content-script-ui/shared.d.ts +0 -5
  265. package/dist/utils/content-script-ui/types.d.ts +0 -104
  266. package/dist/utils/define-background.d.ts +0 -4
  267. package/dist/utils/define-content-script.d.ts +0 -3
  268. package/dist/utils/define-unlisted-script.d.ts +0 -4
  269. package/dist/utils/define-wxt-plugin.d.ts +0 -3
  270. package/dist/utils/inject-script.d.ts +0 -36
  271. package/dist/utils/internal/custom-events.d.ts +0 -10
  272. package/dist/utils/internal/dev-server-websocket.d.ts +0 -21
  273. package/dist/utils/internal/dev-server-websocket.mjs +0 -37
  274. package/dist/utils/internal/location-watcher.d.ts +0 -12
  275. package/dist/utils/internal/logger.d.ts +0 -9
  276. package/dist/utils/match-patterns.d.ts +0 -5
  277. package/dist/utils/storage.d.ts +0 -5
  278. package/dist/version.d.ts +0 -1
@@ -1,522 +1,407 @@
1
- import fs from "fs-extra";
2
- import { resolve } from "path";
1
+ import { normalizePath } from "./paths.mjs";
3
2
  import { getEntrypointBundlePath } from "./entrypoints.mjs";
3
+ import { wxt } from "../wxt.mjs";
4
+ import { writeFileIfDifferent } from "./fs.mjs";
4
5
  import { ContentSecurityPolicy } from "./content-security-policy.mjs";
5
- import {
6
- hashContentScriptOptions,
7
- mapWxtOptionsToContentScript
8
- } from "./content-scripts.mjs";
6
+ import { hashContentScriptOptions, mapWxtOptionsToContentScript } from "./content-scripts.mjs";
9
7
  import { getPackageJson } from "./package.mjs";
10
- import { normalizePath } from "./paths.mjs";
11
- import { writeFileIfDifferent } from "./fs.mjs";
8
+ import fs from "fs-extra";
9
+ import { resolve } from "path";
12
10
  import defu from "defu";
13
- import { wxt } from "../wxt.mjs";
14
- export async function writeManifest(manifest, output) {
15
- const str = wxt.config.mode === "production" ? JSON.stringify(manifest) : JSON.stringify(manifest, null, 2);
16
- await fs.ensureDir(wxt.config.outDir);
17
- await writeFileIfDifferent(resolve(wxt.config.outDir, "manifest.json"), str);
18
- output.publicAssets.unshift({
19
- type: "asset",
20
- fileName: "manifest.json"
21
- });
11
+
12
+ //#region src/core/utils/manifest.ts
13
+ /**
14
+ * Writes the manifest to the output directory and the build output.
15
+ */
16
+ async function writeManifest(manifest, output) {
17
+ const str = wxt.config.mode === "production" ? JSON.stringify(manifest) : JSON.stringify(manifest, null, 2);
18
+ await fs.ensureDir(wxt.config.outDir);
19
+ await writeFileIfDifferent(resolve(wxt.config.outDir, "manifest.json"), str);
20
+ output.publicAssets.unshift({
21
+ type: "asset",
22
+ fileName: "manifest.json"
23
+ });
22
24
  }
23
- export async function generateManifest(allEntrypoints, buildOutput) {
24
- const entrypoints = allEntrypoints.filter((entry) => !entry.skipped);
25
- const warnings = [];
26
- const pkg = await getPackageJson();
27
- let versionName = wxt.config.manifest.version_name ?? wxt.config.manifest.version ?? pkg?.version;
28
- if (versionName == null) {
29
- versionName = "0.0.0";
30
- wxt.logger.warn(
31
- 'Extension version not found, defaulting to "0.0.0". Add a version to your `package.json` or `wxt.config.ts` file. For more details, see: https://wxt.dev/guide/key-concepts/manifest.html#version-and-version-name'
32
- );
33
- }
34
- const version = wxt.config.manifest.version ?? simplifyVersion(versionName);
35
- const baseManifest = {
36
- manifest_version: wxt.config.manifestVersion,
37
- name: pkg?.name,
38
- description: pkg?.description,
39
- version,
40
- short_name: pkg?.shortName,
41
- icons: discoverIcons(buildOutput)
42
- };
43
- const userManifest = wxt.config.manifest;
44
- if (userManifest.manifest_version) {
45
- delete userManifest.manifest_version;
46
- wxt.logger.warn(
47
- "`manifest.manifest_version` config was set, but ignored. To change the target manifest version, use the `manifestVersion` option or the `--mv2`/`--mv3` CLI flags.\nSee https://wxt.dev/guide/essentials/target-different-browsers.html#target-a-manifest-version"
48
- );
49
- }
50
- let manifest = defu(userManifest, baseManifest);
51
- if (wxt.config.command === "serve" && wxt.config.dev.reloadCommand) {
52
- if (manifest.commands && // If the following limit is exceeded, Chrome will fail to load the extension.
53
- // Error: "Too many commands specified for 'commands': The maximum is 4."
54
- Object.values(manifest.commands).filter(
55
- (command) => command.suggested_key
56
- ).length >= 4) {
57
- warnings.push([
58
- "Extension already has 4 registered commands with suggested keys, WXT's reload command is disabled"
59
- ]);
60
- } else {
61
- manifest.commands ??= {};
62
- manifest.commands["wxt:reload-extension"] = {
63
- description: "Reload the extension during development",
64
- suggested_key: {
65
- default: wxt.config.dev.reloadCommand
66
- }
67
- };
68
- }
69
- }
70
- manifest.version = version;
71
- manifest.version_name = // Firefox doesn't support version_name
72
- wxt.config.browser === "firefox" || versionName === version ? void 0 : versionName;
73
- addEntrypoints(manifest, entrypoints, buildOutput);
74
- if (wxt.config.command === "serve") addDevModeCsp(manifest);
75
- if (wxt.config.command === "serve") addDevModePermissions(manifest);
76
- await wxt.hooks.callHook("build:manifestGenerated", wxt, manifest);
77
- if (wxt.config.manifestVersion === 2) {
78
- convertWebAccessibleResourcesToMv2(manifest);
79
- convertActionToMv2(manifest);
80
- convertCspToMv2(manifest);
81
- moveHostPermissionsToPermissions(manifest);
82
- }
83
- if (wxt.config.manifestVersion === 3) {
84
- validateMv3WebAccessibleResources(manifest);
85
- }
86
- stripKeys(manifest);
87
- if (manifest.name == null)
88
- throw Error(
89
- "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"
90
- );
91
- if (manifest.version == null) {
92
- throw Error(
93
- "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"
94
- );
95
- }
96
- return {
97
- manifest,
98
- warnings
99
- };
25
+ /**
26
+ * Generates the manifest based on the config and entrypoints.
27
+ */
28
+ async function generateManifest(allEntrypoints, buildOutput) {
29
+ const entrypoints = allEntrypoints.filter((entry) => !entry.skipped);
30
+ const warnings = [];
31
+ const pkg = await getPackageJson();
32
+ let versionName = wxt.config.manifest.version_name ?? wxt.config.manifest.version ?? pkg?.version;
33
+ if (versionName == null) {
34
+ versionName = "0.0.0";
35
+ wxt.logger.warn("Extension version not found, defaulting to \"0.0.0\". Add a version to your `package.json` or `wxt.config.ts` file. For more details, see: https://wxt.dev/guide/key-concepts/manifest.html#version-and-version-name");
36
+ }
37
+ const version = wxt.config.manifest.version ?? simplifyVersion(versionName);
38
+ const baseManifest = {
39
+ manifest_version: wxt.config.manifestVersion,
40
+ name: pkg?.name,
41
+ description: pkg?.description,
42
+ version,
43
+ short_name: pkg?.shortName,
44
+ icons: discoverIcons(buildOutput)
45
+ };
46
+ const userManifest = wxt.config.manifest;
47
+ if (userManifest.manifest_version) {
48
+ delete userManifest.manifest_version;
49
+ wxt.logger.warn("`manifest.manifest_version` config was set, but ignored. To change the target manifest version, use the `manifestVersion` option or the `--mv2`/`--mv3` CLI flags.\nSee https://wxt.dev/guide/essentials/target-different-browsers.html#target-a-manifest-version");
50
+ }
51
+ let manifest = defu(userManifest, baseManifest);
52
+ if (wxt.config.command === "serve" && wxt.config.dev.reloadCommand) if (manifest.commands && Object.values(manifest.commands).filter((command) => command.suggested_key).length >= 4) warnings.push(["Extension already has 4 registered commands with suggested keys, WXT's reload command is disabled"]);
53
+ else {
54
+ manifest.commands ??= {};
55
+ manifest.commands["wxt:reload-extension"] = {
56
+ description: "Reload the extension during development",
57
+ suggested_key: { default: wxt.config.dev.reloadCommand }
58
+ };
59
+ }
60
+ manifest.version = version;
61
+ manifest.version_name = wxt.config.browser === "firefox" || versionName === version ? void 0 : versionName;
62
+ addEntrypoints(manifest, entrypoints, buildOutput);
63
+ if (wxt.config.command === "serve") addDevModeCsp(manifest);
64
+ if (wxt.config.command === "serve") addDevModePermissions(manifest);
65
+ await wxt.hooks.callHook("build:manifestGenerated", wxt, manifest);
66
+ if (wxt.config.manifestVersion === 2) {
67
+ convertWebAccessibleResourcesToMv2(manifest);
68
+ convertActionToMv2(manifest);
69
+ convertCspToMv2(manifest);
70
+ moveHostPermissionsToPermissions(manifest);
71
+ }
72
+ if (wxt.config.manifestVersion === 3) validateMv3WebAccessibleResources(manifest);
73
+ stripKeys(manifest);
74
+ if (manifest.name == null) throw Error("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");
75
+ if (manifest.version == null) throw Error("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");
76
+ return {
77
+ manifest,
78
+ warnings
79
+ };
100
80
  }
81
+ /**
82
+ * Removes suffixes from the version, like X.Y.Z-alpha1 (which browsers don't allow), so it's a
83
+ * simple version number, like X or X.Y or X.Y.Z, which browsers allow.
84
+ */
101
85
  function simplifyVersion(versionName) {
102
- const version = /^((0|[1-9][0-9]{0,8})([.](0|[1-9][0-9]{0,8})){0,3}).*$/.exec(
103
- versionName
104
- )?.[1];
105
- if (version == null)
106
- throw Error(
107
- `Cannot simplify package.json version "${versionName}" to a valid extension version, "X.Y.Z"`
108
- );
109
- return version;
86
+ const version = /^((0|[1-9][0-9]{0,8})([.](0|[1-9][0-9]{0,8})){0,3}).*$/.exec(versionName)?.[1];
87
+ if (version == null) throw Error(`Cannot simplify package.json version "${versionName}" to a valid extension version, "X.Y.Z"`);
88
+ return version;
110
89
  }
111
90
  function addEntrypoints(manifest, entrypoints, buildOutput) {
112
- const entriesByType = entrypoints.reduce((map, entrypoint) => {
113
- map[entrypoint.type] ??= [];
114
- map[entrypoint.type]?.push(entrypoint);
115
- return map;
116
- }, {});
117
- const background = entriesByType["background"]?.[0];
118
- const bookmarks = entriesByType["bookmarks"]?.[0];
119
- const contentScripts = entriesByType["content-script"];
120
- const devtools = entriesByType["devtools"]?.[0];
121
- const history = entriesByType["history"]?.[0];
122
- const newtab = entriesByType["newtab"]?.[0];
123
- const options = entriesByType["options"]?.[0];
124
- const popup = entriesByType["popup"]?.[0];
125
- const sandboxes = entriesByType["sandbox"];
126
- const sidepanels = entriesByType["sidepanel"];
127
- if (background) {
128
- const script = getEntrypointBundlePath(
129
- background,
130
- wxt.config.outDir,
131
- ".js"
132
- );
133
- if (wxt.config.browser === "firefox" && wxt.config.manifestVersion === 3) {
134
- manifest.background = {
135
- type: background.options.type,
136
- scripts: [script]
137
- };
138
- } else if (wxt.config.manifestVersion === 3) {
139
- manifest.background = {
140
- type: background.options.type,
141
- service_worker: script
142
- };
143
- } else {
144
- manifest.background = {
145
- persistent: background.options.persistent,
146
- scripts: [script]
147
- };
148
- }
149
- }
150
- if (bookmarks) {
151
- if (wxt.config.browser === "firefox") {
152
- wxt.logger.warn(
153
- "Bookmarks are not supported by Firefox. chrome_url_overrides.bookmarks was not added to the manifest"
154
- );
155
- } else {
156
- manifest.chrome_url_overrides ??= {};
157
- manifest.chrome_url_overrides.bookmarks = getEntrypointBundlePath(
158
- bookmarks,
159
- wxt.config.outDir,
160
- ".html"
161
- );
162
- }
163
- }
164
- if (history) {
165
- if (wxt.config.browser === "firefox") {
166
- wxt.logger.warn(
167
- "Bookmarks are not supported by Firefox. chrome_url_overrides.history was not added to the manifest"
168
- );
169
- } else {
170
- manifest.chrome_url_overrides ??= {};
171
- manifest.chrome_url_overrides.history = getEntrypointBundlePath(
172
- history,
173
- wxt.config.outDir,
174
- ".html"
175
- );
176
- }
177
- }
178
- if (newtab) {
179
- manifest.chrome_url_overrides ??= {};
180
- manifest.chrome_url_overrides.newtab = getEntrypointBundlePath(
181
- newtab,
182
- wxt.config.outDir,
183
- ".html"
184
- );
185
- }
186
- if (popup) {
187
- const default_popup = getEntrypointBundlePath(
188
- popup,
189
- wxt.config.outDir,
190
- ".html"
191
- );
192
- const options2 = {};
193
- if (popup.options.defaultIcon)
194
- options2.default_icon = popup.options.defaultIcon;
195
- if (popup.options.defaultTitle)
196
- options2.default_title = popup.options.defaultTitle;
197
- if (popup.options.browserStyle)
198
- options2.browser_style = popup.options.browserStyle;
199
- if (manifest.manifest_version === 3) {
200
- manifest.action = {
201
- ...manifest.action,
202
- ...options2,
203
- default_popup
204
- };
205
- } else {
206
- const key = popup.options.mv2Key ?? "browser_action";
207
- manifest[key] = {
208
- ...manifest[key],
209
- ...options2,
210
- default_popup
211
- };
212
- }
213
- }
214
- if (devtools) {
215
- manifest.devtools_page = getEntrypointBundlePath(
216
- devtools,
217
- wxt.config.outDir,
218
- ".html"
219
- );
220
- }
221
- if (options) {
222
- const page = getEntrypointBundlePath(options, wxt.config.outDir, ".html");
223
- manifest.options_ui = {
224
- open_in_tab: options.options.openInTab,
225
- // @ts-expect-error: Not typed by @wxt-dev/browser, but supported by Firefox
226
- browser_style: wxt.config.browser === "firefox" ? options.options.browserStyle : void 0,
227
- chrome_style: wxt.config.browser !== "firefox" ? options.options.chromeStyle : void 0,
228
- page
229
- };
230
- }
231
- if (sandboxes?.length) {
232
- if (wxt.config.browser === "firefox") {
233
- wxt.logger.warn(
234
- "Sandboxed pages not supported by Firefox. sandbox.pages was not added to the manifest"
235
- );
236
- } else {
237
- manifest.sandbox = {
238
- pages: sandboxes.map(
239
- (entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".html")
240
- )
241
- };
242
- }
243
- }
244
- if (sidepanels?.length) {
245
- const defaultSidepanel = sidepanels.find((entry) => entry.name === "sidepanel") ?? sidepanels[0];
246
- const page = getEntrypointBundlePath(
247
- defaultSidepanel,
248
- wxt.config.outDir,
249
- ".html"
250
- );
251
- if (wxt.config.browser === "firefox") {
252
- manifest.sidebar_action = {
253
- default_panel: page,
254
- browser_style: defaultSidepanel.options.browserStyle,
255
- default_icon: defaultSidepanel.options.defaultIcon,
256
- default_title: defaultSidepanel.options.defaultTitle,
257
- open_at_install: defaultSidepanel.options.openAtInstall
258
- };
259
- } else if (wxt.config.manifestVersion === 3) {
260
- manifest.side_panel = {
261
- default_path: page
262
- };
263
- addPermission(manifest, "sidePanel");
264
- } else {
265
- wxt.logger.warn(
266
- "Side panel not supported by Chromium using MV2. side_panel.default_path was not added to the manifest"
267
- );
268
- }
269
- }
270
- if (contentScripts?.length) {
271
- const cssMap = getContentScriptsCssMap(buildOutput, contentScripts);
272
- if (wxt.config.command === "serve" && wxt.config.manifestVersion === 3) {
273
- contentScripts.forEach((script) => {
274
- script.options.matches?.forEach((matchPattern) => {
275
- addHostPermission(manifest, matchPattern);
276
- });
277
- });
278
- } else {
279
- const hashToEntrypointsMap = contentScripts.filter((cs) => cs.options.registration !== "runtime").reduce((map, script) => {
280
- const hash = hashContentScriptOptions(script.options);
281
- if (map.has(hash)) map.get(hash)?.push(script);
282
- else map.set(hash, [script]);
283
- return map;
284
- }, /* @__PURE__ */ new Map());
285
- const manifestContentScripts = Array.from(
286
- hashToEntrypointsMap.values()
287
- ).map(
288
- (scripts) => mapWxtOptionsToContentScript(
289
- scripts[0].options,
290
- scripts.map(
291
- (entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".js")
292
- ),
293
- getContentScriptCssFiles(scripts, cssMap)
294
- )
295
- );
296
- if (manifestContentScripts.length >= 0) {
297
- manifest.content_scripts ??= [];
298
- manifest.content_scripts.push(...manifestContentScripts);
299
- }
300
- const runtimeContentScripts = contentScripts.filter(
301
- (cs) => cs.options.registration === "runtime"
302
- );
303
- runtimeContentScripts.forEach((script) => {
304
- script.options.matches?.forEach((matchPattern) => {
305
- addHostPermission(manifest, matchPattern);
306
- });
307
- });
308
- }
309
- const contentScriptCssResources = getContentScriptCssWebAccessibleResources(
310
- contentScripts,
311
- cssMap
312
- );
313
- if (contentScriptCssResources.length > 0) {
314
- manifest.web_accessible_resources ??= [];
315
- manifest.web_accessible_resources.push(...contentScriptCssResources);
316
- }
317
- }
91
+ const entriesByType = entrypoints.reduce((map, entrypoint) => {
92
+ map[entrypoint.type] ??= [];
93
+ map[entrypoint.type]?.push(entrypoint);
94
+ return map;
95
+ }, {});
96
+ const background = entriesByType["background"]?.[0];
97
+ const bookmarks = entriesByType["bookmarks"]?.[0];
98
+ const contentScripts = entriesByType["content-script"];
99
+ const devtools = entriesByType["devtools"]?.[0];
100
+ const history = entriesByType["history"]?.[0];
101
+ const newtab = entriesByType["newtab"]?.[0];
102
+ const options = entriesByType["options"]?.[0];
103
+ const popup = entriesByType["popup"]?.[0];
104
+ const sandboxes = entriesByType["sandbox"];
105
+ const sidepanels = entriesByType["sidepanel"];
106
+ if (background) {
107
+ const script = getEntrypointBundlePath(background, wxt.config.outDir, ".js");
108
+ if (wxt.config.browser === "firefox" && wxt.config.manifestVersion === 3) manifest.background = {
109
+ type: background.options.type,
110
+ scripts: [script]
111
+ };
112
+ else if (wxt.config.manifestVersion === 3) manifest.background = {
113
+ type: background.options.type,
114
+ service_worker: script
115
+ };
116
+ else manifest.background = {
117
+ persistent: background.options.persistent,
118
+ scripts: [script]
119
+ };
120
+ }
121
+ if (bookmarks) if (wxt.config.browser === "firefox") wxt.logger.warn("Bookmarks are not supported by Firefox. chrome_url_overrides.bookmarks was not added to the manifest");
122
+ else {
123
+ manifest.chrome_url_overrides ??= {};
124
+ manifest.chrome_url_overrides.bookmarks = getEntrypointBundlePath(bookmarks, wxt.config.outDir, ".html");
125
+ }
126
+ if (history) if (wxt.config.browser === "firefox") wxt.logger.warn("Bookmarks are not supported by Firefox. chrome_url_overrides.history was not added to the manifest");
127
+ else {
128
+ manifest.chrome_url_overrides ??= {};
129
+ manifest.chrome_url_overrides.history = getEntrypointBundlePath(history, wxt.config.outDir, ".html");
130
+ }
131
+ if (newtab) {
132
+ manifest.chrome_url_overrides ??= {};
133
+ manifest.chrome_url_overrides.newtab = getEntrypointBundlePath(newtab, wxt.config.outDir, ".html");
134
+ }
135
+ if (popup) {
136
+ const default_popup = getEntrypointBundlePath(popup, wxt.config.outDir, ".html");
137
+ const options = {};
138
+ if (popup.options.defaultIcon) options.default_icon = popup.options.defaultIcon;
139
+ if (popup.options.defaultTitle) options.default_title = popup.options.defaultTitle;
140
+ if (popup.options.browserStyle) options.browser_style = popup.options.browserStyle;
141
+ if (manifest.manifest_version === 3) manifest.action = {
142
+ ...manifest.action,
143
+ ...options,
144
+ default_popup
145
+ };
146
+ else {
147
+ const key = popup.options.mv2Key ?? "browser_action";
148
+ manifest[key] = {
149
+ ...manifest[key],
150
+ ...options,
151
+ default_popup
152
+ };
153
+ }
154
+ }
155
+ if (devtools) manifest.devtools_page = getEntrypointBundlePath(devtools, wxt.config.outDir, ".html");
156
+ if (options) {
157
+ const page = getEntrypointBundlePath(options, wxt.config.outDir, ".html");
158
+ manifest.options_ui = {
159
+ open_in_tab: options.options.openInTab,
160
+ browser_style: wxt.config.browser === "firefox" ? options.options.browserStyle : void 0,
161
+ chrome_style: wxt.config.browser !== "firefox" ? options.options.chromeStyle : void 0,
162
+ page
163
+ };
164
+ }
165
+ if (sandboxes?.length) if (wxt.config.browser === "firefox") wxt.logger.warn("Sandboxed pages not supported by Firefox. sandbox.pages was not added to the manifest");
166
+ else manifest.sandbox = { pages: sandboxes.map((entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".html")) };
167
+ if (sidepanels?.length) {
168
+ const defaultSidepanel = sidepanels.find((entry) => entry.name === "sidepanel") ?? sidepanels[0];
169
+ const page = getEntrypointBundlePath(defaultSidepanel, wxt.config.outDir, ".html");
170
+ if (wxt.config.browser === "firefox") manifest.sidebar_action = {
171
+ default_panel: page,
172
+ browser_style: defaultSidepanel.options.browserStyle,
173
+ default_icon: defaultSidepanel.options.defaultIcon,
174
+ default_title: defaultSidepanel.options.defaultTitle,
175
+ open_at_install: defaultSidepanel.options.openAtInstall
176
+ };
177
+ else if (wxt.config.manifestVersion === 3) {
178
+ manifest.side_panel = { default_path: page };
179
+ addPermission(manifest, "sidePanel");
180
+ } else wxt.logger.warn("Side panel not supported by Chromium using MV2. side_panel.default_path was not added to the manifest");
181
+ }
182
+ if (contentScripts?.length) {
183
+ const cssMap = getContentScriptsCssMap(buildOutput, contentScripts);
184
+ if (wxt.config.command === "serve" && wxt.config.manifestVersion === 3) contentScripts.forEach((script) => {
185
+ script.options.matches?.forEach((matchPattern) => {
186
+ addHostPermission(manifest, matchPattern);
187
+ });
188
+ });
189
+ else {
190
+ const hashToEntrypointsMap = contentScripts.filter((cs) => cs.options.registration !== "runtime").reduce((map, script) => {
191
+ const hash = hashContentScriptOptions(script.options);
192
+ if (map.has(hash)) map.get(hash)?.push(script);
193
+ else map.set(hash, [script]);
194
+ return map;
195
+ }, /* @__PURE__ */ new Map());
196
+ const manifestContentScripts = Array.from(hashToEntrypointsMap.values()).map((scripts) => mapWxtOptionsToContentScript(scripts[0].options, scripts.map((entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".js")), getContentScriptCssFiles(scripts, cssMap)));
197
+ if (manifestContentScripts.length >= 0) {
198
+ manifest.content_scripts ??= [];
199
+ manifest.content_scripts.push(...manifestContentScripts);
200
+ }
201
+ contentScripts.filter((cs) => cs.options.registration === "runtime").forEach((script) => {
202
+ script.options.matches?.forEach((matchPattern) => {
203
+ addHostPermission(manifest, matchPattern);
204
+ });
205
+ });
206
+ }
207
+ const contentScriptCssResources = getContentScriptCssWebAccessibleResources(contentScripts, cssMap);
208
+ if (contentScriptCssResources.length > 0) {
209
+ manifest.web_accessible_resources ??= [];
210
+ manifest.web_accessible_resources.push(...contentScriptCssResources);
211
+ }
212
+ }
318
213
  }
319
214
  function discoverIcons(buildOutput) {
320
- const icons = [];
321
- const iconRegex = [
322
- /^icon-([0-9]+)\.png$/,
323
- // icon-16.png
324
- /^icon-([0-9]+)x[0-9]+\.png$/,
325
- // icon-16x16.png
326
- /^icon@([0-9]+)w\.png$/,
327
- // icon@16w.png
328
- /^icon@([0-9]+)h\.png$/,
329
- // icon@16h.png
330
- /^icon@([0-9]+)\.png$/,
331
- // icon@16.png
332
- /^icons?[/\\]([0-9]+)\.png$/,
333
- // icon/16.png | icons/16.png
334
- /^icons?[/\\]([0-9]+)x[0-9]+\.png$/
335
- // icon/16x16.png | icons/16x16.png
336
- ];
337
- buildOutput.publicAssets.forEach((asset) => {
338
- let size;
339
- for (const regex of iconRegex) {
340
- const match = asset.fileName.match(regex);
341
- if (match?.[1] != null) {
342
- size = match[1];
343
- break;
344
- }
345
- }
346
- if (size == null) return;
347
- icons.push([size, normalizePath(asset.fileName)]);
348
- });
349
- return icons.length > 0 ? Object.fromEntries(icons) : void 0;
215
+ const icons = [];
216
+ const iconRegex = [
217
+ /^icon-([0-9]+)\.png$/,
218
+ /^icon-([0-9]+)x[0-9]+\.png$/,
219
+ /^icon@([0-9]+)w\.png$/,
220
+ /^icon@([0-9]+)h\.png$/,
221
+ /^icon@([0-9]+)\.png$/,
222
+ /^icons?[/\\]([0-9]+)\.png$/,
223
+ /^icons?[/\\]([0-9]+)x[0-9]+\.png$/
224
+ ];
225
+ buildOutput.publicAssets.forEach((asset) => {
226
+ let size;
227
+ for (const regex of iconRegex) {
228
+ const match = asset.fileName.match(regex);
229
+ if (match?.[1] != null) {
230
+ size = match[1];
231
+ break;
232
+ }
233
+ }
234
+ if (size == null) return;
235
+ icons.push([size, normalizePath(asset.fileName)]);
236
+ });
237
+ return icons.length > 0 ? Object.fromEntries(icons) : void 0;
350
238
  }
351
239
  function addDevModeCsp(manifest) {
352
- let permissonUrl = wxt.server?.origin;
353
- if (permissonUrl) {
354
- const permissionUrlInstance = new URL(permissonUrl);
355
- permissionUrlInstance.port = "";
356
- permissonUrl = permissionUrlInstance.toString();
357
- }
358
- const permission = `${permissonUrl}*`;
359
- const allowedCsp = wxt.server?.origin ?? "http://localhost:*";
360
- if (manifest.manifest_version === 3) {
361
- addHostPermission(manifest, permission);
362
- } else {
363
- addPermission(manifest, permission);
364
- }
365
- const extensionPagesCsp = new ContentSecurityPolicy(
366
- // @ts-expect-error: extension_pages exists, we convert MV2 CSPs to this earlier in the process
367
- manifest.content_security_policy?.extension_pages ?? (manifest.manifest_version === 3 ? DEFAULT_MV3_EXTENSION_PAGES_CSP : DEFAULT_MV2_CSP)
368
- );
369
- const sandboxCsp = new ContentSecurityPolicy(
370
- // @ts-expect-error: sandbox is not typed
371
- manifest.content_security_policy?.sandbox ?? DEFAULT_MV3_SANDBOX_CSP
372
- );
373
- if (wxt.config.command === "serve") {
374
- extensionPagesCsp.add("script-src", allowedCsp);
375
- sandboxCsp.add("script-src", allowedCsp);
376
- }
377
- manifest.content_security_policy ??= {};
378
- manifest.content_security_policy.extension_pages = extensionPagesCsp.toString();
379
- manifest.content_security_policy.sandbox = sandboxCsp.toString();
240
+ let permissonUrl = wxt.server?.origin;
241
+ if (permissonUrl) {
242
+ const permissionUrlInstance = new URL(permissonUrl);
243
+ permissionUrlInstance.port = "";
244
+ permissonUrl = permissionUrlInstance.toString();
245
+ }
246
+ const permission = `${permissonUrl}*`;
247
+ const allowedCsp = wxt.server?.origin ?? "http://localhost:*";
248
+ if (manifest.manifest_version === 3) addHostPermission(manifest, permission);
249
+ else addPermission(manifest, permission);
250
+ const extensionPagesCsp = new ContentSecurityPolicy(manifest.content_security_policy?.extension_pages ?? (manifest.manifest_version === 3 ? DEFAULT_MV3_EXTENSION_PAGES_CSP : DEFAULT_MV2_CSP));
251
+ const sandboxCsp = new ContentSecurityPolicy(manifest.content_security_policy?.sandbox ?? DEFAULT_MV3_SANDBOX_CSP);
252
+ if (wxt.config.command === "serve") {
253
+ extensionPagesCsp.add("script-src", allowedCsp);
254
+ sandboxCsp.add("script-src", allowedCsp);
255
+ }
256
+ manifest.content_security_policy ??= {};
257
+ manifest.content_security_policy.extension_pages = extensionPagesCsp.toString();
258
+ manifest.content_security_policy.sandbox = sandboxCsp.toString();
380
259
  }
381
260
  function addDevModePermissions(manifest) {
382
- addPermission(manifest, "tabs");
383
- if (wxt.config.manifestVersion === 3) addPermission(manifest, "scripting");
261
+ addPermission(manifest, "tabs");
262
+ if (wxt.config.manifestVersion === 3) addPermission(manifest, "scripting");
384
263
  }
385
- export function getContentScriptCssFiles(contentScripts, contentScriptCssMap) {
386
- const css = [];
387
- contentScripts.forEach((script) => {
388
- if (script.options.cssInjectionMode === "manual" || script.options.cssInjectionMode === "ui")
389
- return;
390
- const cssFile = contentScriptCssMap[script.name];
391
- if (cssFile == null) return;
392
- if (cssFile) css.push(cssFile);
393
- });
394
- if (css.length > 0) return css;
395
- return void 0;
264
+ /**
265
+ * Returns the bundle paths to CSS files associated with a list of content scripts, or undefined if
266
+ * there is no associated CSS.
267
+ */
268
+ function getContentScriptCssFiles(contentScripts, contentScriptCssMap) {
269
+ const css = [];
270
+ contentScripts.forEach((script) => {
271
+ if (script.options.cssInjectionMode === "manual" || script.options.cssInjectionMode === "ui") return;
272
+ const cssFile = contentScriptCssMap[script.name];
273
+ if (cssFile == null) return;
274
+ if (cssFile) css.push(cssFile);
275
+ });
276
+ if (css.length > 0) return css;
396
277
  }
397
- export function getContentScriptCssWebAccessibleResources(contentScripts, contentScriptCssMap) {
398
- const resources = [];
399
- contentScripts.forEach((script) => {
400
- if (script.options.cssInjectionMode !== "ui") return;
401
- const cssFile = contentScriptCssMap[script.name];
402
- if (cssFile == null) return;
403
- resources.push({
404
- resources: [cssFile],
405
- use_dynamic_url: true,
406
- matches: script.options.matches?.map(
407
- (matchPattern) => stripPathFromMatchPattern(matchPattern)
408
- ) ?? []
409
- });
410
- });
411
- return resources;
278
+ /**
279
+ * Content scripts configured with `cssInjectionMode: "ui"` need to add their CSS files to web
280
+ * accessible resources so they can be fetched as text and added to shadow roots that the UI is
281
+ * added to.
282
+ */
283
+ function getContentScriptCssWebAccessibleResources(contentScripts, contentScriptCssMap) {
284
+ const resources = [];
285
+ contentScripts.forEach((script) => {
286
+ if (script.options.cssInjectionMode !== "ui") return;
287
+ const cssFile = contentScriptCssMap[script.name];
288
+ if (cssFile == null) return;
289
+ resources.push({
290
+ resources: [cssFile],
291
+ use_dynamic_url: true,
292
+ matches: script.options.matches?.map((matchPattern) => stripPathFromMatchPattern(matchPattern)) ?? []
293
+ });
294
+ });
295
+ return resources;
412
296
  }
413
- export function getContentScriptsCssMap(buildOutput, scripts) {
414
- const map = {};
415
- const allChunks = buildOutput.steps.flatMap((step) => step.chunks);
416
- scripts.forEach((script) => {
417
- const relatedCss = allChunks.find(
418
- (chunk) => chunk.fileName === `content-scripts/${script.name}.css`
419
- );
420
- if (relatedCss != null) map[script.name] = relatedCss.fileName;
421
- });
422
- return map;
297
+ /**
298
+ * Based on the build output, return a Record of each content script's name to it CSS file if the
299
+ * script includes one.
300
+ */
301
+ function getContentScriptsCssMap(buildOutput, scripts) {
302
+ const map = {};
303
+ const allChunks = buildOutput.steps.flatMap((step) => step.chunks);
304
+ scripts.forEach((script) => {
305
+ const relatedCss = allChunks.find((chunk) => chunk.fileName === `content-scripts/${script.name}.css`);
306
+ if (relatedCss != null) map[script.name] = relatedCss.fileName;
307
+ });
308
+ return map;
423
309
  }
424
310
  function addPermission(manifest, permission) {
425
- manifest.permissions ??= [];
426
- if (manifest.permissions.includes(permission)) return;
427
- manifest.permissions.push(permission);
311
+ manifest.permissions ??= [];
312
+ if (manifest.permissions.includes(permission)) return;
313
+ manifest.permissions.push(permission);
428
314
  }
429
315
  function addHostPermission(manifest, hostPermission) {
430
- manifest.host_permissions ??= [];
431
- if (manifest.host_permissions.includes(hostPermission)) return;
432
- manifest.host_permissions.push(hostPermission);
316
+ manifest.host_permissions ??= [];
317
+ if (manifest.host_permissions.includes(hostPermission)) return;
318
+ manifest.host_permissions.push(hostPermission);
433
319
  }
434
- export function stripPathFromMatchPattern(pattern) {
435
- const protocolSepIndex = pattern.indexOf("://");
436
- if (protocolSepIndex === -1) return pattern;
437
- const startOfPath = pattern.indexOf("/", protocolSepIndex + 3);
438
- return pattern.substring(0, startOfPath) + "/*";
320
+ /**
321
+ * - "<all_urls>" &rarr; "<all_urls>"
322
+ * - "*://play.google.com/books/*" &rarr; "*://play.google.com/*"
323
+ */
324
+ function stripPathFromMatchPattern(pattern) {
325
+ const protocolSepIndex = pattern.indexOf("://");
326
+ if (protocolSepIndex === -1) return pattern;
327
+ const startOfPath = pattern.indexOf("/", protocolSepIndex + 3);
328
+ return pattern.substring(0, startOfPath) + "/*";
439
329
  }
440
- export function convertWebAccessibleResourcesToMv2(manifest) {
441
- if (manifest.web_accessible_resources == null) return;
442
- manifest.web_accessible_resources = Array.from(
443
- new Set(
444
- manifest.web_accessible_resources.flatMap((item) => {
445
- if (typeof item === "string") return item;
446
- return item.resources;
447
- })
448
- )
449
- );
330
+ /**
331
+ * Converts all MV3 web accessible resources to their MV2 forms. MV3 web accessible resources are
332
+ * generated in this file, and may be defined by the user in their manifest. In both cases, when
333
+ * targeting MV2, automatically convert their definitions down to the basic MV2 array.
334
+ */
335
+ function convertWebAccessibleResourcesToMv2(manifest) {
336
+ if (manifest.web_accessible_resources == null) return;
337
+ manifest.web_accessible_resources = Array.from(new Set(manifest.web_accessible_resources.flatMap((item) => {
338
+ if (typeof item === "string") return item;
339
+ return item.resources;
340
+ })));
450
341
  }
451
342
  function moveHostPermissionsToPermissions(manifest) {
452
- if (!manifest.host_permissions?.length) return;
453
- manifest.host_permissions.forEach(
454
- (permission) => addPermission(manifest, permission)
455
- );
456
- delete manifest.host_permissions;
343
+ if (!manifest.host_permissions?.length) return;
344
+ manifest.host_permissions.forEach((permission) => addPermission(manifest, permission));
345
+ delete manifest.host_permissions;
457
346
  }
458
347
  function convertActionToMv2(manifest) {
459
- if (manifest.action == null || manifest.browser_action != null || manifest.page_action != null)
460
- return;
461
- manifest.browser_action = manifest.action;
348
+ if (manifest.action == null || manifest.browser_action != null || manifest.page_action != null) return;
349
+ manifest.browser_action = manifest.action;
462
350
  }
463
351
  function convertCspToMv2(manifest) {
464
- if (typeof manifest.content_security_policy === "string" || manifest.content_security_policy?.extension_pages == null)
465
- return;
466
- manifest.content_security_policy = manifest.content_security_policy.extension_pages;
352
+ if (typeof manifest.content_security_policy === "string" || manifest.content_security_policy?.extension_pages == null) return;
353
+ manifest.content_security_policy = manifest.content_security_policy.extension_pages;
467
354
  }
355
+ /**
356
+ * Make sure all resources are in MV3 format. If not, add a wanring
357
+ */
468
358
  function validateMv3WebAccessibleResources(manifest) {
469
- if (manifest.web_accessible_resources == null) return;
470
- const stringResources = manifest.web_accessible_resources.filter(
471
- (item) => typeof item === "string"
472
- );
473
- if (stringResources.length > 0) {
474
- throw Error(
475
- `Non-MV3 web_accessible_resources detected: ${JSON.stringify(
476
- stringResources
477
- )}. When manually defining web_accessible_resources, define them as MV3 objects ({ matches: [...], resources: [...] }), and WXT will automatically convert them to MV2 when necessary.`
478
- );
479
- }
359
+ if (manifest.web_accessible_resources == null) return;
360
+ const stringResources = manifest.web_accessible_resources.filter((item) => typeof item === "string");
361
+ if (stringResources.length > 0) throw Error(`Non-MV3 web_accessible_resources detected: ${JSON.stringify(stringResources)}. When manually defining web_accessible_resources, define them as MV3 objects ({ matches: [...], resources: [...] }), and WXT will automatically convert them to MV2 when necessary.`);
480
362
  }
363
+ /**
364
+ * Remove keys from the manifest based on the build target.
365
+ */
481
366
  function stripKeys(manifest) {
482
- let keysToRemove = [];
483
- if (wxt.config.manifestVersion === 2) {
484
- keysToRemove.push(...mv3OnlyKeys);
485
- if (wxt.config.browser === "firefox")
486
- keysToRemove.push(...firefoxMv3OnlyKeys);
487
- } else {
488
- keysToRemove.push(...mv2OnlyKeys);
489
- }
490
- keysToRemove.forEach((key) => {
491
- delete manifest[key];
492
- });
367
+ let keysToRemove = [];
368
+ if (wxt.config.manifestVersion === 2) {
369
+ keysToRemove.push(...mv3OnlyKeys);
370
+ if (wxt.config.browser === "firefox") keysToRemove.push(...firefoxMv3OnlyKeys);
371
+ } else keysToRemove.push(...mv2OnlyKeys);
372
+ keysToRemove.forEach((key) => {
373
+ delete manifest[key];
374
+ });
493
375
  }
494
376
  const mv2OnlyKeys = [
495
- "page_action",
496
- "browser_action",
497
- "automation",
498
- "content_capabilities",
499
- "converted_from_user_script",
500
- "current_locale",
501
- "differential_fingerprint",
502
- "event_rules",
503
- "file_browser_handlers",
504
- "file_system_provider_capabilities",
505
- "nacl_modules",
506
- "natively_connectable",
507
- "offline_enabled",
508
- "platforms",
509
- "replacement_web_app",
510
- "system_indicator",
511
- "user_scripts"
377
+ "page_action",
378
+ "browser_action",
379
+ "automation",
380
+ "content_capabilities",
381
+ "converted_from_user_script",
382
+ "current_locale",
383
+ "differential_fingerprint",
384
+ "event_rules",
385
+ "file_browser_handlers",
386
+ "file_system_provider_capabilities",
387
+ "nacl_modules",
388
+ "natively_connectable",
389
+ "offline_enabled",
390
+ "platforms",
391
+ "replacement_web_app",
392
+ "system_indicator",
393
+ "user_scripts"
512
394
  ];
513
395
  const mv3OnlyKeys = [
514
- "action",
515
- "export",
516
- "optional_host_permissions",
517
- "side_panel"
396
+ "action",
397
+ "export",
398
+ "optional_host_permissions",
399
+ "side_panel"
518
400
  ];
519
401
  const firefoxMv3OnlyKeys = ["host_permissions"];
520
402
  const DEFAULT_MV3_EXTENSION_PAGES_CSP = "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';";
521
403
  const DEFAULT_MV3_SANDBOX_CSP = "sandbox allow-scripts allow-forms allow-popups allow-modals; script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self';";
522
404
  const DEFAULT_MV2_CSP = "script-src 'self'; object-src 'self';";
405
+
406
+ //#endregion
407
+ export { generateManifest, getContentScriptCssFiles, getContentScriptsCssMap, writeManifest };