wxt 0.18.15 → 0.19.0
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/bin/wxt.mjs +1 -1
- package/dist/browser/chrome.d.ts +17 -0
- package/dist/browser/chrome.mjs +7 -0
- package/dist/browser/index.d.ts +18 -0
- package/dist/browser/index.mjs +2 -0
- package/dist/builtin-modules/index.d.ts +2 -0
- package/dist/builtin-modules/index.mjs +2 -0
- package/dist/builtin-modules/unimport.d.ts +8 -0
- package/dist/builtin-modules/unimport.mjs +99 -0
- package/dist/cli/cli-utils.d.ts +25 -0
- package/dist/cli/cli-utils.mjs +58 -0
- package/dist/cli/commands.d.ts +2 -0
- package/dist/cli/commands.mjs +104 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.mjs +11 -0
- package/dist/client/app-config.d.ts +2 -0
- package/dist/client/app-config.mjs +4 -0
- package/dist/client/content-scripts/content-script-context.d.ts +114 -0
- package/dist/client/content-scripts/content-script-context.mjs +169 -0
- package/dist/client/content-scripts/custom-events.d.ts +10 -0
- package/dist/client/content-scripts/custom-events.mjs +13 -0
- package/dist/client/content-scripts/index.d.ts +2 -0
- package/dist/client/content-scripts/index.mjs +2 -0
- package/dist/client/content-scripts/location-watcher.d.ts +12 -0
- package/dist/client/content-scripts/location-watcher.mjs +22 -0
- package/dist/client/content-scripts/ui/index.d.ts +23 -0
- package/dist/client/content-scripts/ui/index.mjs +188 -0
- package/dist/{client.d.ts → client/content-scripts/ui/types.d.ts} +17 -45
- package/dist/client/content-scripts/ui/types.mjs +0 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.mjs +2 -0
- package/dist/core/build.d.ts +15 -0
- package/dist/core/build.mjs +6 -0
- package/dist/core/builders/vite/index.d.ts +3 -0
- package/dist/core/builders/vite/index.mjs +285 -0
- package/dist/core/builders/vite/plugins/bundleAnalysis.d.ts +7 -0
- package/dist/core/builders/vite/plugins/bundleAnalysis.mjs +15 -0
- package/dist/core/builders/vite/plugins/cssEntrypoints.d.ts +13 -0
- package/dist/core/builders/vite/plugins/cssEntrypoints.mjs +22 -0
- package/dist/core/builders/vite/plugins/defineImportMeta.d.ts +14 -0
- package/dist/core/builders/vite/plugins/defineImportMeta.mjs +13 -0
- package/dist/core/builders/vite/plugins/devHtmlPrerender.d.ts +7 -0
- package/dist/core/builders/vite/plugins/devHtmlPrerender.mjs +140 -0
- package/dist/core/builders/vite/plugins/devServerGlobals.d.ts +6 -0
- package/dist/core/builders/vite/plugins/devServerGlobals.mjs +15 -0
- package/dist/core/builders/vite/plugins/download.d.ts +10 -0
- package/dist/core/builders/vite/plugins/download.mjs +14 -0
- package/dist/core/builders/vite/plugins/entrypointGroupGlobals.d.ts +6 -0
- package/dist/core/builders/vite/plugins/entrypointGroupGlobals.mjs +16 -0
- package/dist/core/builders/vite/plugins/extensionApiMock.d.ts +11 -0
- package/dist/core/builders/vite/plugins/extensionApiMock.mjs +26 -0
- package/dist/core/builders/vite/plugins/globals.d.ts +3 -0
- package/dist/core/builders/vite/plugins/globals.mjs +15 -0
- package/dist/core/builders/vite/plugins/index.d.ts +17 -0
- package/dist/core/builders/vite/plugins/index.mjs +17 -0
- package/dist/core/builders/vite/plugins/multipageMove.d.ts +20 -0
- package/dist/core/builders/vite/plugins/multipageMove.mjs +59 -0
- package/dist/core/builders/vite/plugins/noopBackground.d.ts +6 -0
- package/dist/core/builders/vite/plugins/noopBackground.mjs +17 -0
- package/dist/core/builders/vite/plugins/removeEntrypointMainFunction.d.ts +6 -0
- package/dist/core/builders/vite/plugins/removeEntrypointMainFunction.mjs +12 -0
- package/dist/core/builders/vite/plugins/resolveAppConfig.d.ts +6 -0
- package/dist/core/builders/vite/plugins/resolveAppConfig.mjs +26 -0
- package/dist/core/builders/vite/plugins/resolveExtensionApi.d.ts +10 -0
- package/dist/core/builders/vite/plugins/resolveExtensionApi.mjs +15 -0
- package/dist/core/builders/vite/plugins/resolveVirtualModules.d.ts +6 -0
- package/dist/core/builders/vite/plugins/resolveVirtualModules.mjs +30 -0
- package/dist/core/builders/vite/plugins/tsconfigPaths.d.ts +3 -0
- package/dist/core/builders/vite/plugins/tsconfigPaths.mjs +12 -0
- package/dist/core/builders/vite/plugins/wxtPluginLoader.d.ts +6 -0
- package/dist/core/builders/vite/plugins/wxtPluginLoader.mjs +56 -0
- package/dist/core/clean.d.ts +21 -0
- package/dist/core/clean.mjs +38 -0
- package/dist/core/create-server.d.ts +11 -0
- package/dist/core/create-server.mjs +206 -0
- package/dist/core/define-config.d.ts +2 -0
- package/dist/core/define-config.mjs +3 -0
- package/dist/core/define-runner-config.d.ts +2 -0
- package/dist/core/define-runner-config.mjs +3 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.mjs +8 -0
- package/dist/core/initialize.d.ts +5 -0
- package/dist/core/initialize.mjs +128 -0
- package/dist/core/package-managers/bun.d.ts +2 -0
- package/dist/core/package-managers/bun.mjs +19 -0
- package/dist/core/package-managers/index.d.ts +2 -0
- package/dist/core/package-managers/index.mjs +65 -0
- package/dist/core/package-managers/npm.d.ts +17 -0
- package/dist/core/package-managers/npm.mjs +58 -0
- package/dist/core/package-managers/pnpm.d.ts +2 -0
- package/dist/core/package-managers/pnpm.mjs +21 -0
- package/dist/core/package-managers/types.d.ts +2 -0
- package/dist/core/package-managers/types.mjs +0 -0
- package/dist/core/package-managers/yarn.d.ts +2 -0
- package/dist/core/package-managers/yarn.mjs +31 -0
- package/dist/core/prepare.d.ts +2 -0
- package/dist/core/prepare.mjs +8 -0
- package/dist/core/runners/index.d.ts +2 -0
- package/dist/core/runners/index.mjs +12 -0
- package/dist/core/runners/manual.d.ts +5 -0
- package/dist/core/runners/manual.mjs +16 -0
- package/dist/core/runners/safari.d.ts +5 -0
- package/dist/core/runners/safari.mjs +16 -0
- package/dist/core/runners/web-ext.d.ts +5 -0
- package/dist/core/runners/web-ext.mjs +78 -0
- package/dist/core/runners/wsl.d.ts +5 -0
- package/dist/core/runners/wsl.mjs +16 -0
- package/dist/core/utils/arrays.d.ts +13 -0
- package/dist/{chunk-BERPNPEZ.js → core/utils/arrays.mjs} +6 -10
- package/dist/core/utils/building/build-entrypoints.d.ts +3 -0
- package/dist/core/utils/building/build-entrypoints.mjs +47 -0
- package/dist/core/utils/building/detect-dev-changes.d.ts +57 -0
- package/dist/core/utils/building/detect-dev-changes.mjs +93 -0
- package/dist/core/utils/building/find-entrypoints.d.ts +5 -0
- package/dist/core/utils/building/find-entrypoints.mjs +385 -0
- package/dist/core/utils/building/generate-wxt-dir.d.ts +5 -0
- package/dist/core/utils/building/generate-wxt-dir.mjs +192 -0
- package/dist/core/utils/building/group-entrypoints.d.ts +8 -0
- package/dist/core/utils/building/group-entrypoints.mjs +37 -0
- package/dist/core/utils/building/import-entrypoint.d.ts +16 -0
- package/dist/core/utils/building/import-entrypoint.mjs +97 -0
- package/dist/core/utils/building/index.d.ts +9 -0
- package/dist/core/utils/building/index.mjs +9 -0
- package/dist/core/utils/building/internal-build.d.ts +12 -0
- package/dist/core/utils/building/internal-build.mjs +112 -0
- package/dist/core/utils/building/rebuild.d.ts +23 -0
- package/dist/core/utils/building/rebuild.mjs +39 -0
- package/dist/core/utils/building/resolve-config.d.ts +11 -0
- package/dist/core/utils/building/resolve-config.mjs +364 -0
- package/dist/core/utils/cache.d.ts +8 -0
- package/dist/core/utils/cache.mjs +21 -0
- package/dist/core/utils/cli.d.ts +3 -0
- package/dist/core/utils/cli.mjs +26 -0
- package/dist/core/utils/constants.d.ts +5 -0
- package/dist/core/utils/constants.mjs +1 -0
- package/dist/core/utils/content-scripts.d.ts +11 -0
- package/dist/core/utils/content-scripts.mjs +60 -0
- package/dist/core/utils/content-security-policy.d.ts +14 -0
- package/dist/core/utils/content-security-policy.mjs +39 -0
- package/dist/core/utils/entrypoints.d.ts +25 -0
- package/dist/core/utils/entrypoints.mjs +31 -0
- package/dist/core/utils/eslint.d.ts +1 -0
- package/dist/core/utils/eslint.mjs +11 -0
- package/dist/core/utils/fs.d.ts +13 -0
- package/dist/core/utils/fs.mjs +15 -0
- package/dist/core/utils/globals.d.ts +11 -0
- package/dist/core/utils/globals.mjs +53 -0
- package/dist/core/utils/i18n.d.ts +11 -0
- package/dist/core/utils/i18n.mjs +35 -0
- package/dist/core/utils/log/index.d.ts +4 -0
- package/dist/core/utils/log/index.mjs +4 -0
- package/dist/core/utils/log/printBuildSummary.d.ts +2 -0
- package/dist/core/utils/log/printBuildSummary.mjs +32 -0
- package/dist/core/utils/log/printFileList.d.ts +1 -0
- package/dist/core/utils/log/printFileList.mjs +42 -0
- package/dist/core/utils/log/printHeader.d.ts +1 -0
- package/dist/core/utils/log/printHeader.mjs +7 -0
- package/dist/core/utils/log/printTable.d.ts +1 -0
- package/dist/core/utils/log/printTable.mjs +22 -0
- package/dist/core/utils/manifest.d.ts +44 -0
- package/dist/core/utils/manifest.mjs +512 -0
- package/dist/core/utils/network.d.ts +7 -0
- package/dist/core/utils/network.mjs +38 -0
- package/dist/core/utils/package.d.ts +6 -0
- package/dist/core/utils/package.mjs +14 -0
- package/dist/core/utils/paths.d.ts +11 -0
- package/dist/core/utils/paths.mjs +10 -0
- package/dist/core/utils/strings.d.ts +14 -0
- package/dist/core/utils/strings.mjs +18 -0
- package/dist/core/utils/testing/fake-objects.d.ts +4556 -0
- package/dist/core/utils/testing/fake-objects.mjs +322 -0
- package/dist/core/utils/time.d.ts +9 -0
- package/dist/core/utils/time.mjs +17 -0
- package/dist/core/utils/transform.d.ts +9 -0
- package/dist/core/utils/transform.mjs +17 -0
- package/dist/core/utils/types.d.ts +10 -0
- package/dist/core/utils/types.mjs +0 -0
- package/dist/core/utils/validation.d.ts +15 -0
- package/dist/core/utils/validation.mjs +55 -0
- package/dist/core/utils/virtual-modules.d.ts +22 -0
- package/dist/core/utils/virtual-modules.mjs +14 -0
- package/dist/core/utils/wsl.d.ts +4 -0
- package/dist/core/utils/wsl.mjs +4 -0
- package/dist/core/wxt.d.ts +19 -0
- package/dist/core/wxt.mjs +41 -0
- package/dist/core/zip.d.ts +7 -0
- package/dist/core/zip.mjs +137 -0
- package/dist/index.d.ts +4 -79
- package/dist/index.mjs +3 -0
- package/dist/modules.d.ts +10 -20
- package/dist/{chunk-6XSIWUWF.js → modules.mjs} +7 -16
- package/dist/sandbox/define-app-config.d.ts +19 -0
- package/dist/sandbox/define-app-config.mjs +3 -0
- package/dist/sandbox/define-background.d.ts +3 -0
- package/dist/sandbox/define-background.mjs +4 -0
- package/dist/sandbox/define-content-script.d.ts +2 -0
- package/dist/sandbox/define-content-script.mjs +3 -0
- package/dist/sandbox/define-unlisted-script.d.ts +3 -0
- package/dist/sandbox/define-unlisted-script.mjs +4 -0
- package/dist/sandbox/define-wxt-plugin.d.ts +2 -0
- package/dist/sandbox/define-wxt-plugin.mjs +3 -0
- package/dist/sandbox/dev-server-websocket.d.ts +21 -0
- package/dist/sandbox/dev-server-websocket.mjs +37 -0
- package/dist/sandbox/index.d.ts +11 -0
- package/dist/sandbox/index.mjs +6 -0
- package/dist/sandbox/utils/logger.d.ts +9 -0
- package/dist/sandbox/utils/logger.mjs +15 -0
- package/dist/storage.d.ts +39 -16
- package/dist/{storage.js → storage.mjs} +30 -41
- package/dist/testing/fake-browser.d.ts +1 -0
- package/dist/testing/fake-browser.mjs +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.mjs +2 -0
- package/dist/{testing.d.ts → testing/wxt-vitest-plugin.d.ts} +3 -15
- package/dist/testing/wxt-vitest-plugin.mjs +26 -0
- package/dist/{index-nWRfwAJi.d.cts → types.d.ts} +150 -264
- package/dist/types.mjs +0 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.mjs +1 -0
- package/dist/virtual/{background-entrypoint.js → background-entrypoint.mjs} +31 -40
- package/dist/virtual/{content-script-isolated-world-entrypoint.js → content-script-isolated-world-entrypoint.mjs} +9 -13
- package/dist/virtual/{content-script-main-world-entrypoint.js → content-script-main-world-entrypoint.mjs} +9 -14
- package/dist/virtual/mock-browser.mjs +6 -0
- package/dist/virtual/{reload-html.js → reload-html.mjs} +8 -9
- package/dist/virtual/{unlisted-script-entrypoint.js → unlisted-script-entrypoint.mjs} +8 -12
- package/package.json +47 -57
- package/dist/browser.d.ts +0 -18
- package/dist/browser.js +0 -6
- package/dist/chunk-BM6QYGAW.js +0 -1063
- package/dist/chunk-FNTE2L27.js +0 -7
- package/dist/chunk-FP7RYLVL.js +0 -3617
- package/dist/chunk-KPD5J7PZ.js +0 -1065
- package/dist/chunk-QGM4M3NI.js +0 -37
- package/dist/chunk-SGKCDMVR.js +0 -38
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +0 -4438
- package/dist/client.js +0 -424
- package/dist/define-app-config-bg54F_lV.d.ts +0 -294
- package/dist/execa-4UBDUBJZ.js +0 -7244
- package/dist/execa-QLUM2B3W.js +0 -7245
- package/dist/index-nWRfwAJi.d.ts +0 -1401
- package/dist/index.cjs +0 -14473
- package/dist/index.d.cts +0 -81
- package/dist/index.js +0 -696
- package/dist/modules.cjs +0 -96
- package/dist/modules.d.cts +0 -119
- package/dist/modules.js +0 -17
- package/dist/prompt-25QIVJDC.js +0 -755
- package/dist/prompt-7BMKNSWS.js +0 -754
- package/dist/sandbox.d.ts +0 -16
- package/dist/sandbox.js +0 -36
- package/dist/storage.cjs +0 -439
- package/dist/storage.d.cts +0 -200
- package/dist/testing.cjs +0 -2815
- package/dist/testing.d.cts +0 -30
- package/dist/testing.js +0 -40
- package/dist/virtual/mock-browser.js +0 -6
package/dist/chunk-FP7RYLVL.js
DELETED
|
@@ -1,3617 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
every,
|
|
3
|
-
some,
|
|
4
|
-
toArray
|
|
5
|
-
} from "./chunk-BERPNPEZ.js";
|
|
6
|
-
import {
|
|
7
|
-
addViteConfig,
|
|
8
|
-
defineWxtModule
|
|
9
|
-
} from "./chunk-6XSIWUWF.js";
|
|
10
|
-
import {
|
|
11
|
-
LogLevels,
|
|
12
|
-
consola
|
|
13
|
-
} from "./chunk-BM6QYGAW.js";
|
|
14
|
-
import {
|
|
15
|
-
__require
|
|
16
|
-
} from "./chunk-QGM4M3NI.js";
|
|
17
|
-
|
|
18
|
-
// package.json
|
|
19
|
-
var version = "0.18.14";
|
|
20
|
-
|
|
21
|
-
// src/core/utils/paths.ts
|
|
22
|
-
import systemPath from "node:path";
|
|
23
|
-
import normalize from "normalize-path";
|
|
24
|
-
function normalizePath(path8) {
|
|
25
|
-
return normalize(path8);
|
|
26
|
-
}
|
|
27
|
-
function unnormalizePath(path8) {
|
|
28
|
-
return systemPath.normalize(path8);
|
|
29
|
-
}
|
|
30
|
-
var CSS_EXTENSIONS = ["css", "scss", "sass", "less", "styl", "stylus"];
|
|
31
|
-
var CSS_EXTENSIONS_PATTERN = `+(${CSS_EXTENSIONS.join("|")})`;
|
|
32
|
-
|
|
33
|
-
// src/core/utils/entrypoints.ts
|
|
34
|
-
import path, { relative, resolve } from "node:path";
|
|
35
|
-
function getEntrypointName(entrypointsDir, inputPath) {
|
|
36
|
-
const relativePath = path.relative(entrypointsDir, inputPath);
|
|
37
|
-
const name = relativePath.split(/[\.\/\\]/, 2)[0];
|
|
38
|
-
return name;
|
|
39
|
-
}
|
|
40
|
-
function getEntrypointOutputFile(entrypoint, ext) {
|
|
41
|
-
return resolve(entrypoint.outputDir, `${entrypoint.name}${ext}`);
|
|
42
|
-
}
|
|
43
|
-
function getEntrypointBundlePath(entrypoint, outDir, ext) {
|
|
44
|
-
return normalizePath(
|
|
45
|
-
relative(outDir, getEntrypointOutputFile(entrypoint, ext))
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
function resolvePerBrowserOption(option, browser) {
|
|
49
|
-
if (typeof option === "object" && !Array.isArray(option))
|
|
50
|
-
return option[browser];
|
|
51
|
-
return option;
|
|
52
|
-
}
|
|
53
|
-
function resolvePerBrowserOptions(options, browser) {
|
|
54
|
-
return Object.fromEntries(
|
|
55
|
-
Object.entries(options).map(([key, value]) => [
|
|
56
|
-
key,
|
|
57
|
-
key === "defaultIcon" ? value : resolvePerBrowserOption(value, browser)
|
|
58
|
-
])
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
function isHtmlEntrypoint(entrypoint) {
|
|
62
|
-
return entrypoint.inputPath.endsWith(".html");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// src/core/utils/time.ts
|
|
66
|
-
function formatDuration(duration) {
|
|
67
|
-
if (duration < 1e3) return `${duration} ms`;
|
|
68
|
-
if (duration < 1e4) return `${(duration / 1e3).toFixed(3)} s`;
|
|
69
|
-
if (duration < 6e4) return `${(duration / 1e3).toFixed(1)} s`;
|
|
70
|
-
return `${(duration / 1e3).toFixed(0)} s`;
|
|
71
|
-
}
|
|
72
|
-
function withTimeout(promise, duration) {
|
|
73
|
-
return new Promise((res, rej) => {
|
|
74
|
-
const timeout = setTimeout(() => {
|
|
75
|
-
rej(`Promise timed out after ${duration}ms`);
|
|
76
|
-
}, duration);
|
|
77
|
-
promise.then(res).catch(rej).finally(() => clearTimeout(timeout));
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// src/core/utils/network.ts
|
|
82
|
-
import dns from "node:dns";
|
|
83
|
-
function isOffline() {
|
|
84
|
-
const isOffline2 = new Promise((res) => {
|
|
85
|
-
dns.resolve("google.com", (err) => {
|
|
86
|
-
if (err == null) {
|
|
87
|
-
res(false);
|
|
88
|
-
} else {
|
|
89
|
-
res(true);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
return withTimeout(isOffline2, 1e3).catch(() => true);
|
|
94
|
-
}
|
|
95
|
-
async function isOnline() {
|
|
96
|
-
const offline = await isOffline();
|
|
97
|
-
return !offline;
|
|
98
|
-
}
|
|
99
|
-
async function fetchCached(url, config) {
|
|
100
|
-
let content = "";
|
|
101
|
-
if (await isOnline()) {
|
|
102
|
-
const res = await fetch(url);
|
|
103
|
-
if (res.status < 300) {
|
|
104
|
-
content = await res.text();
|
|
105
|
-
await config.fsCache.set(url, content);
|
|
106
|
-
} else {
|
|
107
|
-
config.logger.debug(
|
|
108
|
-
`Failed to download "${url}", falling back to cache...`
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (!content) content = await config.fsCache.get(url) ?? "";
|
|
113
|
-
if (!content)
|
|
114
|
-
throw Error(
|
|
115
|
-
`Offline and "${url}" has not been cached. Try again when online.`
|
|
116
|
-
);
|
|
117
|
-
return content;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// src/core/builders/vite/plugins/download.ts
|
|
121
|
-
function download(config) {
|
|
122
|
-
return {
|
|
123
|
-
name: "wxt:download",
|
|
124
|
-
resolveId(id) {
|
|
125
|
-
if (id.startsWith("url:")) return "\0" + id;
|
|
126
|
-
},
|
|
127
|
-
async load(id) {
|
|
128
|
-
if (!id.startsWith("\0url:")) return;
|
|
129
|
-
const url = id.replace("\0url:", "");
|
|
130
|
-
return await fetchCached(url, config);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// src/core/builders/vite/plugins/tsconfigPaths.ts
|
|
136
|
-
function tsconfigPaths(config) {
|
|
137
|
-
return {
|
|
138
|
-
name: "wxt:aliases",
|
|
139
|
-
async config() {
|
|
140
|
-
return {
|
|
141
|
-
resolve: {
|
|
142
|
-
alias: config.alias
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// src/core/utils/globals.ts
|
|
150
|
-
function getGlobals(config) {
|
|
151
|
-
return [
|
|
152
|
-
{
|
|
153
|
-
name: "MANIFEST_VERSION",
|
|
154
|
-
value: config.manifestVersion,
|
|
155
|
-
type: `2 | 3`
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
name: "BROWSER",
|
|
159
|
-
value: config.browser,
|
|
160
|
-
type: `string`
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
name: "CHROME",
|
|
164
|
-
value: config.browser === "chrome",
|
|
165
|
-
type: `boolean`
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
name: "FIREFOX",
|
|
169
|
-
value: config.browser === "firefox",
|
|
170
|
-
type: `boolean`
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
name: "SAFARI",
|
|
174
|
-
value: config.browser === "safari",
|
|
175
|
-
type: `boolean`
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
name: "EDGE",
|
|
179
|
-
value: config.browser === "edge",
|
|
180
|
-
type: `boolean`
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
name: "OPERA",
|
|
184
|
-
value: config.browser === "opera",
|
|
185
|
-
type: `boolean`
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
name: "COMMAND",
|
|
189
|
-
value: config.command,
|
|
190
|
-
type: `"build" | "serve"`
|
|
191
|
-
}
|
|
192
|
-
];
|
|
193
|
-
}
|
|
194
|
-
function getEntrypointGlobals(entrypointName) {
|
|
195
|
-
return [
|
|
196
|
-
{
|
|
197
|
-
name: "ENTRYPOINT",
|
|
198
|
-
value: entrypointName,
|
|
199
|
-
type: `string`
|
|
200
|
-
}
|
|
201
|
-
];
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// src/core/builders/vite/plugins/globals.ts
|
|
205
|
-
function globals(config) {
|
|
206
|
-
return {
|
|
207
|
-
name: "wxt:globals",
|
|
208
|
-
config() {
|
|
209
|
-
const define = {};
|
|
210
|
-
for (const global of getGlobals(config)) {
|
|
211
|
-
define[`import.meta.env.${global.name}`] = JSON.stringify(global.value);
|
|
212
|
-
}
|
|
213
|
-
return {
|
|
214
|
-
define
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// src/core/builders/vite/plugins/webextensionPolyfillMock.ts
|
|
221
|
-
import path2 from "node:path";
|
|
222
|
-
function webextensionPolyfillMock(config) {
|
|
223
|
-
return {
|
|
224
|
-
name: "wxt:testing-inline-deps",
|
|
225
|
-
config() {
|
|
226
|
-
return {
|
|
227
|
-
resolve: {
|
|
228
|
-
alias: {
|
|
229
|
-
// Alias to use a mocked version of the polyfill
|
|
230
|
-
"webextension-polyfill": path2.resolve(
|
|
231
|
-
config.wxtModuleDir,
|
|
232
|
-
"dist/virtual/mock-browser"
|
|
233
|
-
)
|
|
234
|
-
}
|
|
235
|
-
},
|
|
236
|
-
ssr: {
|
|
237
|
-
// Inline all WXT modules
|
|
238
|
-
noExternal: ["wxt"]
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// src/core/builders/vite/plugins/resolveAppConfig.ts
|
|
246
|
-
import { exists } from "fs-extra";
|
|
247
|
-
import { resolve as resolve2 } from "node:path";
|
|
248
|
-
function resolveAppConfig(config) {
|
|
249
|
-
const virtualModuleId = "virtual:app-config";
|
|
250
|
-
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
251
|
-
const appConfigFile = resolve2(config.srcDir, "app.config.ts");
|
|
252
|
-
return {
|
|
253
|
-
name: "wxt:resolve-app-config",
|
|
254
|
-
config() {
|
|
255
|
-
return {
|
|
256
|
-
optimizeDeps: {
|
|
257
|
-
// Prevent ESBuild from attempting to resolve the virtual module
|
|
258
|
-
// while optimizing WXT.
|
|
259
|
-
exclude: [virtualModuleId]
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
},
|
|
263
|
-
async resolveId(id) {
|
|
264
|
-
if (id !== virtualModuleId) return;
|
|
265
|
-
return await exists(appConfigFile) ? appConfigFile : resolvedVirtualModuleId;
|
|
266
|
-
},
|
|
267
|
-
load(id) {
|
|
268
|
-
if (id === resolvedVirtualModuleId) return `export default {}`;
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// src/core/builders/vite/plugins/devHtmlPrerender.ts
|
|
274
|
-
import { parseHTML } from "linkedom";
|
|
275
|
-
import { dirname, relative as relative2, resolve as resolve3 } from "node:path";
|
|
276
|
-
import { murmurHash } from "ohash";
|
|
277
|
-
var inlineScriptContents = {};
|
|
278
|
-
function devHtmlPrerender(config, server) {
|
|
279
|
-
const htmlReloadId = "@wxt/reload-html";
|
|
280
|
-
const resolvedHtmlReloadId = resolve3(
|
|
281
|
-
config.wxtModuleDir,
|
|
282
|
-
"dist/virtual/reload-html.js"
|
|
283
|
-
);
|
|
284
|
-
const virtualInlineScript = "virtual:wxt-inline-script";
|
|
285
|
-
const resolvedVirtualInlineScript = "\0" + virtualInlineScript;
|
|
286
|
-
return [
|
|
287
|
-
{
|
|
288
|
-
apply: "build",
|
|
289
|
-
name: "wxt:dev-html-prerender",
|
|
290
|
-
config() {
|
|
291
|
-
return {
|
|
292
|
-
resolve: {
|
|
293
|
-
alias: {
|
|
294
|
-
[htmlReloadId]: resolvedHtmlReloadId
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
|
-
},
|
|
299
|
-
// Convert scripts like src="./main.tsx" -> src="http://localhost:3000/entrypoints/popup/main.tsx"
|
|
300
|
-
// before the paths are replaced with their bundled path
|
|
301
|
-
transform(code, id) {
|
|
302
|
-
if (config.command !== "serve" || server == null || !id.endsWith(".html"))
|
|
303
|
-
return;
|
|
304
|
-
const { document } = parseHTML(code);
|
|
305
|
-
const _pointToDevServer = (querySelector, attr) => pointToDevServer(config, server, id, document, querySelector, attr);
|
|
306
|
-
_pointToDevServer("script[type=module]", "src");
|
|
307
|
-
_pointToDevServer("link[rel=stylesheet]", "href");
|
|
308
|
-
const reloader = document.createElement("script");
|
|
309
|
-
reloader.src = htmlReloadId;
|
|
310
|
-
reloader.type = "module";
|
|
311
|
-
document.head.appendChild(reloader);
|
|
312
|
-
const newHtml = document.toString();
|
|
313
|
-
config.logger.debug("transform " + id);
|
|
314
|
-
config.logger.debug("Old HTML:\n" + code);
|
|
315
|
-
config.logger.debug("New HTML:\n" + newHtml);
|
|
316
|
-
return newHtml;
|
|
317
|
-
},
|
|
318
|
-
// Pass the HTML through the dev server to add dev-mode specific code
|
|
319
|
-
async transformIndexHtml(html, ctx) {
|
|
320
|
-
if (config.command !== "serve" || server == null) return;
|
|
321
|
-
const originalUrl = `${server.origin}${ctx.path}`;
|
|
322
|
-
const name = getEntrypointName(config.entrypointsDir, ctx.filename);
|
|
323
|
-
const url = `${server.origin}/${name}.html`;
|
|
324
|
-
const serverHtml = await server.transformHtml(url, html, originalUrl);
|
|
325
|
-
const { document } = parseHTML(serverHtml);
|
|
326
|
-
const inlineScripts = document.querySelectorAll("script:not([src])");
|
|
327
|
-
inlineScripts.forEach((script) => {
|
|
328
|
-
const textContent = script.textContent ?? "";
|
|
329
|
-
const hash = murmurHash(textContent);
|
|
330
|
-
inlineScriptContents[hash] = textContent;
|
|
331
|
-
const virtualScript = document.createElement("script");
|
|
332
|
-
virtualScript.type = "module";
|
|
333
|
-
virtualScript.src = `${server.origin}/@id/${virtualInlineScript}?${hash}`;
|
|
334
|
-
script.replaceWith(virtualScript);
|
|
335
|
-
});
|
|
336
|
-
const viteClientScript = document.querySelector(
|
|
337
|
-
"script[src='/@vite/client']"
|
|
338
|
-
);
|
|
339
|
-
if (viteClientScript) {
|
|
340
|
-
viteClientScript.src = `${server.origin}${viteClientScript.src}`;
|
|
341
|
-
}
|
|
342
|
-
const newHtml = document.toString();
|
|
343
|
-
config.logger.debug("transformIndexHtml " + ctx.filename);
|
|
344
|
-
config.logger.debug("Old HTML:\n" + html);
|
|
345
|
-
config.logger.debug("New HTML:\n" + newHtml);
|
|
346
|
-
return newHtml;
|
|
347
|
-
}
|
|
348
|
-
},
|
|
349
|
-
{
|
|
350
|
-
name: "wxt:virtualize-react-refresh",
|
|
351
|
-
apply: "serve",
|
|
352
|
-
resolveId(id) {
|
|
353
|
-
if (id.startsWith(virtualInlineScript)) {
|
|
354
|
-
return "\0" + id;
|
|
355
|
-
}
|
|
356
|
-
if (id.startsWith("/chunks/")) {
|
|
357
|
-
return "\0noop";
|
|
358
|
-
}
|
|
359
|
-
},
|
|
360
|
-
load(id) {
|
|
361
|
-
if (id.startsWith(resolvedVirtualInlineScript)) {
|
|
362
|
-
const hash = Number(id.substring(id.indexOf("?") + 1));
|
|
363
|
-
return inlineScriptContents[hash];
|
|
364
|
-
}
|
|
365
|
-
if (id === "\0noop") {
|
|
366
|
-
return "";
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
];
|
|
371
|
-
}
|
|
372
|
-
function pointToDevServer(config, server, id, document, querySelector, attr) {
|
|
373
|
-
document.querySelectorAll(querySelector).forEach((element) => {
|
|
374
|
-
const src = element.getAttribute(attr);
|
|
375
|
-
if (!src || isUrl(src)) return;
|
|
376
|
-
let resolvedAbsolutePath;
|
|
377
|
-
const matchingAlias = Object.entries(config.alias).find(
|
|
378
|
-
([key]) => src.startsWith(key)
|
|
379
|
-
);
|
|
380
|
-
if (matchingAlias) {
|
|
381
|
-
const [alias, replacement] = matchingAlias;
|
|
382
|
-
resolvedAbsolutePath = resolve3(
|
|
383
|
-
config.root,
|
|
384
|
-
src.replace(alias, replacement)
|
|
385
|
-
);
|
|
386
|
-
} else {
|
|
387
|
-
resolvedAbsolutePath = resolve3(dirname(id), src);
|
|
388
|
-
}
|
|
389
|
-
if (resolvedAbsolutePath) {
|
|
390
|
-
const relativePath = normalizePath(
|
|
391
|
-
relative2(config.root, resolvedAbsolutePath)
|
|
392
|
-
);
|
|
393
|
-
if (relativePath.startsWith(".")) {
|
|
394
|
-
let path8 = normalizePath(resolvedAbsolutePath);
|
|
395
|
-
if (!path8.startsWith("/")) path8 = "/" + path8;
|
|
396
|
-
element.setAttribute(attr, `${server.origin}/@fs${path8}`);
|
|
397
|
-
} else {
|
|
398
|
-
const url = new URL(relativePath, server.origin);
|
|
399
|
-
element.setAttribute(attr, url.href);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
function isUrl(str) {
|
|
405
|
-
try {
|
|
406
|
-
new URL(str);
|
|
407
|
-
return true;
|
|
408
|
-
} catch {
|
|
409
|
-
return false;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// src/core/builders/vite/plugins/devServerGlobals.ts
|
|
414
|
-
function devServerGlobals(config, server) {
|
|
415
|
-
return {
|
|
416
|
-
name: "wxt:dev-server-globals",
|
|
417
|
-
config() {
|
|
418
|
-
if (server == null || config.command == "build") return;
|
|
419
|
-
return {
|
|
420
|
-
define: {
|
|
421
|
-
__DEV_SERVER_PROTOCOL__: JSON.stringify("ws:"),
|
|
422
|
-
__DEV_SERVER_HOSTNAME__: JSON.stringify(server.hostname),
|
|
423
|
-
__DEV_SERVER_PORT__: JSON.stringify(server.port)
|
|
424
|
-
}
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// src/core/builders/vite/plugins/multipageMove.ts
|
|
431
|
-
import { dirname as dirname2, extname, resolve as resolve4, join } from "node:path";
|
|
432
|
-
import fs, { ensureDir } from "fs-extra";
|
|
433
|
-
function multipageMove(entrypoints, config) {
|
|
434
|
-
return {
|
|
435
|
-
name: "wxt:multipage-move",
|
|
436
|
-
async writeBundle(_, bundle) {
|
|
437
|
-
for (const oldBundlePath in bundle) {
|
|
438
|
-
const entrypoint = entrypoints.find(
|
|
439
|
-
(entry) => !!normalizePath(entry.inputPath).endsWith(oldBundlePath)
|
|
440
|
-
);
|
|
441
|
-
if (entrypoint == null) {
|
|
442
|
-
config.logger.debug(
|
|
443
|
-
`No entrypoint found for ${oldBundlePath}, leaving in chunks directory`
|
|
444
|
-
);
|
|
445
|
-
continue;
|
|
446
|
-
}
|
|
447
|
-
const newBundlePath = getEntrypointBundlePath(
|
|
448
|
-
entrypoint,
|
|
449
|
-
config.outDir,
|
|
450
|
-
extname(oldBundlePath)
|
|
451
|
-
);
|
|
452
|
-
if (newBundlePath === oldBundlePath) {
|
|
453
|
-
config.logger.debug(
|
|
454
|
-
"HTML file is already in the correct location",
|
|
455
|
-
oldBundlePath
|
|
456
|
-
);
|
|
457
|
-
continue;
|
|
458
|
-
}
|
|
459
|
-
const oldAbsPath = resolve4(config.outDir, oldBundlePath);
|
|
460
|
-
const newAbsPath = resolve4(config.outDir, newBundlePath);
|
|
461
|
-
await ensureDir(dirname2(newAbsPath));
|
|
462
|
-
await fs.move(oldAbsPath, newAbsPath, { overwrite: true });
|
|
463
|
-
const renamedChunk = {
|
|
464
|
-
...bundle[oldBundlePath],
|
|
465
|
-
fileName: newBundlePath
|
|
466
|
-
};
|
|
467
|
-
delete bundle[oldBundlePath];
|
|
468
|
-
bundle[newBundlePath] = renamedChunk;
|
|
469
|
-
}
|
|
470
|
-
removeEmptyDirs(config.outDir);
|
|
471
|
-
}
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
async function removeEmptyDirs(dir) {
|
|
475
|
-
const files = await fs.readdir(dir);
|
|
476
|
-
for (const file of files) {
|
|
477
|
-
const filePath = join(dir, file);
|
|
478
|
-
const stats = await fs.stat(filePath);
|
|
479
|
-
if (stats.isDirectory()) {
|
|
480
|
-
await removeEmptyDirs(filePath);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
try {
|
|
484
|
-
await fs.rmdir(dir);
|
|
485
|
-
} catch {
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
// src/core/utils/virtual-modules.ts
|
|
490
|
-
var virtualEntrypointTypes = [
|
|
491
|
-
"content-script-main-world",
|
|
492
|
-
"content-script-isolated-world",
|
|
493
|
-
"background",
|
|
494
|
-
"unlisted-script"
|
|
495
|
-
];
|
|
496
|
-
var virtualEntrypointModuleNames = virtualEntrypointTypes.map(
|
|
497
|
-
(name) => `${name}-entrypoint`
|
|
498
|
-
);
|
|
499
|
-
var virtualModuleNames = [
|
|
500
|
-
...virtualEntrypointModuleNames,
|
|
501
|
-
"mock-browser",
|
|
502
|
-
"reload-html"
|
|
503
|
-
];
|
|
504
|
-
|
|
505
|
-
// src/core/builders/vite/plugins/resolveVirtualModules.ts
|
|
506
|
-
import fs2 from "fs-extra";
|
|
507
|
-
import { resolve as resolve5 } from "path";
|
|
508
|
-
function resolveVirtualModules(config) {
|
|
509
|
-
return virtualModuleNames.map((name) => {
|
|
510
|
-
const virtualId = `virtual:wxt-${name}?`;
|
|
511
|
-
const resolvedVirtualId = "\0" + virtualId;
|
|
512
|
-
return {
|
|
513
|
-
name: `wxt:resolve-virtual-${name}`,
|
|
514
|
-
resolveId(id) {
|
|
515
|
-
const index = id.indexOf(virtualId);
|
|
516
|
-
if (index === -1) return;
|
|
517
|
-
const inputPath = normalizePath(id.substring(index + virtualId.length));
|
|
518
|
-
return resolvedVirtualId + inputPath;
|
|
519
|
-
},
|
|
520
|
-
async load(id) {
|
|
521
|
-
if (!id.startsWith(resolvedVirtualId)) return;
|
|
522
|
-
const inputPath = id.replace(resolvedVirtualId, "");
|
|
523
|
-
const template = await fs2.readFile(
|
|
524
|
-
resolve5(config.wxtModuleDir, `dist/virtual/${name}.js`),
|
|
525
|
-
"utf-8"
|
|
526
|
-
);
|
|
527
|
-
return template.replace(`virtual:user-${name}`, inputPath);
|
|
528
|
-
}
|
|
529
|
-
};
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
// src/core/utils/constants.ts
|
|
534
|
-
var VIRTUAL_NOOP_BACKGROUND_MODULE_ID = "virtual:user-background";
|
|
535
|
-
|
|
536
|
-
// src/core/builders/vite/plugins/noopBackground.ts
|
|
537
|
-
function noopBackground() {
|
|
538
|
-
const virtualModuleId = VIRTUAL_NOOP_BACKGROUND_MODULE_ID;
|
|
539
|
-
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
540
|
-
return {
|
|
541
|
-
name: "wxt:noop-background",
|
|
542
|
-
resolveId(id) {
|
|
543
|
-
if (id === virtualModuleId) return resolvedVirtualModuleId;
|
|
544
|
-
},
|
|
545
|
-
load(id) {
|
|
546
|
-
if (id === resolvedVirtualModuleId) {
|
|
547
|
-
return `import { defineBackground } from 'wxt/sandbox';
|
|
548
|
-
export default defineBackground(() => void 0)`;
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
// src/core/builders/vite/plugins/cssEntrypoints.ts
|
|
555
|
-
function cssEntrypoints(entrypoint, config) {
|
|
556
|
-
return {
|
|
557
|
-
name: "wxt:css-entrypoint",
|
|
558
|
-
config() {
|
|
559
|
-
return {
|
|
560
|
-
build: {
|
|
561
|
-
rollupOptions: {
|
|
562
|
-
output: {
|
|
563
|
-
assetFileNames: () => getEntrypointBundlePath(entrypoint, config.outDir, ".css")
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
};
|
|
568
|
-
},
|
|
569
|
-
generateBundle(_, bundle) {
|
|
570
|
-
Object.keys(bundle).forEach((file) => {
|
|
571
|
-
if (file.endsWith(".js")) delete bundle[file];
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
// src/core/builders/vite/plugins/bundleAnalysis.ts
|
|
578
|
-
import { visualizer } from "@aklinker1/rollup-plugin-visualizer";
|
|
579
|
-
import path3 from "node:path";
|
|
580
|
-
var increment = 0;
|
|
581
|
-
function bundleAnalysis(config) {
|
|
582
|
-
return visualizer({
|
|
583
|
-
template: "raw-data",
|
|
584
|
-
filename: path3.resolve(
|
|
585
|
-
config.analysis.outputDir,
|
|
586
|
-
`${config.analysis.outputName}-${increment++}.json`
|
|
587
|
-
)
|
|
588
|
-
});
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
// src/core/builders/vite/plugins/excludeBrowserPolyfill.ts
|
|
592
|
-
function excludeBrowserPolyfill(config) {
|
|
593
|
-
const virtualId = "virtual:wxt-webextension-polyfill-disabled";
|
|
594
|
-
return {
|
|
595
|
-
name: "wxt:exclude-browser-polyfill",
|
|
596
|
-
config() {
|
|
597
|
-
if (config.experimental.includeBrowserPolyfill) return;
|
|
598
|
-
return {
|
|
599
|
-
resolve: {
|
|
600
|
-
alias: {
|
|
601
|
-
"webextension-polyfill": virtualId
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
};
|
|
605
|
-
},
|
|
606
|
-
load(id) {
|
|
607
|
-
if (id === virtualId) {
|
|
608
|
-
return "export default chrome";
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// src/core/builders/vite/plugins/entrypointGroupGlobals.ts
|
|
615
|
-
function entrypointGroupGlobals(entrypointGroup) {
|
|
616
|
-
return {
|
|
617
|
-
name: "wxt:entrypoint-group-globals",
|
|
618
|
-
config() {
|
|
619
|
-
const define = {};
|
|
620
|
-
let name = Array.isArray(entrypointGroup) ? "html" : entrypointGroup.name;
|
|
621
|
-
for (const global of getEntrypointGlobals(name)) {
|
|
622
|
-
define[`import.meta.env.${global.name}`] = JSON.stringify(global.value);
|
|
623
|
-
}
|
|
624
|
-
return {
|
|
625
|
-
define
|
|
626
|
-
};
|
|
627
|
-
}
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
// src/core/builders/vite/plugins/defineImportMeta.ts
|
|
632
|
-
function defineImportMeta() {
|
|
633
|
-
return {
|
|
634
|
-
name: "wxt:define",
|
|
635
|
-
config() {
|
|
636
|
-
return {
|
|
637
|
-
define: {
|
|
638
|
-
// This works for all extension contexts, including background service worker
|
|
639
|
-
"import.meta.url": "self.location.href"
|
|
640
|
-
}
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
};
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
// src/core/utils/transform.ts
|
|
647
|
-
import { parseModule } from "magicast";
|
|
648
|
-
function removeMainFunctionCode(code) {
|
|
649
|
-
const mod = parseModule(code);
|
|
650
|
-
emptyMainFunction(mod);
|
|
651
|
-
return mod.generate();
|
|
652
|
-
}
|
|
653
|
-
function emptyMainFunction(mod) {
|
|
654
|
-
if (mod.exports?.default?.$type === "function-call") {
|
|
655
|
-
if (mod.exports.default.$ast?.arguments?.[0]?.body) {
|
|
656
|
-
mod.exports.default.$ast.arguments[0].body.body = [];
|
|
657
|
-
} else if (mod.exports.default.$ast?.arguments?.[0]?.properties) {
|
|
658
|
-
mod.exports.default.$ast.arguments[0].properties = mod.exports.default.$ast.arguments[0].properties.filter(
|
|
659
|
-
(prop) => prop.key.name !== "main"
|
|
660
|
-
);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
// src/core/builders/vite/plugins/removeEntrypointMainFunction.ts
|
|
666
|
-
import { resolve as resolve6 } from "node:path";
|
|
667
|
-
function removeEntrypointMainFunction(config, path8) {
|
|
668
|
-
const absPath = normalizePath(resolve6(config.root, path8));
|
|
669
|
-
return {
|
|
670
|
-
name: "wxt:remove-entrypoint-main-function",
|
|
671
|
-
transform(code, id) {
|
|
672
|
-
if (id === absPath) return removeMainFunctionCode(code);
|
|
673
|
-
}
|
|
674
|
-
};
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
// src/core/builders/vite/plugins/wxtPluginLoader.ts
|
|
678
|
-
import { parseHTML as parseHTML2 } from "linkedom";
|
|
679
|
-
function wxtPluginLoader(config) {
|
|
680
|
-
const virtualModuleId = "virtual:wxt-plugins";
|
|
681
|
-
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
682
|
-
const virtualHtmlModuleId = "virtual:wxt-html-plugins";
|
|
683
|
-
const resolvedVirtualHtmlModuleId = "\0" + virtualHtmlModuleId;
|
|
684
|
-
return {
|
|
685
|
-
name: "wxt:plugin-loader",
|
|
686
|
-
resolveId(id) {
|
|
687
|
-
if (id === virtualModuleId) return resolvedVirtualModuleId;
|
|
688
|
-
if (id === virtualHtmlModuleId) return resolvedVirtualHtmlModuleId;
|
|
689
|
-
},
|
|
690
|
-
load(id) {
|
|
691
|
-
if (id === resolvedVirtualModuleId) {
|
|
692
|
-
const imports = config.plugins.map(
|
|
693
|
-
(plugin, i) => `import initPlugin${i} from '${normalizePath(plugin)}';`
|
|
694
|
-
).join("\n");
|
|
695
|
-
const initCalls = config.plugins.map((_, i) => ` initPlugin${i}();`).join("\n");
|
|
696
|
-
return `${imports}
|
|
697
|
-
|
|
698
|
-
export function initPlugins() {
|
|
699
|
-
${initCalls}
|
|
700
|
-
}`;
|
|
701
|
-
}
|
|
702
|
-
if (id === resolvedVirtualHtmlModuleId) {
|
|
703
|
-
return `import { initPlugins } from '${virtualModuleId}';
|
|
704
|
-
|
|
705
|
-
try {
|
|
706
|
-
initPlugins();
|
|
707
|
-
} catch (err) {
|
|
708
|
-
console.error("[wxt] Failed to initialize plugins", err);
|
|
709
|
-
}`;
|
|
710
|
-
}
|
|
711
|
-
},
|
|
712
|
-
transformIndexHtml: {
|
|
713
|
-
// Use "pre" so the new script is added before vite bundles all the scripts
|
|
714
|
-
order: "pre",
|
|
715
|
-
handler(html, _ctx) {
|
|
716
|
-
const src = config.command === "serve" ? `http://${config.dev.server?.hostname}:${config.dev.server?.port}/@id/${virtualHtmlModuleId}` : virtualHtmlModuleId;
|
|
717
|
-
const { document } = parseHTML2(html);
|
|
718
|
-
const existing = document.querySelector(`script[src='${src}']`);
|
|
719
|
-
if (existing) return;
|
|
720
|
-
const script = document.createElement("script");
|
|
721
|
-
script.type = "module";
|
|
722
|
-
script.src = src;
|
|
723
|
-
if (document.head == null) {
|
|
724
|
-
const newHead = document.createElement("head");
|
|
725
|
-
document.documentElement.prepend(newHead);
|
|
726
|
-
}
|
|
727
|
-
document.head.prepend(script);
|
|
728
|
-
return document.toString();
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
};
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
// src/core/utils/strings.ts
|
|
735
|
-
function kebabCaseAlphanumeric(str) {
|
|
736
|
-
return str.toLowerCase().replace(/[^a-z0-9-\s]/g, "").replace(/\s+/g, "-");
|
|
737
|
-
}
|
|
738
|
-
function safeVarName(str) {
|
|
739
|
-
return "_" + kebabCaseAlphanumeric(str.trim()).replace("-", "_");
|
|
740
|
-
}
|
|
741
|
-
function removeImportStatements(text) {
|
|
742
|
-
return text.replace(
|
|
743
|
-
/(import\s?[\s\S]*?from\s?["'][\s\S]*?["'];?|import\s?["'][\s\S]*?["'];?)/gm,
|
|
744
|
-
""
|
|
745
|
-
);
|
|
746
|
-
}
|
|
747
|
-
function removeProjectImportStatements(text) {
|
|
748
|
-
const noImports = removeImportStatements(text);
|
|
749
|
-
return `import { defineUnlistedScript, defineContentScript, defineBackground } from 'wxt/sandbox';
|
|
750
|
-
|
|
751
|
-
${noImports}`;
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
// src/builtin-modules/unimport.ts
|
|
755
|
-
import { createUnimport } from "unimport";
|
|
756
|
-
import { extname as extname2 } from "node:path";
|
|
757
|
-
var unimport_default = defineWxtModule({
|
|
758
|
-
name: "wxt:built-in:unimport",
|
|
759
|
-
setup(wxt2) {
|
|
760
|
-
const options = wxt2.config.imports;
|
|
761
|
-
if (options === false) return;
|
|
762
|
-
let unimport;
|
|
763
|
-
wxt2.hooks.hook("ready", () => {
|
|
764
|
-
const addModuleImports = (module) => {
|
|
765
|
-
if (!module.imports) return;
|
|
766
|
-
options.imports ??= [];
|
|
767
|
-
options.imports.push(...module.imports);
|
|
768
|
-
};
|
|
769
|
-
wxt2.config.builtinModules.forEach(addModuleImports);
|
|
770
|
-
wxt2.config.userModules.forEach(addModuleImports);
|
|
771
|
-
});
|
|
772
|
-
wxt2.hooks.afterEach((event) => {
|
|
773
|
-
if (event.name === "ready") {
|
|
774
|
-
unimport = createUnimport(options);
|
|
775
|
-
}
|
|
776
|
-
});
|
|
777
|
-
wxt2.hooks.hook("prepare:types", async (_, entries) => {
|
|
778
|
-
await unimport.init();
|
|
779
|
-
entries.push(await getImportsDeclarationEntry(unimport));
|
|
780
|
-
if (options.eslintrc.enabled === false) return;
|
|
781
|
-
entries.push(
|
|
782
|
-
await getEslintConfigEntry(unimport, options.eslintrc.enabled, options)
|
|
783
|
-
);
|
|
784
|
-
});
|
|
785
|
-
addViteConfig(wxt2, () => ({
|
|
786
|
-
plugins: [vitePlugin(unimport)]
|
|
787
|
-
}));
|
|
788
|
-
}
|
|
789
|
-
});
|
|
790
|
-
function vitePlugin(unimport) {
|
|
791
|
-
const ENABLED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
792
|
-
".js",
|
|
793
|
-
".jsx",
|
|
794
|
-
".ts",
|
|
795
|
-
".tsx",
|
|
796
|
-
".vue",
|
|
797
|
-
".svelte"
|
|
798
|
-
]);
|
|
799
|
-
return {
|
|
800
|
-
name: "wxt:unimport",
|
|
801
|
-
async transform(code, id) {
|
|
802
|
-
if (id.includes("node_modules")) return;
|
|
803
|
-
if (!ENABLED_EXTENSIONS.has(extname2(id))) return;
|
|
804
|
-
const injected = await unimport.injectImports(code, id);
|
|
805
|
-
return {
|
|
806
|
-
code: injected.code,
|
|
807
|
-
map: injected.s.generateMap({ hires: "boundary", source: id })
|
|
808
|
-
};
|
|
809
|
-
}
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
|
-
async function getImportsDeclarationEntry(unimport) {
|
|
813
|
-
await unimport.init();
|
|
814
|
-
return {
|
|
815
|
-
path: "types/imports.d.ts",
|
|
816
|
-
text: [
|
|
817
|
-
"// Generated by wxt",
|
|
818
|
-
await unimport.generateTypeDeclarations(),
|
|
819
|
-
""
|
|
820
|
-
].join("\n"),
|
|
821
|
-
tsReference: true
|
|
822
|
-
};
|
|
823
|
-
}
|
|
824
|
-
async function getEslintConfigEntry(unimport, version2, options) {
|
|
825
|
-
const globals2 = (await unimport.getImports()).map((i) => i.as ?? i.name).filter(Boolean).sort().reduce((globals3, name) => {
|
|
826
|
-
globals3[name] = options.eslintrc.globalsPropValue;
|
|
827
|
-
return globals3;
|
|
828
|
-
}, {});
|
|
829
|
-
if (version2 <= 8) return getEslint8ConfigEntry(options, globals2);
|
|
830
|
-
else return getEslint9ConfigEntry(options, globals2);
|
|
831
|
-
}
|
|
832
|
-
function getEslint8ConfigEntry(options, globals2) {
|
|
833
|
-
return {
|
|
834
|
-
path: options.eslintrc.filePath,
|
|
835
|
-
text: JSON.stringify({ globals: globals2 }, null, 2) + "\n"
|
|
836
|
-
};
|
|
837
|
-
}
|
|
838
|
-
function getEslint9ConfigEntry(options, globals2) {
|
|
839
|
-
return {
|
|
840
|
-
path: options.eslintrc.filePath,
|
|
841
|
-
text: `const globals = ${JSON.stringify(globals2, null, 2)}
|
|
842
|
-
|
|
843
|
-
export default {
|
|
844
|
-
name: "wxt/auto-imports",
|
|
845
|
-
languageOptions: {
|
|
846
|
-
globals,
|
|
847
|
-
sourceType: "module",
|
|
848
|
-
},
|
|
849
|
-
};
|
|
850
|
-
`
|
|
851
|
-
};
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
// src/core/utils/fs.ts
|
|
855
|
-
import fs3 from "fs-extra";
|
|
856
|
-
import glob from "fast-glob";
|
|
857
|
-
async function writeFileIfDifferent(file, newContents) {
|
|
858
|
-
const existingContents = await fs3.readFile(file, "utf-8").catch(() => void 0);
|
|
859
|
-
if (existingContents !== newContents) {
|
|
860
|
-
await fs3.writeFile(file, newContents);
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
async function getPublicFiles() {
|
|
864
|
-
if (!await fs3.exists(wxt.config.publicDir)) return [];
|
|
865
|
-
const files = await glob("**/*", { cwd: wxt.config.publicDir });
|
|
866
|
-
return files.map(unnormalizePath);
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
// src/core/utils/building/build-entrypoints.ts
|
|
870
|
-
import fs4 from "fs-extra";
|
|
871
|
-
import { dirname as dirname3, resolve as resolve7 } from "path";
|
|
872
|
-
import pc from "picocolors";
|
|
873
|
-
async function buildEntrypoints(groups, spinner) {
|
|
874
|
-
const steps = [];
|
|
875
|
-
for (let i = 0; i < groups.length; i++) {
|
|
876
|
-
const group = groups[i];
|
|
877
|
-
const groupNames = toArray(group).map((e) => e.name);
|
|
878
|
-
const groupNameColored = groupNames.join(pc.dim(", "));
|
|
879
|
-
spinner.text = pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNameColored}`;
|
|
880
|
-
try {
|
|
881
|
-
steps.push(await wxt.builder.build(group));
|
|
882
|
-
} catch (err) {
|
|
883
|
-
spinner.stop().clear();
|
|
884
|
-
wxt.logger.error(err);
|
|
885
|
-
throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
const publicAssets = await copyPublicDirectory();
|
|
889
|
-
return { publicAssets, steps };
|
|
890
|
-
}
|
|
891
|
-
async function copyPublicDirectory() {
|
|
892
|
-
const files = (await getPublicFiles()).map((file) => ({
|
|
893
|
-
absoluteSrc: resolve7(wxt.config.publicDir, file),
|
|
894
|
-
relativeDest: file
|
|
895
|
-
}));
|
|
896
|
-
await wxt.hooks.callHook("build:publicAssets", wxt, files);
|
|
897
|
-
if (files.length === 0) return [];
|
|
898
|
-
const publicAssets = [];
|
|
899
|
-
for (const file of files) {
|
|
900
|
-
const absoluteDest = resolve7(wxt.config.outDir, file.relativeDest);
|
|
901
|
-
await fs4.ensureDir(dirname3(absoluteDest));
|
|
902
|
-
if ("absoluteSrc" in file) {
|
|
903
|
-
await fs4.copyFile(file.absoluteSrc, absoluteDest);
|
|
904
|
-
} else {
|
|
905
|
-
await fs4.writeFile(absoluteDest, file.contents, "utf8");
|
|
906
|
-
}
|
|
907
|
-
publicAssets.push({
|
|
908
|
-
type: "asset",
|
|
909
|
-
fileName: file.relativeDest
|
|
910
|
-
});
|
|
911
|
-
}
|
|
912
|
-
return publicAssets;
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
// src/core/utils/building/detect-dev-changes.ts
|
|
916
|
-
function detectDevChanges(changedFiles, currentOutput) {
|
|
917
|
-
const isConfigChange = some(
|
|
918
|
-
changedFiles,
|
|
919
|
-
(file) => file === wxt.config.userConfigMetadata.configFile
|
|
920
|
-
);
|
|
921
|
-
if (isConfigChange) return { type: "full-restart" };
|
|
922
|
-
const isRunnerChange = some(
|
|
923
|
-
changedFiles,
|
|
924
|
-
(file) => file === wxt.config.runnerConfig.configFile
|
|
925
|
-
);
|
|
926
|
-
if (isRunnerChange) return { type: "browser-restart" };
|
|
927
|
-
const changedSteps = new Set(
|
|
928
|
-
changedFiles.flatMap(
|
|
929
|
-
(changedFile) => findEffectedSteps(changedFile, currentOutput)
|
|
930
|
-
)
|
|
931
|
-
);
|
|
932
|
-
if (changedSteps.size === 0) {
|
|
933
|
-
const hasPublicChange = some(
|
|
934
|
-
changedFiles,
|
|
935
|
-
(file) => file.startsWith(wxt.config.publicDir)
|
|
936
|
-
);
|
|
937
|
-
if (hasPublicChange) {
|
|
938
|
-
return {
|
|
939
|
-
type: "extension-reload",
|
|
940
|
-
rebuildGroups: [],
|
|
941
|
-
cachedOutput: currentOutput
|
|
942
|
-
};
|
|
943
|
-
} else {
|
|
944
|
-
return { type: "no-change" };
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
const unchangedOutput = {
|
|
948
|
-
manifest: currentOutput.manifest,
|
|
949
|
-
steps: [],
|
|
950
|
-
publicAssets: [...currentOutput.publicAssets]
|
|
951
|
-
};
|
|
952
|
-
const changedOutput = {
|
|
953
|
-
manifest: currentOutput.manifest,
|
|
954
|
-
steps: [],
|
|
955
|
-
publicAssets: []
|
|
956
|
-
};
|
|
957
|
-
for (const step of currentOutput.steps) {
|
|
958
|
-
if (changedSteps.has(step)) {
|
|
959
|
-
changedOutput.steps.push(step);
|
|
960
|
-
} else {
|
|
961
|
-
unchangedOutput.steps.push(step);
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
const isOnlyHtmlChanges = changedFiles.length > 0 && every(changedFiles, (file) => file.endsWith(".html"));
|
|
965
|
-
if (isOnlyHtmlChanges) {
|
|
966
|
-
return {
|
|
967
|
-
type: "html-reload",
|
|
968
|
-
cachedOutput: unchangedOutput,
|
|
969
|
-
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
970
|
-
};
|
|
971
|
-
}
|
|
972
|
-
const isOnlyContentScripts = changedOutput.steps.length > 0 && every(
|
|
973
|
-
changedOutput.steps.flatMap((step) => step.entrypoints),
|
|
974
|
-
(entry) => entry.type === "content-script"
|
|
975
|
-
);
|
|
976
|
-
if (isOnlyContentScripts) {
|
|
977
|
-
return {
|
|
978
|
-
type: "content-script-reload",
|
|
979
|
-
cachedOutput: unchangedOutput,
|
|
980
|
-
changedSteps: changedOutput.steps,
|
|
981
|
-
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
return {
|
|
985
|
-
type: "extension-reload",
|
|
986
|
-
cachedOutput: unchangedOutput,
|
|
987
|
-
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
988
|
-
};
|
|
989
|
-
}
|
|
990
|
-
function findEffectedSteps(changedFile, currentOutput) {
|
|
991
|
-
const changes = [];
|
|
992
|
-
const changedPath = normalizePath(changedFile);
|
|
993
|
-
const isChunkEffected = (chunk) => (
|
|
994
|
-
// If it's an HTML file with the same path, is is effected because HTML files need to be re-rendered
|
|
995
|
-
// - fileName is normalized, relative bundle path, "<entrypoint-name>.html"
|
|
996
|
-
chunk.type === "asset" && changedPath.replace("/index.html", ".html").endsWith(chunk.fileName) || // If it's a chunk that depends on the changed file, it is effected
|
|
997
|
-
// - moduleIds are absolute, normalized paths
|
|
998
|
-
chunk.type === "chunk" && chunk.moduleIds.includes(changedPath)
|
|
999
|
-
);
|
|
1000
|
-
for (const step of currentOutput.steps) {
|
|
1001
|
-
const effectedChunk = step.chunks.find((chunk) => isChunkEffected(chunk));
|
|
1002
|
-
if (effectedChunk) changes.push(step);
|
|
1003
|
-
}
|
|
1004
|
-
return changes;
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
// src/core/utils/building/find-entrypoints.ts
|
|
1008
|
-
import { relative as relative3, resolve as resolve8 } from "path";
|
|
1009
|
-
import fs5 from "fs-extra";
|
|
1010
|
-
import { minimatch } from "minimatch";
|
|
1011
|
-
import { parseHTML as parseHTML3 } from "linkedom";
|
|
1012
|
-
import JSON5 from "json5";
|
|
1013
|
-
import glob2 from "fast-glob";
|
|
1014
|
-
import pc2 from "picocolors";
|
|
1015
|
-
async function findEntrypoints() {
|
|
1016
|
-
await fs5.mkdir(wxt.config.wxtDir, { recursive: true });
|
|
1017
|
-
await fs5.writeJson(resolve8(wxt.config.wxtDir, "tsconfig.json"), {});
|
|
1018
|
-
const relativePaths = await glob2(Object.keys(PATH_GLOB_TO_TYPE_MAP), {
|
|
1019
|
-
cwd: wxt.config.entrypointsDir
|
|
1020
|
-
});
|
|
1021
|
-
relativePaths.sort();
|
|
1022
|
-
const pathGlobs = Object.keys(PATH_GLOB_TO_TYPE_MAP);
|
|
1023
|
-
const entrypointInfos = relativePaths.reduce((results, relativePath) => {
|
|
1024
|
-
const inputPath = resolve8(wxt.config.entrypointsDir, relativePath);
|
|
1025
|
-
const name = getEntrypointName(wxt.config.entrypointsDir, inputPath);
|
|
1026
|
-
const matchingGlob = pathGlobs.find(
|
|
1027
|
-
(glob5) => minimatch(relativePath, glob5)
|
|
1028
|
-
);
|
|
1029
|
-
if (matchingGlob) {
|
|
1030
|
-
const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
|
|
1031
|
-
results.push({
|
|
1032
|
-
name,
|
|
1033
|
-
inputPath,
|
|
1034
|
-
type,
|
|
1035
|
-
skipped: wxt.config.filterEntrypoints != null && !wxt.config.filterEntrypoints.has(name)
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
|
-
return results;
|
|
1039
|
-
}, []);
|
|
1040
|
-
preventNoEntrypoints(entrypointInfos);
|
|
1041
|
-
preventDuplicateEntrypointNames(entrypointInfos);
|
|
1042
|
-
let hasBackground = false;
|
|
1043
|
-
const entrypoints = await Promise.all(
|
|
1044
|
-
entrypointInfos.map(async (info) => {
|
|
1045
|
-
const { type } = info;
|
|
1046
|
-
switch (type) {
|
|
1047
|
-
case "popup":
|
|
1048
|
-
return await getPopupEntrypoint(info);
|
|
1049
|
-
case "sidepanel":
|
|
1050
|
-
return await getSidepanelEntrypoint(info);
|
|
1051
|
-
case "options":
|
|
1052
|
-
return await getOptionsEntrypoint(info);
|
|
1053
|
-
case "background":
|
|
1054
|
-
hasBackground = true;
|
|
1055
|
-
return await getBackgroundEntrypoint(info);
|
|
1056
|
-
case "content-script":
|
|
1057
|
-
return await getContentScriptEntrypoint(info);
|
|
1058
|
-
case "unlisted-page":
|
|
1059
|
-
return await getUnlistedPageEntrypoint(info);
|
|
1060
|
-
case "unlisted-script":
|
|
1061
|
-
return await getUnlistedScriptEntrypoint(info);
|
|
1062
|
-
case "content-script-style":
|
|
1063
|
-
return {
|
|
1064
|
-
...info,
|
|
1065
|
-
type,
|
|
1066
|
-
outputDir: resolve8(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
|
|
1067
|
-
options: {
|
|
1068
|
-
include: void 0,
|
|
1069
|
-
exclude: void 0
|
|
1070
|
-
}
|
|
1071
|
-
};
|
|
1072
|
-
default:
|
|
1073
|
-
return {
|
|
1074
|
-
...info,
|
|
1075
|
-
type,
|
|
1076
|
-
outputDir: wxt.config.outDir,
|
|
1077
|
-
options: {
|
|
1078
|
-
include: void 0,
|
|
1079
|
-
exclude: void 0
|
|
1080
|
-
}
|
|
1081
|
-
};
|
|
1082
|
-
}
|
|
1083
|
-
})
|
|
1084
|
-
);
|
|
1085
|
-
if (wxt.config.command === "serve" && !hasBackground) {
|
|
1086
|
-
entrypoints.push(
|
|
1087
|
-
await getBackgroundEntrypoint({
|
|
1088
|
-
inputPath: VIRTUAL_NOOP_BACKGROUND_MODULE_ID,
|
|
1089
|
-
name: "background",
|
|
1090
|
-
type: "background",
|
|
1091
|
-
skipped: false
|
|
1092
|
-
})
|
|
1093
|
-
);
|
|
1094
|
-
}
|
|
1095
|
-
wxt.logger.debug("All entrypoints:", entrypoints);
|
|
1096
|
-
const skippedEntrypointNames = entrypointInfos.filter((item) => item.skipped).map((item) => item.name);
|
|
1097
|
-
if (skippedEntrypointNames.length) {
|
|
1098
|
-
wxt.logger.warn(
|
|
1099
|
-
`Filter excluded the following entrypoints:
|
|
1100
|
-
${skippedEntrypointNames.map((item) => `${pc2.dim("-")} ${pc2.cyan(item)}`).join("\n")}`
|
|
1101
|
-
);
|
|
1102
|
-
}
|
|
1103
|
-
const targetEntrypoints = entrypoints.filter((entry) => {
|
|
1104
|
-
const { include, exclude } = entry.options;
|
|
1105
|
-
if (include?.length && exclude?.length) {
|
|
1106
|
-
wxt.logger.warn(
|
|
1107
|
-
`The ${entry.name} entrypoint lists both include and exclude, but only one can be used per entrypoint. Entrypoint ignored.`
|
|
1108
|
-
);
|
|
1109
|
-
return false;
|
|
1110
|
-
}
|
|
1111
|
-
if (exclude?.length && !include?.length) {
|
|
1112
|
-
return !exclude.includes(wxt.config.browser);
|
|
1113
|
-
}
|
|
1114
|
-
if (include?.length && !exclude?.length) {
|
|
1115
|
-
return include.includes(wxt.config.browser);
|
|
1116
|
-
}
|
|
1117
|
-
if (skippedEntrypointNames.includes(entry.name)) {
|
|
1118
|
-
return false;
|
|
1119
|
-
}
|
|
1120
|
-
return true;
|
|
1121
|
-
});
|
|
1122
|
-
wxt.logger.debug(`${wxt.config.browser} entrypoints:`, targetEntrypoints);
|
|
1123
|
-
await wxt.hooks.callHook("entrypoints:resolved", wxt, targetEntrypoints);
|
|
1124
|
-
return targetEntrypoints;
|
|
1125
|
-
}
|
|
1126
|
-
function preventDuplicateEntrypointNames(files) {
|
|
1127
|
-
const namesToPaths = files.reduce(
|
|
1128
|
-
(map, { name, inputPath }) => {
|
|
1129
|
-
map[name] ??= [];
|
|
1130
|
-
map[name].push(inputPath);
|
|
1131
|
-
return map;
|
|
1132
|
-
},
|
|
1133
|
-
{}
|
|
1134
|
-
);
|
|
1135
|
-
const errorLines = Object.entries(namesToPaths).reduce(
|
|
1136
|
-
(lines, [name, absolutePaths]) => {
|
|
1137
|
-
if (absolutePaths.length > 1) {
|
|
1138
|
-
lines.push(`- ${name}`);
|
|
1139
|
-
absolutePaths.forEach((absolutePath) => {
|
|
1140
|
-
lines.push(` - ${relative3(wxt.config.root, absolutePath)}`);
|
|
1141
|
-
});
|
|
1142
|
-
}
|
|
1143
|
-
return lines;
|
|
1144
|
-
},
|
|
1145
|
-
[]
|
|
1146
|
-
);
|
|
1147
|
-
if (errorLines.length > 0) {
|
|
1148
|
-
const errorContent = errorLines.join("\n");
|
|
1149
|
-
throw Error(
|
|
1150
|
-
`Multiple entrypoints with the same name detected, only one entrypoint for each name is allowed.
|
|
1151
|
-
|
|
1152
|
-
${errorContent}`
|
|
1153
|
-
);
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
function preventNoEntrypoints(files) {
|
|
1157
|
-
if (files.length === 0) {
|
|
1158
|
-
throw Error(`No entrypoints found in ${wxt.config.entrypointsDir}`);
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
async function getPopupEntrypoint(info) {
|
|
1162
|
-
const options = await getHtmlEntrypointOptions(
|
|
1163
|
-
info,
|
|
1164
|
-
{
|
|
1165
|
-
browserStyle: "browse_style",
|
|
1166
|
-
exclude: "exclude",
|
|
1167
|
-
include: "include",
|
|
1168
|
-
defaultIcon: "default_icon",
|
|
1169
|
-
defaultTitle: "default_title",
|
|
1170
|
-
mv2Key: "type"
|
|
1171
|
-
},
|
|
1172
|
-
{
|
|
1173
|
-
defaultTitle: (document) => document.querySelector("title")?.textContent || void 0
|
|
1174
|
-
},
|
|
1175
|
-
{
|
|
1176
|
-
defaultTitle: (content) => content,
|
|
1177
|
-
mv2Key: (content) => content === "page_action" ? "page_action" : "browser_action"
|
|
1178
|
-
}
|
|
1179
|
-
);
|
|
1180
|
-
return {
|
|
1181
|
-
type: "popup",
|
|
1182
|
-
name: "popup",
|
|
1183
|
-
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
|
1184
|
-
inputPath: info.inputPath,
|
|
1185
|
-
outputDir: wxt.config.outDir,
|
|
1186
|
-
skipped: info.skipped
|
|
1187
|
-
};
|
|
1188
|
-
}
|
|
1189
|
-
async function getOptionsEntrypoint(info) {
|
|
1190
|
-
const options = await getHtmlEntrypointOptions(
|
|
1191
|
-
info,
|
|
1192
|
-
{
|
|
1193
|
-
browserStyle: "browse_style",
|
|
1194
|
-
chromeStyle: "chrome_style",
|
|
1195
|
-
exclude: "exclude",
|
|
1196
|
-
include: "include",
|
|
1197
|
-
openInTab: "open_in_tab"
|
|
1198
|
-
}
|
|
1199
|
-
);
|
|
1200
|
-
return {
|
|
1201
|
-
type: "options",
|
|
1202
|
-
name: "options",
|
|
1203
|
-
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
|
1204
|
-
inputPath: info.inputPath,
|
|
1205
|
-
outputDir: wxt.config.outDir,
|
|
1206
|
-
skipped: info.skipped
|
|
1207
|
-
};
|
|
1208
|
-
}
|
|
1209
|
-
async function getUnlistedPageEntrypoint(info) {
|
|
1210
|
-
const options = await getHtmlEntrypointOptions(info, {
|
|
1211
|
-
exclude: "exclude",
|
|
1212
|
-
include: "include"
|
|
1213
|
-
});
|
|
1214
|
-
return {
|
|
1215
|
-
type: "unlisted-page",
|
|
1216
|
-
name: info.name,
|
|
1217
|
-
inputPath: info.inputPath,
|
|
1218
|
-
outputDir: wxt.config.outDir,
|
|
1219
|
-
options,
|
|
1220
|
-
skipped: info.skipped
|
|
1221
|
-
};
|
|
1222
|
-
}
|
|
1223
|
-
async function getUnlistedScriptEntrypoint({
|
|
1224
|
-
inputPath,
|
|
1225
|
-
name,
|
|
1226
|
-
skipped
|
|
1227
|
-
}) {
|
|
1228
|
-
const defaultExport = await wxt.builder.importEntrypoint(inputPath);
|
|
1229
|
-
if (defaultExport == null) {
|
|
1230
|
-
throw Error(
|
|
1231
|
-
`${name}: Default export not found, did you forget to call "export default defineUnlistedScript(...)"?`
|
|
1232
|
-
);
|
|
1233
|
-
}
|
|
1234
|
-
const { main: _, ...options } = defaultExport;
|
|
1235
|
-
return {
|
|
1236
|
-
type: "unlisted-script",
|
|
1237
|
-
name,
|
|
1238
|
-
inputPath,
|
|
1239
|
-
outputDir: wxt.config.outDir,
|
|
1240
|
-
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
|
1241
|
-
skipped
|
|
1242
|
-
};
|
|
1243
|
-
}
|
|
1244
|
-
async function getBackgroundEntrypoint({
|
|
1245
|
-
inputPath,
|
|
1246
|
-
name,
|
|
1247
|
-
skipped
|
|
1248
|
-
}) {
|
|
1249
|
-
let options = {};
|
|
1250
|
-
if (inputPath !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
|
|
1251
|
-
const defaultExport = await wxt.builder.importEntrypoint(inputPath);
|
|
1252
|
-
if (defaultExport == null) {
|
|
1253
|
-
throw Error(
|
|
1254
|
-
`${name}: Default export not found, did you forget to call "export default defineBackground(...)"?`
|
|
1255
|
-
);
|
|
1256
|
-
}
|
|
1257
|
-
const { main: _, ...moduleOptions } = defaultExport;
|
|
1258
|
-
options = moduleOptions;
|
|
1259
|
-
}
|
|
1260
|
-
if (wxt.config.manifestVersion !== 3) {
|
|
1261
|
-
delete options.type;
|
|
1262
|
-
}
|
|
1263
|
-
return {
|
|
1264
|
-
type: "background",
|
|
1265
|
-
name,
|
|
1266
|
-
inputPath,
|
|
1267
|
-
outputDir: wxt.config.outDir,
|
|
1268
|
-
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
|
1269
|
-
skipped
|
|
1270
|
-
};
|
|
1271
|
-
}
|
|
1272
|
-
async function getContentScriptEntrypoint({
|
|
1273
|
-
inputPath,
|
|
1274
|
-
name,
|
|
1275
|
-
skipped
|
|
1276
|
-
}) {
|
|
1277
|
-
const defaultExport = await wxt.builder.importEntrypoint(inputPath);
|
|
1278
|
-
if (defaultExport == null) {
|
|
1279
|
-
throw Error(
|
|
1280
|
-
`${name}: Default export not found, did you forget to call "export default defineContentScript(...)"?`
|
|
1281
|
-
);
|
|
1282
|
-
}
|
|
1283
|
-
const { main: _, ...options } = defaultExport;
|
|
1284
|
-
if (options == null) {
|
|
1285
|
-
throw Error(
|
|
1286
|
-
`${name}: Default export not found, did you forget to call "export default defineContentScript(...)"?`
|
|
1287
|
-
);
|
|
1288
|
-
}
|
|
1289
|
-
return {
|
|
1290
|
-
type: "content-script",
|
|
1291
|
-
name,
|
|
1292
|
-
inputPath,
|
|
1293
|
-
outputDir: resolve8(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
|
|
1294
|
-
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
|
1295
|
-
skipped
|
|
1296
|
-
};
|
|
1297
|
-
}
|
|
1298
|
-
async function getSidepanelEntrypoint(info) {
|
|
1299
|
-
const options = await getHtmlEntrypointOptions(
|
|
1300
|
-
info,
|
|
1301
|
-
{
|
|
1302
|
-
browserStyle: "browse_style",
|
|
1303
|
-
exclude: "exclude",
|
|
1304
|
-
include: "include",
|
|
1305
|
-
defaultIcon: "default_icon",
|
|
1306
|
-
defaultTitle: "default_title",
|
|
1307
|
-
openAtInstall: "open_at_install"
|
|
1308
|
-
},
|
|
1309
|
-
{
|
|
1310
|
-
defaultTitle: (document) => document.querySelector("title")?.textContent || void 0
|
|
1311
|
-
},
|
|
1312
|
-
{
|
|
1313
|
-
defaultTitle: (content) => content
|
|
1314
|
-
}
|
|
1315
|
-
);
|
|
1316
|
-
return {
|
|
1317
|
-
type: "sidepanel",
|
|
1318
|
-
name: info.name,
|
|
1319
|
-
options: resolvePerBrowserOptions(options, wxt.config.browser),
|
|
1320
|
-
inputPath: info.inputPath,
|
|
1321
|
-
outputDir: wxt.config.outDir,
|
|
1322
|
-
skipped: info.skipped
|
|
1323
|
-
};
|
|
1324
|
-
}
|
|
1325
|
-
async function getHtmlEntrypointOptions(info, keyMap, queries, parsers) {
|
|
1326
|
-
const content = await fs5.readFile(info.inputPath, "utf-8");
|
|
1327
|
-
const { document } = parseHTML3(content);
|
|
1328
|
-
const options = {};
|
|
1329
|
-
const defaultQuery = (manifestKey) => document.querySelector(`meta[name='manifest.${manifestKey}']`)?.getAttribute("content");
|
|
1330
|
-
Object.entries(keyMap).forEach(([_key, manifestKey]) => {
|
|
1331
|
-
const key = _key;
|
|
1332
|
-
const content2 = queries?.[key] ? queries[key](document, manifestKey) : defaultQuery(manifestKey);
|
|
1333
|
-
if (content2) {
|
|
1334
|
-
try {
|
|
1335
|
-
options[key] = (parsers?.[key] ?? JSON5.parse)(content2);
|
|
1336
|
-
} catch (err) {
|
|
1337
|
-
wxt.logger.fatal(
|
|
1338
|
-
`Failed to parse meta tag content. Usually this means you have invalid JSON5 content (content=${content2})`,
|
|
1339
|
-
err
|
|
1340
|
-
);
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
});
|
|
1344
|
-
return options;
|
|
1345
|
-
}
|
|
1346
|
-
var PATH_GLOB_TO_TYPE_MAP = {
|
|
1347
|
-
"sandbox.html": "sandbox",
|
|
1348
|
-
"sandbox/index.html": "sandbox",
|
|
1349
|
-
"*.sandbox.html": "sandbox",
|
|
1350
|
-
"*.sandbox/index.html": "sandbox",
|
|
1351
|
-
"bookmarks.html": "bookmarks",
|
|
1352
|
-
"bookmarks/index.html": "bookmarks",
|
|
1353
|
-
"history.html": "history",
|
|
1354
|
-
"history/index.html": "history",
|
|
1355
|
-
"newtab.html": "newtab",
|
|
1356
|
-
"newtab/index.html": "newtab",
|
|
1357
|
-
"sidepanel.html": "sidepanel",
|
|
1358
|
-
"sidepanel/index.html": "sidepanel",
|
|
1359
|
-
"*.sidepanel.html": "sidepanel",
|
|
1360
|
-
"*.sidepanel/index.html": "sidepanel",
|
|
1361
|
-
"devtools.html": "devtools",
|
|
1362
|
-
"devtools/index.html": "devtools",
|
|
1363
|
-
"background.[jt]s": "background",
|
|
1364
|
-
"background/index.[jt]s": "background",
|
|
1365
|
-
[VIRTUAL_NOOP_BACKGROUND_MODULE_ID]: "background",
|
|
1366
|
-
"content.[jt]s?(x)": "content-script",
|
|
1367
|
-
"content/index.[jt]s?(x)": "content-script",
|
|
1368
|
-
"*.content.[jt]s?(x)": "content-script",
|
|
1369
|
-
"*.content/index.[jt]s?(x)": "content-script",
|
|
1370
|
-
[`content.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
|
|
1371
|
-
[`*.content.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
|
|
1372
|
-
[`content/index.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
|
|
1373
|
-
[`*.content/index.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
|
|
1374
|
-
"popup.html": "popup",
|
|
1375
|
-
"popup/index.html": "popup",
|
|
1376
|
-
"options.html": "options",
|
|
1377
|
-
"options/index.html": "options",
|
|
1378
|
-
"*.html": "unlisted-page",
|
|
1379
|
-
"*/index.html": "unlisted-page",
|
|
1380
|
-
"*.[jt]s?(x)": "unlisted-script",
|
|
1381
|
-
"*/index.[jt]s?(x)": "unlisted-script",
|
|
1382
|
-
[`*.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style",
|
|
1383
|
-
[`*/index.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style"
|
|
1384
|
-
};
|
|
1385
|
-
var CONTENT_SCRIPT_OUT_DIR = "content-scripts";
|
|
1386
|
-
|
|
1387
|
-
// src/core/utils/building/generate-wxt-dir.ts
|
|
1388
|
-
import fs6 from "fs-extra";
|
|
1389
|
-
import { dirname as dirname4, relative as relative4, resolve as resolve9 } from "node:path";
|
|
1390
|
-
import path4 from "node:path";
|
|
1391
|
-
|
|
1392
|
-
// src/core/utils/i18n.ts
|
|
1393
|
-
var predefinedMessages = {
|
|
1394
|
-
"@@extension_id": {
|
|
1395
|
-
message: "<browser.runtime.id>",
|
|
1396
|
-
description: "The extension or app ID; you might use this string to construct URLs for resources inside the extension. Even unlocalized extensions can use this message.\nNote: You can't use this message in a manifest file."
|
|
1397
|
-
},
|
|
1398
|
-
"@@ui_locale": {
|
|
1399
|
-
message: "<browser.i18n.getUiLocale()>",
|
|
1400
|
-
description: ""
|
|
1401
|
-
},
|
|
1402
|
-
"@@bidi_dir": {
|
|
1403
|
-
message: "<ltr|rtl>",
|
|
1404
|
-
description: 'The text direction for the current locale, either "ltr" for left-to-right languages such as English or "rtl" for right-to-left languages such as Japanese.'
|
|
1405
|
-
},
|
|
1406
|
-
"@@bidi_reversed_dir": {
|
|
1407
|
-
message: "<rtl|ltr>",
|
|
1408
|
-
description: `If the @@bidi_dir is "ltr", then this is "rtl"; otherwise, it's "ltr".`
|
|
1409
|
-
},
|
|
1410
|
-
"@@bidi_start_edge": {
|
|
1411
|
-
message: "<left|right>",
|
|
1412
|
-
description: `If the @@bidi_dir is "ltr", then this is "left"; otherwise, it's "right".`
|
|
1413
|
-
},
|
|
1414
|
-
"@@bidi_end_edge": {
|
|
1415
|
-
message: "<right|left>",
|
|
1416
|
-
description: `If the @@bidi_dir is "ltr", then this is "right"; otherwise, it's "left".`
|
|
1417
|
-
}
|
|
1418
|
-
};
|
|
1419
|
-
function parseI18nMessages(messagesJson) {
|
|
1420
|
-
return Object.entries({
|
|
1421
|
-
...predefinedMessages,
|
|
1422
|
-
...messagesJson
|
|
1423
|
-
}).map(([name, details]) => ({
|
|
1424
|
-
name,
|
|
1425
|
-
...details
|
|
1426
|
-
}));
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
// src/core/utils/building/generate-wxt-dir.ts
|
|
1430
|
-
async function generateTypesDir(entrypoints) {
|
|
1431
|
-
await fs6.ensureDir(wxt.config.typesDir);
|
|
1432
|
-
const entries = [
|
|
1433
|
-
// Hard-coded entries
|
|
1434
|
-
{ module: "wxt/vite-builder-env" }
|
|
1435
|
-
];
|
|
1436
|
-
wxt.config.userModules.forEach((module) => {
|
|
1437
|
-
if (module.type === "node_module") entries.push({ module: module.id });
|
|
1438
|
-
});
|
|
1439
|
-
entries.push(await getPathsDeclarationEntry(entrypoints));
|
|
1440
|
-
entries.push(await getI18nDeclarationEntry());
|
|
1441
|
-
entries.push(await getGlobalsDeclarationEntry());
|
|
1442
|
-
entries.push(await getTsConfigEntry());
|
|
1443
|
-
await wxt.hooks.callHook("prepare:types", wxt, entries);
|
|
1444
|
-
entries.push(getMainDeclarationEntry(entries));
|
|
1445
|
-
const absoluteFileEntries = entries.filter((entry) => "path" in entry).map((entry) => ({
|
|
1446
|
-
...entry,
|
|
1447
|
-
path: resolve9(wxt.config.wxtDir, entry.path)
|
|
1448
|
-
}));
|
|
1449
|
-
await Promise.all(
|
|
1450
|
-
absoluteFileEntries.map(async (file) => {
|
|
1451
|
-
await fs6.ensureDir(dirname4(file.path));
|
|
1452
|
-
await writeFileIfDifferent(file.path, file.text);
|
|
1453
|
-
})
|
|
1454
|
-
);
|
|
1455
|
-
}
|
|
1456
|
-
async function getPathsDeclarationEntry(entrypoints) {
|
|
1457
|
-
const unions = entrypoints.map(
|
|
1458
|
-
(entry) => getEntrypointBundlePath(
|
|
1459
|
-
entry,
|
|
1460
|
-
wxt.config.outDir,
|
|
1461
|
-
isHtmlEntrypoint(entry) ? ".html" : ".js"
|
|
1462
|
-
)
|
|
1463
|
-
).concat(await getPublicFiles()).map(normalizePath).map((path8) => ` | "/${path8}"`).sort().join("\n");
|
|
1464
|
-
const template = `// Generated by wxt
|
|
1465
|
-
import "wxt/browser";
|
|
1466
|
-
|
|
1467
|
-
declare module "wxt/browser" {
|
|
1468
|
-
export type PublicPath =
|
|
1469
|
-
{{ union }}
|
|
1470
|
-
type HtmlPublicPath = Extract<PublicPath, \`\${string}.html\`>
|
|
1471
|
-
export interface WxtRuntime extends Runtime.Static {
|
|
1472
|
-
getURL(path: PublicPath): string;
|
|
1473
|
-
getURL(path: \`\${HtmlPublicPath}\${string}\`): string;
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
`;
|
|
1477
|
-
return {
|
|
1478
|
-
path: "types/paths.d.ts",
|
|
1479
|
-
text: template.replace("{{ union }}", unions || " | never"),
|
|
1480
|
-
tsReference: true
|
|
1481
|
-
};
|
|
1482
|
-
}
|
|
1483
|
-
async function getI18nDeclarationEntry() {
|
|
1484
|
-
const defaultLocale = wxt.config.manifest.default_locale;
|
|
1485
|
-
const template = `// Generated by wxt
|
|
1486
|
-
import "wxt/browser";
|
|
1487
|
-
|
|
1488
|
-
declare module "wxt/browser" {
|
|
1489
|
-
/**
|
|
1490
|
-
* See https://developer.chrome.com/docs/extensions/reference/i18n/#method-getMessage
|
|
1491
|
-
*/
|
|
1492
|
-
interface GetMessageOptions {
|
|
1493
|
-
/**
|
|
1494
|
-
* See https://developer.chrome.com/docs/extensions/reference/i18n/#method-getMessage
|
|
1495
|
-
*/
|
|
1496
|
-
escapeLt?: boolean
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
export interface WxtI18n extends I18n.Static {
|
|
1500
|
-
{{ overrides }}
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
`;
|
|
1504
|
-
const defaultLocalePath = path4.resolve(
|
|
1505
|
-
wxt.config.publicDir,
|
|
1506
|
-
"_locales",
|
|
1507
|
-
defaultLocale ?? "",
|
|
1508
|
-
"messages.json"
|
|
1509
|
-
);
|
|
1510
|
-
let messages;
|
|
1511
|
-
if (await fs6.exists(defaultLocalePath)) {
|
|
1512
|
-
const content = JSON.parse(await fs6.readFile(defaultLocalePath, "utf-8"));
|
|
1513
|
-
messages = parseI18nMessages(content);
|
|
1514
|
-
} else {
|
|
1515
|
-
messages = parseI18nMessages({});
|
|
1516
|
-
}
|
|
1517
|
-
const overrides = messages.map((message) => {
|
|
1518
|
-
return ` /**
|
|
1519
|
-
* ${message.description || "No message description."}
|
|
1520
|
-
*
|
|
1521
|
-
* "${message.message}"
|
|
1522
|
-
*/
|
|
1523
|
-
getMessage(
|
|
1524
|
-
messageName: "${message.name}",
|
|
1525
|
-
substitutions?: string | string[],
|
|
1526
|
-
options?: GetMessageOptions,
|
|
1527
|
-
): string;`;
|
|
1528
|
-
});
|
|
1529
|
-
return {
|
|
1530
|
-
path: "types/i18n.d.ts",
|
|
1531
|
-
text: template.replace("{{ overrides }}", overrides.join("\n")),
|
|
1532
|
-
tsReference: true
|
|
1533
|
-
};
|
|
1534
|
-
}
|
|
1535
|
-
async function getGlobalsDeclarationEntry() {
|
|
1536
|
-
const globals2 = [...getGlobals(wxt.config), ...getEntrypointGlobals("")];
|
|
1537
|
-
return {
|
|
1538
|
-
path: "types/globals.d.ts",
|
|
1539
|
-
text: [
|
|
1540
|
-
"// Generated by wxt",
|
|
1541
|
-
"export {}",
|
|
1542
|
-
"interface ImportMetaEnv {",
|
|
1543
|
-
...globals2.map((global) => ` readonly ${global.name}: ${global.type};`),
|
|
1544
|
-
"}",
|
|
1545
|
-
"interface ImportMeta {",
|
|
1546
|
-
" readonly env: ImportMetaEnv",
|
|
1547
|
-
"}",
|
|
1548
|
-
""
|
|
1549
|
-
].join("\n"),
|
|
1550
|
-
tsReference: true
|
|
1551
|
-
};
|
|
1552
|
-
}
|
|
1553
|
-
function getMainDeclarationEntry(references) {
|
|
1554
|
-
const lines = ["// Generated by wxt"];
|
|
1555
|
-
references.forEach((ref) => {
|
|
1556
|
-
if ("module" in ref) {
|
|
1557
|
-
return lines.push(`/// <reference types="${ref.module}" />`);
|
|
1558
|
-
} else if (ref.tsReference) {
|
|
1559
|
-
const absolutePath = resolve9(wxt.config.wxtDir, ref.path);
|
|
1560
|
-
const relativePath = relative4(wxt.config.wxtDir, absolutePath);
|
|
1561
|
-
lines.push(`/// <reference types="./${normalizePath(relativePath)}" />`);
|
|
1562
|
-
}
|
|
1563
|
-
});
|
|
1564
|
-
return {
|
|
1565
|
-
path: "wxt.d.ts",
|
|
1566
|
-
text: lines.join("\n") + "\n"
|
|
1567
|
-
};
|
|
1568
|
-
}
|
|
1569
|
-
async function getTsConfigEntry() {
|
|
1570
|
-
const dir = wxt.config.wxtDir;
|
|
1571
|
-
const getTsconfigPath = (path8) => normalizePath(relative4(dir, path8));
|
|
1572
|
-
const paths = Object.entries(wxt.config.alias).flatMap(([alias, absolutePath]) => {
|
|
1573
|
-
const aliasPath = getTsconfigPath(absolutePath);
|
|
1574
|
-
return [
|
|
1575
|
-
` "${alias}": ["${aliasPath}"]`,
|
|
1576
|
-
` "${alias}/*": ["${aliasPath}/*"]`
|
|
1577
|
-
];
|
|
1578
|
-
}).join(",\n");
|
|
1579
|
-
const text = `{
|
|
1580
|
-
"compilerOptions": {
|
|
1581
|
-
"target": "ESNext",
|
|
1582
|
-
"module": "ESNext",
|
|
1583
|
-
"moduleResolution": "Bundler",
|
|
1584
|
-
"noEmit": true,
|
|
1585
|
-
"esModuleInterop": true,
|
|
1586
|
-
"forceConsistentCasingInFileNames": true,
|
|
1587
|
-
"resolveJsonModule": true,
|
|
1588
|
-
"strict": true,
|
|
1589
|
-
"skipLibCheck": true,
|
|
1590
|
-
"paths": {
|
|
1591
|
-
${paths}
|
|
1592
|
-
}
|
|
1593
|
-
},
|
|
1594
|
-
"include": [
|
|
1595
|
-
"${getTsconfigPath(wxt.config.root)}/**/*",
|
|
1596
|
-
"./wxt.d.ts"
|
|
1597
|
-
],
|
|
1598
|
-
"exclude": ["${getTsconfigPath(wxt.config.outBaseDir)}"]
|
|
1599
|
-
}`;
|
|
1600
|
-
return {
|
|
1601
|
-
path: "tsconfig.json",
|
|
1602
|
-
text
|
|
1603
|
-
};
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
// src/core/utils/building/resolve-config.ts
|
|
1607
|
-
import { loadConfig } from "c12";
|
|
1608
|
-
import path5 from "node:path";
|
|
1609
|
-
|
|
1610
|
-
// src/core/utils/cache.ts
|
|
1611
|
-
import fs7, { ensureDir as ensureDir2 } from "fs-extra";
|
|
1612
|
-
import { dirname as dirname5, resolve as resolve10 } from "path";
|
|
1613
|
-
function createFsCache(wxtDir) {
|
|
1614
|
-
const getPath = (key) => resolve10(wxtDir, "cache", encodeURIComponent(key));
|
|
1615
|
-
return {
|
|
1616
|
-
async set(key, value) {
|
|
1617
|
-
const path8 = getPath(key);
|
|
1618
|
-
await ensureDir2(dirname5(path8));
|
|
1619
|
-
await writeFileIfDifferent(path8, value);
|
|
1620
|
-
},
|
|
1621
|
-
async get(key) {
|
|
1622
|
-
const path8 = getPath(key);
|
|
1623
|
-
try {
|
|
1624
|
-
return await fs7.readFile(path8, "utf-8");
|
|
1625
|
-
} catch {
|
|
1626
|
-
return void 0;
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
};
|
|
1630
|
-
}
|
|
1631
|
-
|
|
1632
|
-
// src/core/utils/building/resolve-config.ts
|
|
1633
|
-
import defu from "defu";
|
|
1634
|
-
import fs8 from "fs-extra";
|
|
1635
|
-
import glob3 from "fast-glob";
|
|
1636
|
-
|
|
1637
|
-
// src/builtin-modules/index.ts
|
|
1638
|
-
var builtinModules = [unimport_default];
|
|
1639
|
-
|
|
1640
|
-
// src/core/utils/eslint.ts
|
|
1641
|
-
async function getEslintVersion() {
|
|
1642
|
-
try {
|
|
1643
|
-
const require2 = (await import("node:module")).default.createRequire(
|
|
1644
|
-
import.meta.url
|
|
1645
|
-
);
|
|
1646
|
-
const { ESLint } = require2("eslint");
|
|
1647
|
-
return ESLint.version?.split(".") ?? [];
|
|
1648
|
-
} catch (error) {
|
|
1649
|
-
return [];
|
|
1650
|
-
}
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
// src/core/utils/building/resolve-config.ts
|
|
1654
|
-
async function resolveConfig(inlineConfig, command) {
|
|
1655
|
-
let userConfig = {};
|
|
1656
|
-
let userConfigMetadata;
|
|
1657
|
-
if (inlineConfig.configFile !== false) {
|
|
1658
|
-
const { config: loadedConfig, ...metadata } = await loadConfig({
|
|
1659
|
-
configFile: inlineConfig.configFile,
|
|
1660
|
-
name: "wxt",
|
|
1661
|
-
cwd: inlineConfig.root ?? process.cwd(),
|
|
1662
|
-
rcFile: false,
|
|
1663
|
-
jitiOptions: {
|
|
1664
|
-
esmResolve: true
|
|
1665
|
-
}
|
|
1666
|
-
});
|
|
1667
|
-
userConfig = loadedConfig ?? {};
|
|
1668
|
-
userConfigMetadata = metadata;
|
|
1669
|
-
}
|
|
1670
|
-
const mergedConfig = await mergeInlineConfig(inlineConfig, userConfig);
|
|
1671
|
-
const debug = mergedConfig.debug ?? false;
|
|
1672
|
-
const logger = mergedConfig.logger ?? consola;
|
|
1673
|
-
if (debug) logger.level = LogLevels.debug;
|
|
1674
|
-
const browser = mergedConfig.browser ?? "chrome";
|
|
1675
|
-
const manifestVersion = mergedConfig.manifestVersion ?? (browser === "firefox" || browser === "safari" ? 2 : 3);
|
|
1676
|
-
const mode = mergedConfig.mode ?? COMMAND_MODES[command];
|
|
1677
|
-
const env = { browser, command, manifestVersion, mode };
|
|
1678
|
-
const root = path5.resolve(
|
|
1679
|
-
inlineConfig.root ?? userConfig.root ?? process.cwd()
|
|
1680
|
-
);
|
|
1681
|
-
const wxtDir = path5.resolve(root, ".wxt");
|
|
1682
|
-
const wxtModuleDir = await resolveWxtModuleDir();
|
|
1683
|
-
const srcDir = path5.resolve(root, mergedConfig.srcDir ?? root);
|
|
1684
|
-
const entrypointsDir = path5.resolve(
|
|
1685
|
-
srcDir,
|
|
1686
|
-
mergedConfig.entrypointsDir ?? "entrypoints"
|
|
1687
|
-
);
|
|
1688
|
-
const modulesDir = path5.resolve(srcDir, mergedConfig.modulesDir ?? "modules");
|
|
1689
|
-
if (await isDirMissing(entrypointsDir)) {
|
|
1690
|
-
logMissingDir(logger, "Entrypoints", entrypointsDir);
|
|
1691
|
-
}
|
|
1692
|
-
const filterEntrypoints = !!mergedConfig.filterEntrypoints?.length ? new Set(mergedConfig.filterEntrypoints) : void 0;
|
|
1693
|
-
const publicDir = path5.resolve(srcDir, mergedConfig.publicDir ?? "public");
|
|
1694
|
-
if (await isDirMissing(publicDir)) {
|
|
1695
|
-
logMissingDir(logger, "Public", publicDir);
|
|
1696
|
-
}
|
|
1697
|
-
const typesDir = path5.resolve(wxtDir, "types");
|
|
1698
|
-
const outBaseDir = path5.resolve(root, mergedConfig.outDir ?? ".output");
|
|
1699
|
-
const outDir = path5.resolve(outBaseDir, `${browser}-mv${manifestVersion}`);
|
|
1700
|
-
const reloadCommand = mergedConfig.dev?.reloadCommand ?? "Alt+R";
|
|
1701
|
-
const runnerConfig = await loadConfig({
|
|
1702
|
-
name: "web-ext",
|
|
1703
|
-
cwd: root,
|
|
1704
|
-
globalRc: true,
|
|
1705
|
-
rcFile: ".webextrc",
|
|
1706
|
-
overrides: inlineConfig.runner,
|
|
1707
|
-
defaults: userConfig.runner
|
|
1708
|
-
});
|
|
1709
|
-
const alias = Object.fromEntries(
|
|
1710
|
-
Object.entries({
|
|
1711
|
-
...mergedConfig.alias,
|
|
1712
|
-
"@": srcDir,
|
|
1713
|
-
"~": srcDir,
|
|
1714
|
-
"@@": root,
|
|
1715
|
-
"~~": root
|
|
1716
|
-
}).map(([key, value]) => [key, path5.resolve(root, value)])
|
|
1717
|
-
);
|
|
1718
|
-
let devServerConfig;
|
|
1719
|
-
if (command === "serve") {
|
|
1720
|
-
let port = mergedConfig.dev?.server?.port;
|
|
1721
|
-
if (port == null || !isFinite(port)) {
|
|
1722
|
-
const { default: getPort, portNumbers } = await import("get-port");
|
|
1723
|
-
port = await getPort({ port: portNumbers(3e3, 3010) });
|
|
1724
|
-
}
|
|
1725
|
-
devServerConfig = {
|
|
1726
|
-
port,
|
|
1727
|
-
hostname: mergedConfig.dev?.server?.hostname ?? "localhost"
|
|
1728
|
-
};
|
|
1729
|
-
}
|
|
1730
|
-
const userModules = await resolveWxtUserModules(
|
|
1731
|
-
modulesDir,
|
|
1732
|
-
mergedConfig.modules
|
|
1733
|
-
);
|
|
1734
|
-
const moduleOptions = userModules.reduce(
|
|
1735
|
-
(map, module) => {
|
|
1736
|
-
if (module.configKey) {
|
|
1737
|
-
map[module.configKey] = // @ts-expect-error
|
|
1738
|
-
mergedConfig[module.configKey];
|
|
1739
|
-
}
|
|
1740
|
-
return map;
|
|
1741
|
-
},
|
|
1742
|
-
{}
|
|
1743
|
-
);
|
|
1744
|
-
return {
|
|
1745
|
-
browser,
|
|
1746
|
-
command,
|
|
1747
|
-
debug,
|
|
1748
|
-
entrypointsDir,
|
|
1749
|
-
modulesDir,
|
|
1750
|
-
filterEntrypoints,
|
|
1751
|
-
env,
|
|
1752
|
-
fsCache: createFsCache(wxtDir),
|
|
1753
|
-
imports: await getUnimportOptions(wxtDir, srcDir, logger, mergedConfig),
|
|
1754
|
-
logger,
|
|
1755
|
-
manifest: await resolveManifestConfig(env, mergedConfig.manifest),
|
|
1756
|
-
manifestVersion,
|
|
1757
|
-
mode,
|
|
1758
|
-
outBaseDir,
|
|
1759
|
-
outDir,
|
|
1760
|
-
publicDir,
|
|
1761
|
-
wxtModuleDir,
|
|
1762
|
-
root,
|
|
1763
|
-
runnerConfig,
|
|
1764
|
-
srcDir,
|
|
1765
|
-
typesDir,
|
|
1766
|
-
wxtDir,
|
|
1767
|
-
zip: resolveZipConfig(root, outBaseDir, mergedConfig),
|
|
1768
|
-
transformManifest: mergedConfig.transformManifest,
|
|
1769
|
-
analysis: resolveAnalysisConfig(root, mergedConfig),
|
|
1770
|
-
userConfigMetadata: userConfigMetadata ?? {},
|
|
1771
|
-
alias,
|
|
1772
|
-
experimental: defu(mergedConfig.experimental, {
|
|
1773
|
-
includeBrowserPolyfill: true,
|
|
1774
|
-
entrypointImporter: "jiti"
|
|
1775
|
-
}),
|
|
1776
|
-
dev: {
|
|
1777
|
-
server: devServerConfig,
|
|
1778
|
-
reloadCommand
|
|
1779
|
-
},
|
|
1780
|
-
hooks: mergedConfig.hooks ?? {},
|
|
1781
|
-
vite: mergedConfig.vite ?? (() => ({})),
|
|
1782
|
-
builtinModules,
|
|
1783
|
-
userModules,
|
|
1784
|
-
plugins: [],
|
|
1785
|
-
...moduleOptions
|
|
1786
|
-
};
|
|
1787
|
-
}
|
|
1788
|
-
async function resolveManifestConfig(env, manifest) {
|
|
1789
|
-
return await (typeof manifest === "function" ? manifest(env) : manifest ?? {});
|
|
1790
|
-
}
|
|
1791
|
-
async function mergeInlineConfig(inlineConfig, userConfig) {
|
|
1792
|
-
const imports = inlineConfig.imports === false || userConfig.imports === false ? false : userConfig.imports == null && inlineConfig.imports == null ? void 0 : defu(inlineConfig.imports ?? {}, userConfig.imports ?? {});
|
|
1793
|
-
const manifest = async (env) => {
|
|
1794
|
-
const user = await resolveManifestConfig(env, userConfig.manifest);
|
|
1795
|
-
const inline = await resolveManifestConfig(env, inlineConfig.manifest);
|
|
1796
|
-
return defu(inline, user);
|
|
1797
|
-
};
|
|
1798
|
-
const transformManifest = (manifest2) => {
|
|
1799
|
-
userConfig.transformManifest?.(manifest2);
|
|
1800
|
-
inlineConfig.transformManifest?.(manifest2);
|
|
1801
|
-
};
|
|
1802
|
-
const merged = defu(inlineConfig, userConfig);
|
|
1803
|
-
const builderConfig = await mergeBuilderConfig(
|
|
1804
|
-
merged.logger ?? consola,
|
|
1805
|
-
inlineConfig,
|
|
1806
|
-
userConfig
|
|
1807
|
-
);
|
|
1808
|
-
return {
|
|
1809
|
-
...merged,
|
|
1810
|
-
// Custom merge values
|
|
1811
|
-
transformManifest,
|
|
1812
|
-
imports,
|
|
1813
|
-
manifest,
|
|
1814
|
-
...builderConfig
|
|
1815
|
-
};
|
|
1816
|
-
}
|
|
1817
|
-
function resolveZipConfig(root, outBaseDir, mergedConfig) {
|
|
1818
|
-
const downloadedPackagesDir = path5.resolve(root, ".wxt/local_modules");
|
|
1819
|
-
return {
|
|
1820
|
-
name: void 0,
|
|
1821
|
-
sourcesTemplate: "{{name}}-{{version}}-sources.zip",
|
|
1822
|
-
artifactTemplate: "{{name}}-{{version}}-{{browser}}.zip",
|
|
1823
|
-
sourcesRoot: root,
|
|
1824
|
-
includeSources: [],
|
|
1825
|
-
compressionLevel: 9,
|
|
1826
|
-
...mergedConfig.zip,
|
|
1827
|
-
excludeSources: [
|
|
1828
|
-
"**/node_modules",
|
|
1829
|
-
// WXT files
|
|
1830
|
-
"**/web-ext.config.ts",
|
|
1831
|
-
// Hidden files
|
|
1832
|
-
"**/.*",
|
|
1833
|
-
// Tests
|
|
1834
|
-
"**/__tests__/**",
|
|
1835
|
-
"**/*.+(test|spec).?(c|m)+(j|t)s?(x)",
|
|
1836
|
-
// Output directory
|
|
1837
|
-
`${path5.relative(root, outBaseDir)}/**`,
|
|
1838
|
-
// From user
|
|
1839
|
-
...mergedConfig.zip?.excludeSources ?? []
|
|
1840
|
-
],
|
|
1841
|
-
downloadPackages: mergedConfig.zip?.downloadPackages ?? [],
|
|
1842
|
-
downloadedPackagesDir
|
|
1843
|
-
};
|
|
1844
|
-
}
|
|
1845
|
-
function resolveAnalysisConfig(root, mergedConfig) {
|
|
1846
|
-
const analysisOutputFile = path5.resolve(
|
|
1847
|
-
root,
|
|
1848
|
-
mergedConfig.analysis?.outputFile ?? "stats.html"
|
|
1849
|
-
);
|
|
1850
|
-
const analysisOutputDir = path5.dirname(analysisOutputFile);
|
|
1851
|
-
const analysisOutputName = path5.parse(analysisOutputFile).name;
|
|
1852
|
-
return {
|
|
1853
|
-
enabled: mergedConfig.analysis?.enabled ?? false,
|
|
1854
|
-
open: mergedConfig.analysis?.open ?? false,
|
|
1855
|
-
template: mergedConfig.analysis?.template ?? "treemap",
|
|
1856
|
-
outputFile: analysisOutputFile,
|
|
1857
|
-
outputDir: analysisOutputDir,
|
|
1858
|
-
outputName: analysisOutputName,
|
|
1859
|
-
keepArtifacts: mergedConfig.analysis?.keepArtifacts ?? false
|
|
1860
|
-
};
|
|
1861
|
-
}
|
|
1862
|
-
async function getUnimportOptions(wxtDir, srcDir, logger, config) {
|
|
1863
|
-
if (config.imports === false) return false;
|
|
1864
|
-
const defaultOptions = {
|
|
1865
|
-
debugLog: logger.debug,
|
|
1866
|
-
imports: [
|
|
1867
|
-
{ name: "defineConfig", from: "wxt" },
|
|
1868
|
-
{ name: "fakeBrowser", from: "wxt/testing" }
|
|
1869
|
-
],
|
|
1870
|
-
presets: [
|
|
1871
|
-
{ package: "wxt/client" },
|
|
1872
|
-
{ package: "wxt/browser" },
|
|
1873
|
-
{ package: "wxt/sandbox" },
|
|
1874
|
-
{ package: "wxt/storage" }
|
|
1875
|
-
],
|
|
1876
|
-
warn: logger.warn,
|
|
1877
|
-
dirs: ["components", "composables", "hooks", "utils"],
|
|
1878
|
-
dirsScanOptions: {
|
|
1879
|
-
cwd: srcDir
|
|
1880
|
-
},
|
|
1881
|
-
eslintrc: await getUnimportEslintOptions(wxtDir, config.imports?.eslintrc)
|
|
1882
|
-
};
|
|
1883
|
-
return defu(
|
|
1884
|
-
config.imports ?? {},
|
|
1885
|
-
defaultOptions
|
|
1886
|
-
);
|
|
1887
|
-
}
|
|
1888
|
-
async function getUnimportEslintOptions(wxtDir, options) {
|
|
1889
|
-
const rawEslintEnabled = options?.enabled ?? "auto";
|
|
1890
|
-
let eslintEnabled;
|
|
1891
|
-
switch (rawEslintEnabled) {
|
|
1892
|
-
case "auto":
|
|
1893
|
-
const version2 = await getEslintVersion();
|
|
1894
|
-
let major = parseInt(version2[0]);
|
|
1895
|
-
if (major <= 8) eslintEnabled = 8;
|
|
1896
|
-
else if (major >= 9) eslintEnabled = 9;
|
|
1897
|
-
else eslintEnabled = 8;
|
|
1898
|
-
break;
|
|
1899
|
-
case true:
|
|
1900
|
-
eslintEnabled = 8;
|
|
1901
|
-
break;
|
|
1902
|
-
default:
|
|
1903
|
-
eslintEnabled = rawEslintEnabled;
|
|
1904
|
-
}
|
|
1905
|
-
return {
|
|
1906
|
-
enabled: eslintEnabled,
|
|
1907
|
-
filePath: path5.resolve(
|
|
1908
|
-
wxtDir,
|
|
1909
|
-
eslintEnabled === 9 ? "eslint-auto-imports.mjs" : "eslintrc-auto-import.json"
|
|
1910
|
-
),
|
|
1911
|
-
globalsPropValue: true
|
|
1912
|
-
};
|
|
1913
|
-
}
|
|
1914
|
-
async function resolveWxtModuleDir() {
|
|
1915
|
-
const requireResolve = __require?.resolve ?? (await import("node:module")).default.createRequire(import.meta.url).resolve;
|
|
1916
|
-
return path5.resolve(requireResolve("wxt"), "../..");
|
|
1917
|
-
}
|
|
1918
|
-
async function isDirMissing(dir) {
|
|
1919
|
-
return !await fs8.exists(dir);
|
|
1920
|
-
}
|
|
1921
|
-
function logMissingDir(logger, name, expected) {
|
|
1922
|
-
logger.warn(
|
|
1923
|
-
`${name} directory not found: ./${normalizePath(
|
|
1924
|
-
path5.relative(process.cwd(), expected)
|
|
1925
|
-
)}`
|
|
1926
|
-
);
|
|
1927
|
-
}
|
|
1928
|
-
var COMMAND_MODES = {
|
|
1929
|
-
build: "production",
|
|
1930
|
-
serve: "development"
|
|
1931
|
-
};
|
|
1932
|
-
async function mergeBuilderConfig(logger, inlineConfig, userConfig) {
|
|
1933
|
-
const vite = await import("vite").catch((err) => {
|
|
1934
|
-
logger.debug("Failed to import vite:", err);
|
|
1935
|
-
});
|
|
1936
|
-
if (vite) {
|
|
1937
|
-
return {
|
|
1938
|
-
vite: async (env) => {
|
|
1939
|
-
const resolvedInlineConfig = await inlineConfig.vite?.(env) ?? {};
|
|
1940
|
-
const resolvedUserConfig = await userConfig.vite?.(env) ?? {};
|
|
1941
|
-
return vite.mergeConfig(resolvedUserConfig, resolvedInlineConfig);
|
|
1942
|
-
}
|
|
1943
|
-
};
|
|
1944
|
-
}
|
|
1945
|
-
throw Error("Builder not found. Make sure vite is installed.");
|
|
1946
|
-
}
|
|
1947
|
-
async function resolveWxtUserModules(modulesDir, modules = []) {
|
|
1948
|
-
const npmModules = await Promise.all(
|
|
1949
|
-
modules.map(async (moduleId) => {
|
|
1950
|
-
const mod = await import(
|
|
1951
|
-
/* @vite-ignore */
|
|
1952
|
-
moduleId
|
|
1953
|
-
);
|
|
1954
|
-
if (mod.default == null) {
|
|
1955
|
-
throw Error("Module missing default export: " + moduleId);
|
|
1956
|
-
}
|
|
1957
|
-
return {
|
|
1958
|
-
...mod.default,
|
|
1959
|
-
type: "node_module",
|
|
1960
|
-
id: moduleId
|
|
1961
|
-
};
|
|
1962
|
-
})
|
|
1963
|
-
);
|
|
1964
|
-
const localModulePaths = await glob3(["*.[tj]s", "*/index.[tj]s"], {
|
|
1965
|
-
cwd: modulesDir,
|
|
1966
|
-
onlyFiles: true
|
|
1967
|
-
}).catch(() => []);
|
|
1968
|
-
const localModules = await Promise.all(
|
|
1969
|
-
localModulePaths.map(async (file) => {
|
|
1970
|
-
const absolutePath = normalizePath(path5.resolve(modulesDir, file));
|
|
1971
|
-
const { config } = await loadConfig({
|
|
1972
|
-
configFile: absolutePath,
|
|
1973
|
-
globalRc: false,
|
|
1974
|
-
rcFile: false,
|
|
1975
|
-
packageJson: false,
|
|
1976
|
-
envName: false,
|
|
1977
|
-
dotenv: false
|
|
1978
|
-
});
|
|
1979
|
-
if (config == null)
|
|
1980
|
-
throw Error(
|
|
1981
|
-
`No config found for ${file}. Did you forget to add a default export?`
|
|
1982
|
-
);
|
|
1983
|
-
config.name ??= file;
|
|
1984
|
-
return {
|
|
1985
|
-
...config,
|
|
1986
|
-
type: "local",
|
|
1987
|
-
id: absolutePath
|
|
1988
|
-
};
|
|
1989
|
-
})
|
|
1990
|
-
);
|
|
1991
|
-
return [...npmModules, ...localModules];
|
|
1992
|
-
}
|
|
1993
|
-
|
|
1994
|
-
// src/core/utils/building/group-entrypoints.ts
|
|
1995
|
-
function groupEntrypoints(entrypoints) {
|
|
1996
|
-
const groupIndexMap = {};
|
|
1997
|
-
const groups = [];
|
|
1998
|
-
for (const entry of entrypoints) {
|
|
1999
|
-
let group = ENTRY_TYPE_TO_GROUP_MAP[entry.type];
|
|
2000
|
-
if (entry.type === "background" && entry.options.type === "module") {
|
|
2001
|
-
group = "esm";
|
|
2002
|
-
}
|
|
2003
|
-
if (group === "individual") {
|
|
2004
|
-
groups.push(entry);
|
|
2005
|
-
} else {
|
|
2006
|
-
let groupIndex = groupIndexMap[group];
|
|
2007
|
-
if (groupIndex == null) {
|
|
2008
|
-
groupIndex = groups.push([]) - 1;
|
|
2009
|
-
groupIndexMap[group] = groupIndex;
|
|
2010
|
-
}
|
|
2011
|
-
groups[groupIndex].push(entry);
|
|
2012
|
-
}
|
|
2013
|
-
}
|
|
2014
|
-
return groups;
|
|
2015
|
-
}
|
|
2016
|
-
var ENTRY_TYPE_TO_GROUP_MAP = {
|
|
2017
|
-
sandbox: "sandboxed-esm",
|
|
2018
|
-
popup: "esm",
|
|
2019
|
-
newtab: "esm",
|
|
2020
|
-
history: "esm",
|
|
2021
|
-
options: "esm",
|
|
2022
|
-
devtools: "esm",
|
|
2023
|
-
bookmarks: "esm",
|
|
2024
|
-
sidepanel: "esm",
|
|
2025
|
-
"unlisted-page": "esm",
|
|
2026
|
-
background: "individual",
|
|
2027
|
-
"content-script": "individual",
|
|
2028
|
-
"unlisted-script": "individual",
|
|
2029
|
-
"unlisted-style": "individual",
|
|
2030
|
-
"content-script-style": "individual"
|
|
2031
|
-
};
|
|
2032
|
-
|
|
2033
|
-
// src/core/utils/building/import-entrypoint.ts
|
|
2034
|
-
import createJITI from "jiti";
|
|
2035
|
-
import { createUnimport as createUnimport2 } from "unimport";
|
|
2036
|
-
import fs9 from "fs-extra";
|
|
2037
|
-
import { relative as relative5, resolve as resolve11 } from "node:path";
|
|
2038
|
-
import { transformSync } from "esbuild";
|
|
2039
|
-
import { fileURLToPath } from "node:url";
|
|
2040
|
-
async function importEntrypointFile(path8) {
|
|
2041
|
-
wxt.logger.debug("Loading file metadata:", path8);
|
|
2042
|
-
const normalPath = normalizePath(path8);
|
|
2043
|
-
const unimport = createUnimport2({
|
|
2044
|
-
...wxt.config.imports,
|
|
2045
|
-
// Only allow specific imports, not all from the project
|
|
2046
|
-
dirs: []
|
|
2047
|
-
});
|
|
2048
|
-
await unimport.init();
|
|
2049
|
-
const text = await fs9.readFile(path8, "utf-8");
|
|
2050
|
-
const textNoImports = removeProjectImportStatements(text);
|
|
2051
|
-
const { code } = await unimport.injectImports(textNoImports);
|
|
2052
|
-
wxt.logger.debug(
|
|
2053
|
-
["Text:", text, "No imports:", textNoImports, "Code:", code].join("\n")
|
|
2054
|
-
);
|
|
2055
|
-
const jiti = createJITI(
|
|
2056
|
-
typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url),
|
|
2057
|
-
{
|
|
2058
|
-
cache: false,
|
|
2059
|
-
debug: wxt.config.debug,
|
|
2060
|
-
esmResolve: true,
|
|
2061
|
-
alias: {
|
|
2062
|
-
"webextension-polyfill": resolve11(
|
|
2063
|
-
wxt.config.wxtModuleDir,
|
|
2064
|
-
"dist/virtual/mock-browser.js"
|
|
2065
|
-
),
|
|
2066
|
-
// TODO: Resolve this virtual module to some file with
|
|
2067
|
-
// `export default {}` instead of this hack of using another file with
|
|
2068
|
-
// a default export.
|
|
2069
|
-
"virtual:app-config": resolve11(
|
|
2070
|
-
wxt.config.wxtModuleDir,
|
|
2071
|
-
"dist/virtual/mock-browser.js"
|
|
2072
|
-
)
|
|
2073
|
-
},
|
|
2074
|
-
// Continue using node to load TS files even if `bun run --bun` is detected. Jiti does not
|
|
2075
|
-
// respect the custom transform function when using it's native bun option.
|
|
2076
|
-
experimentalBun: false,
|
|
2077
|
-
// List of extensions to transform with esbuild
|
|
2078
|
-
extensions: [
|
|
2079
|
-
".ts",
|
|
2080
|
-
".cts",
|
|
2081
|
-
".mts",
|
|
2082
|
-
".tsx",
|
|
2083
|
-
".js",
|
|
2084
|
-
".cjs",
|
|
2085
|
-
".mjs",
|
|
2086
|
-
".jsx"
|
|
2087
|
-
],
|
|
2088
|
-
transform(opts) {
|
|
2089
|
-
const isEntrypoint = opts.filename === normalPath;
|
|
2090
|
-
return transformSync(
|
|
2091
|
-
// Use modified source code for entrypoints
|
|
2092
|
-
isEntrypoint ? code : opts.source,
|
|
2093
|
-
getEsbuildOptions(opts)
|
|
2094
|
-
);
|
|
2095
|
-
}
|
|
2096
|
-
}
|
|
2097
|
-
);
|
|
2098
|
-
try {
|
|
2099
|
-
const res = await jiti(path8);
|
|
2100
|
-
return res.default;
|
|
2101
|
-
} catch (err) {
|
|
2102
|
-
const filePath = relative5(wxt.config.root, path8);
|
|
2103
|
-
if (err instanceof ReferenceError) {
|
|
2104
|
-
const variableName = err.message.replace(" is not defined", "");
|
|
2105
|
-
throw Error(
|
|
2106
|
-
`${filePath}: Cannot use imported variable "${variableName}" outside the main function. See https://wxt.dev/guide/go-further/entrypoint-side-effects.html`,
|
|
2107
|
-
{ cause: err }
|
|
2108
|
-
);
|
|
2109
|
-
} else {
|
|
2110
|
-
wxt.logger.error(err);
|
|
2111
|
-
throw Error(`Failed to load entrypoint: ${filePath}`, { cause: err });
|
|
2112
|
-
}
|
|
2113
|
-
}
|
|
2114
|
-
}
|
|
2115
|
-
function getEsbuildOptions(opts) {
|
|
2116
|
-
const isJsx = opts.filename?.endsWith("x");
|
|
2117
|
-
return {
|
|
2118
|
-
format: "cjs",
|
|
2119
|
-
loader: isJsx ? "tsx" : "ts",
|
|
2120
|
-
...isJsx ? {
|
|
2121
|
-
// `h` and `Fragment` are undefined, but that's OK because JSX is never evaluated while
|
|
2122
|
-
// grabbing the entrypoint's options.
|
|
2123
|
-
jsxFactory: "h",
|
|
2124
|
-
jsxFragment: "Fragment"
|
|
2125
|
-
} : void 0
|
|
2126
|
-
};
|
|
2127
|
-
}
|
|
2128
|
-
|
|
2129
|
-
// src/core/utils/building/internal-build.ts
|
|
2130
|
-
import pc5 from "picocolors";
|
|
2131
|
-
import fs13 from "fs-extra";
|
|
2132
|
-
|
|
2133
|
-
// src/core/utils/log/printBuildSummary.ts
|
|
2134
|
-
import { resolve as resolve12 } from "path";
|
|
2135
|
-
|
|
2136
|
-
// src/core/utils/log/printFileList.ts
|
|
2137
|
-
import path6 from "node:path";
|
|
2138
|
-
import pc3 from "picocolors";
|
|
2139
|
-
import fs10 from "fs-extra";
|
|
2140
|
-
import { filesize } from "filesize";
|
|
2141
|
-
|
|
2142
|
-
// src/core/utils/log/printTable.ts
|
|
2143
|
-
function printTable(log, header, rows, gap = 2) {
|
|
2144
|
-
if (rows.length === 0) return;
|
|
2145
|
-
const columnWidths = rows.reduce(
|
|
2146
|
-
(widths, row) => {
|
|
2147
|
-
for (let i = 0; i < Math.max(widths.length, row.length); i++) {
|
|
2148
|
-
widths[i] = Math.max(row[i]?.length ?? 0, widths[i] ?? 0);
|
|
2149
|
-
}
|
|
2150
|
-
return widths;
|
|
2151
|
-
},
|
|
2152
|
-
rows[0].map((column) => column.length)
|
|
2153
|
-
);
|
|
2154
|
-
let str = "";
|
|
2155
|
-
rows.forEach((row, i) => {
|
|
2156
|
-
row.forEach((col, j) => {
|
|
2157
|
-
str += col.padEnd(columnWidths[j], " ");
|
|
2158
|
-
if (j !== row.length - 1) str += "".padEnd(gap, " ");
|
|
2159
|
-
});
|
|
2160
|
-
if (i !== rows.length - 1) str += "\n";
|
|
2161
|
-
});
|
|
2162
|
-
log(`${header}
|
|
2163
|
-
${str}`);
|
|
2164
|
-
}
|
|
2165
|
-
|
|
2166
|
-
// src/core/utils/log/printFileList.ts
|
|
2167
|
-
async function printFileList(log, header, baseDir, files) {
|
|
2168
|
-
let totalSize = 0;
|
|
2169
|
-
const fileRows = await Promise.all(
|
|
2170
|
-
files.map(async (file, i) => {
|
|
2171
|
-
const parts = [
|
|
2172
|
-
path6.relative(process.cwd(), baseDir) + path6.sep,
|
|
2173
|
-
path6.relative(baseDir, file)
|
|
2174
|
-
];
|
|
2175
|
-
const prefix = i === files.length - 1 ? " \u2514\u2500" : " \u251C\u2500";
|
|
2176
|
-
const color = getChunkColor(file);
|
|
2177
|
-
const stats = await fs10.lstat(file);
|
|
2178
|
-
totalSize += stats.size;
|
|
2179
|
-
const size = String(filesize(stats.size));
|
|
2180
|
-
return [
|
|
2181
|
-
`${pc3.gray(prefix)} ${pc3.dim(parts[0])}${color(parts[1])}`,
|
|
2182
|
-
pc3.dim(size)
|
|
2183
|
-
];
|
|
2184
|
-
})
|
|
2185
|
-
);
|
|
2186
|
-
fileRows.push([`${pc3.cyan("\u03A3 Total size:")} ${String(filesize(totalSize))}`]);
|
|
2187
|
-
printTable(log, header, fileRows);
|
|
2188
|
-
}
|
|
2189
|
-
var DEFAULT_COLOR = pc3.blue;
|
|
2190
|
-
var CHUNK_COLORS = {
|
|
2191
|
-
".js.map": pc3.gray,
|
|
2192
|
-
".cjs.map": pc3.gray,
|
|
2193
|
-
".mjs.map": pc3.gray,
|
|
2194
|
-
".html": pc3.green,
|
|
2195
|
-
".css": pc3.magenta,
|
|
2196
|
-
".js": pc3.cyan,
|
|
2197
|
-
".cjs": pc3.cyan,
|
|
2198
|
-
".mjs": pc3.cyan,
|
|
2199
|
-
".zip": pc3.yellow
|
|
2200
|
-
};
|
|
2201
|
-
function getChunkColor(filename) {
|
|
2202
|
-
return Object.entries(CHUNK_COLORS).find(([key]) => filename.endsWith(key))?.[1] ?? DEFAULT_COLOR;
|
|
2203
|
-
}
|
|
2204
|
-
|
|
2205
|
-
// src/core/utils/log/printBuildSummary.ts
|
|
2206
|
-
async function printBuildSummary(log, header, output) {
|
|
2207
|
-
const chunks = [
|
|
2208
|
-
...output.steps.flatMap((step) => step.chunks),
|
|
2209
|
-
...output.publicAssets
|
|
2210
|
-
].sort((l, r) => {
|
|
2211
|
-
const lWeight = getChunkSortWeight(l.fileName);
|
|
2212
|
-
const rWeight = getChunkSortWeight(r.fileName);
|
|
2213
|
-
const diff = lWeight - rWeight;
|
|
2214
|
-
if (diff !== 0) return diff;
|
|
2215
|
-
return l.fileName.localeCompare(r.fileName);
|
|
2216
|
-
});
|
|
2217
|
-
const files = chunks.map(
|
|
2218
|
-
(chunk) => resolve12(wxt.config.outDir, chunk.fileName)
|
|
2219
|
-
);
|
|
2220
|
-
await printFileList(log, header, wxt.config.outDir, files);
|
|
2221
|
-
}
|
|
2222
|
-
var DEFAULT_SORT_WEIGHT = 100;
|
|
2223
|
-
var CHUNK_SORT_WEIGHTS = {
|
|
2224
|
-
"manifest.json": 0,
|
|
2225
|
-
".html": 1,
|
|
2226
|
-
".js.map": 2,
|
|
2227
|
-
".js": 2,
|
|
2228
|
-
".css": 3
|
|
2229
|
-
};
|
|
2230
|
-
function getChunkSortWeight(filename) {
|
|
2231
|
-
return Object.entries(CHUNK_SORT_WEIGHTS).find(
|
|
2232
|
-
([key]) => filename.endsWith(key)
|
|
2233
|
-
)?.[1] ?? DEFAULT_SORT_WEIGHT;
|
|
2234
|
-
}
|
|
2235
|
-
|
|
2236
|
-
// src/core/utils/log/printHeader.ts
|
|
2237
|
-
import pc4 from "picocolors";
|
|
2238
|
-
|
|
2239
|
-
// src/core/utils/building/internal-build.ts
|
|
2240
|
-
import glob4 from "fast-glob";
|
|
2241
|
-
|
|
2242
|
-
// src/core/utils/manifest.ts
|
|
2243
|
-
import fs12 from "fs-extra";
|
|
2244
|
-
import { resolve as resolve14 } from "path";
|
|
2245
|
-
|
|
2246
|
-
// src/core/utils/content-security-policy.ts
|
|
2247
|
-
var ContentSecurityPolicy = class _ContentSecurityPolicy {
|
|
2248
|
-
static DIRECTIVE_ORDER = {
|
|
2249
|
-
"default-src": 0,
|
|
2250
|
-
"script-src": 1,
|
|
2251
|
-
"object-src": 2
|
|
2252
|
-
};
|
|
2253
|
-
data;
|
|
2254
|
-
constructor(csp) {
|
|
2255
|
-
if (csp) {
|
|
2256
|
-
const sections = csp.split(";").map((section) => section.trim());
|
|
2257
|
-
this.data = sections.reduce((data, section) => {
|
|
2258
|
-
const [key, ...values] = section.split(" ").map((item) => item.trim());
|
|
2259
|
-
if (key) data[key] = values;
|
|
2260
|
-
return data;
|
|
2261
|
-
}, {});
|
|
2262
|
-
} else {
|
|
2263
|
-
this.data = {};
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
/**
|
|
2267
|
-
* Ensure a set of values are listed under a directive.
|
|
2268
|
-
*/
|
|
2269
|
-
add(directive, ...newValues) {
|
|
2270
|
-
const values = this.data[directive] ?? [];
|
|
2271
|
-
newValues.forEach((newValue) => {
|
|
2272
|
-
if (!values.includes(newValue)) values.push(newValue);
|
|
2273
|
-
});
|
|
2274
|
-
this.data[directive] = values;
|
|
2275
|
-
return this;
|
|
2276
|
-
}
|
|
2277
|
-
toString() {
|
|
2278
|
-
const directives = Object.entries(this.data).sort(([l], [r]) => {
|
|
2279
|
-
const lo = _ContentSecurityPolicy.DIRECTIVE_ORDER[l] ?? 2;
|
|
2280
|
-
const ro = _ContentSecurityPolicy.DIRECTIVE_ORDER[r] ?? 2;
|
|
2281
|
-
return lo - ro;
|
|
2282
|
-
});
|
|
2283
|
-
return directives.map((entry) => entry.flat().join(" ")).join("; ") + ";";
|
|
2284
|
-
}
|
|
2285
|
-
};
|
|
2286
|
-
|
|
2287
|
-
// src/core/utils/content-scripts.ts
|
|
2288
|
-
function hashContentScriptOptions(options) {
|
|
2289
|
-
const simplifiedOptions = mapWxtOptionsToContentScript(
|
|
2290
|
-
options,
|
|
2291
|
-
void 0,
|
|
2292
|
-
void 0
|
|
2293
|
-
);
|
|
2294
|
-
Object.keys(simplifiedOptions).forEach((key) => {
|
|
2295
|
-
if (simplifiedOptions[key] == null) delete simplifiedOptions[key];
|
|
2296
|
-
});
|
|
2297
|
-
const withDefaults = {
|
|
2298
|
-
exclude_globs: [],
|
|
2299
|
-
exclude_matches: [],
|
|
2300
|
-
include_globs: [],
|
|
2301
|
-
match_about_blank: false,
|
|
2302
|
-
run_at: "document_idle",
|
|
2303
|
-
all_frames: false,
|
|
2304
|
-
// @ts-expect-error - not in type
|
|
2305
|
-
match_origin_as_fallback: false,
|
|
2306
|
-
world: "ISOLATED",
|
|
2307
|
-
...simplifiedOptions
|
|
2308
|
-
};
|
|
2309
|
-
return JSON.stringify(
|
|
2310
|
-
Object.entries(withDefaults).map(([key, value]) => {
|
|
2311
|
-
if (Array.isArray(value)) return [key, value.sort()];
|
|
2312
|
-
else return [key, value];
|
|
2313
|
-
}).sort((l, r) => l[0].localeCompare(r[0]))
|
|
2314
|
-
);
|
|
2315
|
-
}
|
|
2316
|
-
function mapWxtOptionsToContentScript(options, js, css) {
|
|
2317
|
-
return {
|
|
2318
|
-
matches: options.matches,
|
|
2319
|
-
all_frames: options.allFrames,
|
|
2320
|
-
match_about_blank: options.matchAboutBlank,
|
|
2321
|
-
exclude_globs: options.excludeGlobs,
|
|
2322
|
-
exclude_matches: options.excludeMatches,
|
|
2323
|
-
include_globs: options.includeGlobs,
|
|
2324
|
-
run_at: options.runAt,
|
|
2325
|
-
css,
|
|
2326
|
-
js,
|
|
2327
|
-
// @ts-expect-error: untyped chrome options
|
|
2328
|
-
match_origin_as_fallback: options.matchOriginAsFallback,
|
|
2329
|
-
world: options.world
|
|
2330
|
-
};
|
|
2331
|
-
}
|
|
2332
|
-
function mapWxtOptionsToRegisteredContentScript(options, js, css) {
|
|
2333
|
-
return {
|
|
2334
|
-
allFrames: options.allFrames,
|
|
2335
|
-
excludeMatches: options.excludeMatches,
|
|
2336
|
-
matches: options.matches,
|
|
2337
|
-
runAt: options.runAt,
|
|
2338
|
-
js,
|
|
2339
|
-
css,
|
|
2340
|
-
// @ts-expect-error: Chrome accepts this, not typed in webextension-polyfill (https://developer.chrome.com/docs/extensions/reference/scripting/#type-RegisteredContentScript)
|
|
2341
|
-
world: options.world
|
|
2342
|
-
};
|
|
2343
|
-
}
|
|
2344
|
-
function getContentScriptJs(config, entrypoint) {
|
|
2345
|
-
return [getEntrypointBundlePath(entrypoint, config.outDir, ".js")];
|
|
2346
|
-
}
|
|
2347
|
-
|
|
2348
|
-
// src/core/utils/package.ts
|
|
2349
|
-
import { resolve as resolve13 } from "node:path";
|
|
2350
|
-
import fs11 from "fs-extra";
|
|
2351
|
-
async function getPackageJson() {
|
|
2352
|
-
const file = resolve13(wxt.config.root, "package.json");
|
|
2353
|
-
try {
|
|
2354
|
-
return await fs11.readJson(file);
|
|
2355
|
-
} catch (err) {
|
|
2356
|
-
wxt.logger.debug(
|
|
2357
|
-
`Failed to read package.json at: ${file}. Returning undefined.`
|
|
2358
|
-
);
|
|
2359
|
-
return {};
|
|
2360
|
-
}
|
|
2361
|
-
}
|
|
2362
|
-
|
|
2363
|
-
// src/core/utils/manifest.ts
|
|
2364
|
-
import defu2 from "defu";
|
|
2365
|
-
async function writeManifest(manifest, output) {
|
|
2366
|
-
const str = wxt.config.mode === "production" ? JSON.stringify(manifest) : JSON.stringify(manifest, null, 2);
|
|
2367
|
-
await fs12.ensureDir(wxt.config.outDir);
|
|
2368
|
-
await writeFileIfDifferent(resolve14(wxt.config.outDir, "manifest.json"), str);
|
|
2369
|
-
output.publicAssets.unshift({
|
|
2370
|
-
type: "asset",
|
|
2371
|
-
fileName: "manifest.json"
|
|
2372
|
-
});
|
|
2373
|
-
}
|
|
2374
|
-
async function generateManifest(entrypoints, buildOutput) {
|
|
2375
|
-
const warnings = [];
|
|
2376
|
-
const pkg = await getPackageJson();
|
|
2377
|
-
let versionName = wxt.config.manifest.version_name ?? wxt.config.manifest.version ?? pkg?.version;
|
|
2378
|
-
if (versionName == null) {
|
|
2379
|
-
versionName = "0.0.0";
|
|
2380
|
-
wxt.logger.warn(
|
|
2381
|
-
'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'
|
|
2382
|
-
);
|
|
2383
|
-
}
|
|
2384
|
-
const version2 = wxt.config.manifest.version ?? simplifyVersion(versionName);
|
|
2385
|
-
const baseManifest = {
|
|
2386
|
-
manifest_version: wxt.config.manifestVersion,
|
|
2387
|
-
name: pkg?.name,
|
|
2388
|
-
description: pkg?.description,
|
|
2389
|
-
version: version2,
|
|
2390
|
-
short_name: pkg?.shortName,
|
|
2391
|
-
icons: discoverIcons(buildOutput)
|
|
2392
|
-
};
|
|
2393
|
-
const userManifest = wxt.config.manifest;
|
|
2394
|
-
let manifest = defu2(
|
|
2395
|
-
userManifest,
|
|
2396
|
-
baseManifest
|
|
2397
|
-
);
|
|
2398
|
-
if (wxt.config.command === "serve" && wxt.config.dev.reloadCommand) {
|
|
2399
|
-
if (manifest.commands && Object.keys(manifest.commands).length >= 4) {
|
|
2400
|
-
warnings.push([
|
|
2401
|
-
"Extension already has 4 registered commands, WXT's reload command is disabled"
|
|
2402
|
-
]);
|
|
2403
|
-
} else {
|
|
2404
|
-
manifest.commands ??= {};
|
|
2405
|
-
manifest.commands["wxt:reload-extension"] = {
|
|
2406
|
-
description: "Reload the extension during development",
|
|
2407
|
-
suggested_key: {
|
|
2408
|
-
default: wxt.config.dev.reloadCommand
|
|
2409
|
-
}
|
|
2410
|
-
};
|
|
2411
|
-
}
|
|
2412
|
-
}
|
|
2413
|
-
manifest.version = version2;
|
|
2414
|
-
manifest.version_name = // Firefox doesn't support version_name
|
|
2415
|
-
wxt.config.browser === "firefox" || versionName === version2 ? void 0 : versionName;
|
|
2416
|
-
addEntrypoints(manifest, entrypoints, buildOutput);
|
|
2417
|
-
if (wxt.config.command === "serve") addDevModeCsp(manifest);
|
|
2418
|
-
if (wxt.config.command === "serve") addDevModePermissions(manifest);
|
|
2419
|
-
wxt.config.transformManifest?.(manifest);
|
|
2420
|
-
await wxt.hooks.callHook("build:manifestGenerated", wxt, manifest);
|
|
2421
|
-
if (wxt.config.manifestVersion === 2) {
|
|
2422
|
-
convertWebAccessibleResourcesToMv2(manifest);
|
|
2423
|
-
convertActionToMv2(manifest);
|
|
2424
|
-
moveHostPermissionsToPermissions(manifest);
|
|
2425
|
-
}
|
|
2426
|
-
if (wxt.config.manifestVersion === 3) {
|
|
2427
|
-
validateMv3WebAccessbileResources(manifest);
|
|
2428
|
-
}
|
|
2429
|
-
stripKeys(manifest);
|
|
2430
|
-
if (manifest.name == null)
|
|
2431
|
-
throw Error(
|
|
2432
|
-
"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"
|
|
2433
|
-
);
|
|
2434
|
-
if (manifest.version == null) {
|
|
2435
|
-
throw Error(
|
|
2436
|
-
"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"
|
|
2437
|
-
);
|
|
2438
|
-
}
|
|
2439
|
-
return {
|
|
2440
|
-
manifest,
|
|
2441
|
-
warnings
|
|
2442
|
-
};
|
|
2443
|
-
}
|
|
2444
|
-
function simplifyVersion(versionName) {
|
|
2445
|
-
const version2 = /^((0|[1-9][0-9]{0,8})([.](0|[1-9][0-9]{0,8})){0,3}).*$/.exec(
|
|
2446
|
-
versionName
|
|
2447
|
-
)?.[1];
|
|
2448
|
-
if (version2 == null)
|
|
2449
|
-
throw Error(
|
|
2450
|
-
`Cannot simplify package.json version "${versionName}" to a valid extension version, "X.Y.Z"`
|
|
2451
|
-
);
|
|
2452
|
-
return version2;
|
|
2453
|
-
}
|
|
2454
|
-
function addEntrypoints(manifest, entrypoints, buildOutput) {
|
|
2455
|
-
const entriesByType = entrypoints.reduce((map, entrypoint) => {
|
|
2456
|
-
map[entrypoint.type] ??= [];
|
|
2457
|
-
map[entrypoint.type]?.push(entrypoint);
|
|
2458
|
-
return map;
|
|
2459
|
-
}, {});
|
|
2460
|
-
const background = entriesByType["background"]?.[0];
|
|
2461
|
-
const bookmarks = entriesByType["bookmarks"]?.[0];
|
|
2462
|
-
const contentScripts = entriesByType["content-script"];
|
|
2463
|
-
const devtools = entriesByType["devtools"]?.[0];
|
|
2464
|
-
const history = entriesByType["history"]?.[0];
|
|
2465
|
-
const newtab = entriesByType["newtab"]?.[0];
|
|
2466
|
-
const options = entriesByType["options"]?.[0];
|
|
2467
|
-
const popup = entriesByType["popup"]?.[0];
|
|
2468
|
-
const sandboxes = entriesByType["sandbox"];
|
|
2469
|
-
const sidepanels = entriesByType["sidepanel"];
|
|
2470
|
-
if (background) {
|
|
2471
|
-
const script = getEntrypointBundlePath(
|
|
2472
|
-
background,
|
|
2473
|
-
wxt.config.outDir,
|
|
2474
|
-
".js"
|
|
2475
|
-
);
|
|
2476
|
-
if (wxt.config.browser === "firefox" && wxt.config.manifestVersion === 3) {
|
|
2477
|
-
manifest.background = {
|
|
2478
|
-
type: background.options.type,
|
|
2479
|
-
scripts: [script]
|
|
2480
|
-
};
|
|
2481
|
-
} else if (wxt.config.manifestVersion === 3) {
|
|
2482
|
-
manifest.background = {
|
|
2483
|
-
type: background.options.type,
|
|
2484
|
-
service_worker: script
|
|
2485
|
-
};
|
|
2486
|
-
} else {
|
|
2487
|
-
manifest.background = {
|
|
2488
|
-
persistent: background.options.persistent,
|
|
2489
|
-
scripts: [script]
|
|
2490
|
-
};
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
|
-
if (bookmarks) {
|
|
2494
|
-
if (wxt.config.browser === "firefox") {
|
|
2495
|
-
wxt.logger.warn(
|
|
2496
|
-
"Bookmarks are not supported by Firefox. chrome_url_overrides.bookmarks was not added to the manifest"
|
|
2497
|
-
);
|
|
2498
|
-
} else {
|
|
2499
|
-
manifest.chrome_url_overrides ??= {};
|
|
2500
|
-
manifest.chrome_url_overrides.bookmarks = getEntrypointBundlePath(
|
|
2501
|
-
bookmarks,
|
|
2502
|
-
wxt.config.outDir,
|
|
2503
|
-
".html"
|
|
2504
|
-
);
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2507
|
-
if (history) {
|
|
2508
|
-
if (wxt.config.browser === "firefox") {
|
|
2509
|
-
wxt.logger.warn(
|
|
2510
|
-
"Bookmarks are not supported by Firefox. chrome_url_overrides.history was not added to the manifest"
|
|
2511
|
-
);
|
|
2512
|
-
} else {
|
|
2513
|
-
manifest.chrome_url_overrides ??= {};
|
|
2514
|
-
manifest.chrome_url_overrides.history = getEntrypointBundlePath(
|
|
2515
|
-
history,
|
|
2516
|
-
wxt.config.outDir,
|
|
2517
|
-
".html"
|
|
2518
|
-
);
|
|
2519
|
-
}
|
|
2520
|
-
}
|
|
2521
|
-
if (newtab) {
|
|
2522
|
-
manifest.chrome_url_overrides ??= {};
|
|
2523
|
-
manifest.chrome_url_overrides.newtab = getEntrypointBundlePath(
|
|
2524
|
-
newtab,
|
|
2525
|
-
wxt.config.outDir,
|
|
2526
|
-
".html"
|
|
2527
|
-
);
|
|
2528
|
-
}
|
|
2529
|
-
if (popup) {
|
|
2530
|
-
const default_popup = getEntrypointBundlePath(
|
|
2531
|
-
popup,
|
|
2532
|
-
wxt.config.outDir,
|
|
2533
|
-
".html"
|
|
2534
|
-
);
|
|
2535
|
-
const options2 = {};
|
|
2536
|
-
if (popup.options.defaultIcon)
|
|
2537
|
-
options2.default_icon = popup.options.defaultIcon;
|
|
2538
|
-
if (popup.options.defaultTitle)
|
|
2539
|
-
options2.default_title = popup.options.defaultTitle;
|
|
2540
|
-
if (popup.options.browserStyle)
|
|
2541
|
-
options2.browser_style = popup.options.browserStyle;
|
|
2542
|
-
if (manifest.manifest_version === 3) {
|
|
2543
|
-
manifest.action = {
|
|
2544
|
-
...manifest.action ?? {},
|
|
2545
|
-
...options2,
|
|
2546
|
-
default_popup
|
|
2547
|
-
};
|
|
2548
|
-
} else {
|
|
2549
|
-
const key = popup.options.mv2Key ?? "browser_action";
|
|
2550
|
-
manifest[key] = {
|
|
2551
|
-
...manifest[key] ?? {},
|
|
2552
|
-
...options2,
|
|
2553
|
-
default_popup
|
|
2554
|
-
};
|
|
2555
|
-
}
|
|
2556
|
-
}
|
|
2557
|
-
if (devtools) {
|
|
2558
|
-
manifest.devtools_page = getEntrypointBundlePath(
|
|
2559
|
-
devtools,
|
|
2560
|
-
wxt.config.outDir,
|
|
2561
|
-
".html"
|
|
2562
|
-
);
|
|
2563
|
-
}
|
|
2564
|
-
if (options) {
|
|
2565
|
-
const page = getEntrypointBundlePath(options, wxt.config.outDir, ".html");
|
|
2566
|
-
manifest.options_ui = {
|
|
2567
|
-
open_in_tab: options.options.openInTab,
|
|
2568
|
-
browser_style: wxt.config.browser === "firefox" ? options.options.browserStyle : void 0,
|
|
2569
|
-
chrome_style: wxt.config.browser !== "firefox" ? options.options.chromeStyle : void 0,
|
|
2570
|
-
page
|
|
2571
|
-
};
|
|
2572
|
-
}
|
|
2573
|
-
if (sandboxes?.length) {
|
|
2574
|
-
if (wxt.config.browser === "firefox") {
|
|
2575
|
-
wxt.logger.warn(
|
|
2576
|
-
"Sandboxed pages not supported by Firefox. sandbox.pages was not added to the manifest"
|
|
2577
|
-
);
|
|
2578
|
-
} else {
|
|
2579
|
-
manifest.sandbox = {
|
|
2580
|
-
pages: sandboxes.map(
|
|
2581
|
-
(entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".html")
|
|
2582
|
-
)
|
|
2583
|
-
};
|
|
2584
|
-
}
|
|
2585
|
-
}
|
|
2586
|
-
if (sidepanels?.length) {
|
|
2587
|
-
const defaultSidepanel = sidepanels.find((entry) => entry.name === "sidepanel") ?? sidepanels[0];
|
|
2588
|
-
const page = getEntrypointBundlePath(
|
|
2589
|
-
defaultSidepanel,
|
|
2590
|
-
wxt.config.outDir,
|
|
2591
|
-
".html"
|
|
2592
|
-
);
|
|
2593
|
-
if (wxt.config.browser === "firefox") {
|
|
2594
|
-
manifest.sidebar_action = {
|
|
2595
|
-
default_panel: page,
|
|
2596
|
-
browser_style: defaultSidepanel.options.browserStyle,
|
|
2597
|
-
default_icon: defaultSidepanel.options.defaultIcon,
|
|
2598
|
-
default_title: defaultSidepanel.options.defaultTitle,
|
|
2599
|
-
open_at_install: defaultSidepanel.options.openAtInstall
|
|
2600
|
-
};
|
|
2601
|
-
} else if (wxt.config.manifestVersion === 3) {
|
|
2602
|
-
manifest.side_panel = {
|
|
2603
|
-
default_path: page
|
|
2604
|
-
};
|
|
2605
|
-
addPermission(manifest, "sidePanel");
|
|
2606
|
-
} else {
|
|
2607
|
-
wxt.logger.warn(
|
|
2608
|
-
"Side panel not supported by Chromium using MV2. side_panel.default_path was not added to the manifest"
|
|
2609
|
-
);
|
|
2610
|
-
}
|
|
2611
|
-
}
|
|
2612
|
-
if (contentScripts?.length) {
|
|
2613
|
-
const cssMap = getContentScriptsCssMap(buildOutput, contentScripts);
|
|
2614
|
-
if (wxt.config.command === "serve" && wxt.config.manifestVersion === 3) {
|
|
2615
|
-
contentScripts.forEach((script) => {
|
|
2616
|
-
script.options.matches.forEach((matchPattern) => {
|
|
2617
|
-
addHostPermission(manifest, matchPattern);
|
|
2618
|
-
});
|
|
2619
|
-
});
|
|
2620
|
-
} else {
|
|
2621
|
-
const hashToEntrypointsMap = contentScripts.filter((cs) => cs.options.registration !== "runtime").reduce((map, script) => {
|
|
2622
|
-
const hash = hashContentScriptOptions(script.options);
|
|
2623
|
-
if (map.has(hash)) map.get(hash)?.push(script);
|
|
2624
|
-
else map.set(hash, [script]);
|
|
2625
|
-
return map;
|
|
2626
|
-
}, /* @__PURE__ */ new Map());
|
|
2627
|
-
const manifestContentScripts = Array.from(
|
|
2628
|
-
hashToEntrypointsMap.values()
|
|
2629
|
-
).map(
|
|
2630
|
-
(scripts) => mapWxtOptionsToContentScript(
|
|
2631
|
-
scripts[0].options,
|
|
2632
|
-
scripts.map(
|
|
2633
|
-
(entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".js")
|
|
2634
|
-
),
|
|
2635
|
-
getContentScriptCssFiles(scripts, cssMap)
|
|
2636
|
-
)
|
|
2637
|
-
);
|
|
2638
|
-
if (manifestContentScripts.length >= 0) {
|
|
2639
|
-
manifest.content_scripts ??= [];
|
|
2640
|
-
manifest.content_scripts.push(...manifestContentScripts);
|
|
2641
|
-
}
|
|
2642
|
-
const runtimeContentScripts = contentScripts.filter(
|
|
2643
|
-
(cs) => cs.options.registration === "runtime"
|
|
2644
|
-
);
|
|
2645
|
-
if (runtimeContentScripts.length > 0 && wxt.config.manifestVersion === 2) {
|
|
2646
|
-
throw Error(
|
|
2647
|
-
'Cannot use `registration: "runtime"` with MV2 content scripts, it is a MV3-only feature.'
|
|
2648
|
-
);
|
|
2649
|
-
}
|
|
2650
|
-
runtimeContentScripts.forEach((script) => {
|
|
2651
|
-
script.options.matches.forEach((matchPattern) => {
|
|
2652
|
-
addHostPermission(manifest, matchPattern);
|
|
2653
|
-
});
|
|
2654
|
-
});
|
|
2655
|
-
}
|
|
2656
|
-
const contentScriptCssResources = getContentScriptCssWebAccessibleResources(
|
|
2657
|
-
contentScripts,
|
|
2658
|
-
cssMap
|
|
2659
|
-
);
|
|
2660
|
-
if (contentScriptCssResources.length > 0) {
|
|
2661
|
-
manifest.web_accessible_resources ??= [];
|
|
2662
|
-
manifest.web_accessible_resources.push(...contentScriptCssResources);
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2665
|
-
}
|
|
2666
|
-
function discoverIcons(buildOutput) {
|
|
2667
|
-
const icons = [];
|
|
2668
|
-
const iconRegex = [
|
|
2669
|
-
/^icon-([0-9]+)\.png$/,
|
|
2670
|
-
// icon-16.png
|
|
2671
|
-
/^icon-([0-9]+)x[0-9]+\.png$/,
|
|
2672
|
-
// icon-16x16.png
|
|
2673
|
-
/^icon@([0-9]+)w\.png$/,
|
|
2674
|
-
// icon@16w.png
|
|
2675
|
-
/^icon@([0-9]+)h\.png$/,
|
|
2676
|
-
// icon@16h.png
|
|
2677
|
-
/^icon@([0-9]+)\.png$/,
|
|
2678
|
-
// icon@16.png
|
|
2679
|
-
/^icons?[\/\\]([0-9]+)\.png$/,
|
|
2680
|
-
// icon/16.png | icons/16.png
|
|
2681
|
-
/^icons?[\/\\]([0-9]+)x[0-9]+\.png$/
|
|
2682
|
-
// icon/16x16.png | icons/16x16.png
|
|
2683
|
-
];
|
|
2684
|
-
buildOutput.publicAssets.forEach((asset) => {
|
|
2685
|
-
let size;
|
|
2686
|
-
for (const regex of iconRegex) {
|
|
2687
|
-
const match = asset.fileName.match(regex);
|
|
2688
|
-
if (match?.[1] != null) {
|
|
2689
|
-
size = match[1];
|
|
2690
|
-
break;
|
|
2691
|
-
}
|
|
2692
|
-
}
|
|
2693
|
-
if (size == null) return;
|
|
2694
|
-
icons.push([size, normalizePath(asset.fileName)]);
|
|
2695
|
-
});
|
|
2696
|
-
return icons.length > 0 ? Object.fromEntries(icons) : void 0;
|
|
2697
|
-
}
|
|
2698
|
-
function addDevModeCsp(manifest) {
|
|
2699
|
-
const permission = `http://${wxt.server?.hostname ?? ""}/*`;
|
|
2700
|
-
const allowedCsp = wxt.server?.origin ?? "http://localhost:*";
|
|
2701
|
-
if (manifest.manifest_version === 3) {
|
|
2702
|
-
addHostPermission(manifest, permission);
|
|
2703
|
-
} else {
|
|
2704
|
-
addPermission(manifest, permission);
|
|
2705
|
-
}
|
|
2706
|
-
const extensionPagesCsp = new ContentSecurityPolicy(
|
|
2707
|
-
manifest.manifest_version === 3 ? (
|
|
2708
|
-
// @ts-expect-error: extension_pages is not typed
|
|
2709
|
-
manifest.content_security_policy?.extension_pages ?? "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';"
|
|
2710
|
-
) : manifest.content_security_policy ?? "script-src 'self'; object-src 'self';"
|
|
2711
|
-
// default CSP for MV2
|
|
2712
|
-
);
|
|
2713
|
-
const sandboxCsp = new ContentSecurityPolicy(
|
|
2714
|
-
// @ts-expect-error: sandbox is not typed
|
|
2715
|
-
manifest.content_security_policy?.sandbox ?? "sandbox allow-scripts allow-forms allow-popups allow-modals; script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self';"
|
|
2716
|
-
// default sandbox CSP for MV3
|
|
2717
|
-
);
|
|
2718
|
-
if (wxt.server) {
|
|
2719
|
-
extensionPagesCsp.add("script-src", allowedCsp);
|
|
2720
|
-
sandboxCsp.add("script-src", allowedCsp);
|
|
2721
|
-
}
|
|
2722
|
-
if (manifest.manifest_version === 3) {
|
|
2723
|
-
manifest.content_security_policy ??= {};
|
|
2724
|
-
manifest.content_security_policy.extension_pages = extensionPagesCsp.toString();
|
|
2725
|
-
manifest.content_security_policy.sandbox = sandboxCsp.toString();
|
|
2726
|
-
} else {
|
|
2727
|
-
manifest.content_security_policy = extensionPagesCsp.toString();
|
|
2728
|
-
}
|
|
2729
|
-
}
|
|
2730
|
-
function addDevModePermissions(manifest) {
|
|
2731
|
-
addPermission(manifest, "tabs");
|
|
2732
|
-
if (wxt.config.manifestVersion === 3) addPermission(manifest, "scripting");
|
|
2733
|
-
}
|
|
2734
|
-
function getContentScriptCssFiles(contentScripts, contentScriptCssMap) {
|
|
2735
|
-
const css = [];
|
|
2736
|
-
contentScripts.forEach((script) => {
|
|
2737
|
-
if (script.options.cssInjectionMode === "manual" || script.options.cssInjectionMode === "ui")
|
|
2738
|
-
return;
|
|
2739
|
-
const cssFile = contentScriptCssMap[script.name];
|
|
2740
|
-
if (cssFile == null) return;
|
|
2741
|
-
if (cssFile) css.push(cssFile);
|
|
2742
|
-
});
|
|
2743
|
-
if (css.length > 0) return css;
|
|
2744
|
-
return void 0;
|
|
2745
|
-
}
|
|
2746
|
-
function getContentScriptCssWebAccessibleResources(contentScripts, contentScriptCssMap) {
|
|
2747
|
-
const resources = [];
|
|
2748
|
-
contentScripts.forEach((script) => {
|
|
2749
|
-
if (script.options.cssInjectionMode !== "ui") return;
|
|
2750
|
-
const cssFile = contentScriptCssMap[script.name];
|
|
2751
|
-
if (cssFile == null) return;
|
|
2752
|
-
resources.push({
|
|
2753
|
-
resources: [cssFile],
|
|
2754
|
-
matches: script.options.matches.map(
|
|
2755
|
-
(matchPattern) => stripPathFromMatchPattern(matchPattern)
|
|
2756
|
-
)
|
|
2757
|
-
});
|
|
2758
|
-
});
|
|
2759
|
-
return resources;
|
|
2760
|
-
}
|
|
2761
|
-
function getContentScriptsCssMap(buildOutput, scripts) {
|
|
2762
|
-
const map = {};
|
|
2763
|
-
const allChunks = buildOutput.steps.flatMap((step) => step.chunks);
|
|
2764
|
-
scripts.forEach((script) => {
|
|
2765
|
-
const relatedCss = allChunks.find(
|
|
2766
|
-
(chunk) => chunk.fileName === `content-scripts/${script.name}.css`
|
|
2767
|
-
);
|
|
2768
|
-
if (relatedCss != null) map[script.name] = relatedCss.fileName;
|
|
2769
|
-
});
|
|
2770
|
-
return map;
|
|
2771
|
-
}
|
|
2772
|
-
function addPermission(manifest, permission) {
|
|
2773
|
-
manifest.permissions ??= [];
|
|
2774
|
-
if (manifest.permissions.includes(permission)) return;
|
|
2775
|
-
manifest.permissions.push(permission);
|
|
2776
|
-
}
|
|
2777
|
-
function addHostPermission(manifest, hostPermission) {
|
|
2778
|
-
manifest.host_permissions ??= [];
|
|
2779
|
-
if (manifest.host_permissions.includes(hostPermission)) return;
|
|
2780
|
-
manifest.host_permissions.push(hostPermission);
|
|
2781
|
-
}
|
|
2782
|
-
function stripPathFromMatchPattern(pattern) {
|
|
2783
|
-
const protocolSepIndex = pattern.indexOf("://");
|
|
2784
|
-
if (protocolSepIndex === -1) return pattern;
|
|
2785
|
-
const startOfPath = pattern.indexOf("/", protocolSepIndex + 3);
|
|
2786
|
-
return pattern.substring(0, startOfPath) + "/*";
|
|
2787
|
-
}
|
|
2788
|
-
function convertWebAccessibleResourcesToMv2(manifest) {
|
|
2789
|
-
if (manifest.web_accessible_resources == null) return;
|
|
2790
|
-
manifest.web_accessible_resources = Array.from(
|
|
2791
|
-
new Set(
|
|
2792
|
-
manifest.web_accessible_resources.flatMap((item) => {
|
|
2793
|
-
if (typeof item === "string") return item;
|
|
2794
|
-
return item.resources;
|
|
2795
|
-
})
|
|
2796
|
-
)
|
|
2797
|
-
);
|
|
2798
|
-
}
|
|
2799
|
-
function moveHostPermissionsToPermissions(manifest) {
|
|
2800
|
-
if (!manifest.host_permissions?.length) return;
|
|
2801
|
-
manifest.host_permissions.forEach(
|
|
2802
|
-
(permission) => addPermission(manifest, permission)
|
|
2803
|
-
);
|
|
2804
|
-
delete manifest.host_permissions;
|
|
2805
|
-
}
|
|
2806
|
-
function convertActionToMv2(manifest) {
|
|
2807
|
-
if (manifest.action == null || manifest.browser_action != null || manifest.page_action != null)
|
|
2808
|
-
return;
|
|
2809
|
-
manifest.browser_action = manifest.action;
|
|
2810
|
-
}
|
|
2811
|
-
function validateMv3WebAccessbileResources(manifest) {
|
|
2812
|
-
if (manifest.web_accessible_resources == null) return;
|
|
2813
|
-
const stringResources = manifest.web_accessible_resources.filter(
|
|
2814
|
-
(item) => typeof item === "string"
|
|
2815
|
-
);
|
|
2816
|
-
if (stringResources.length > 0) {
|
|
2817
|
-
throw Error(
|
|
2818
|
-
`Non-MV3 web_accessible_resources detected: ${JSON.stringify(
|
|
2819
|
-
stringResources
|
|
2820
|
-
)}. When manually defining web_accessible_resources, define them as MV3 objects ({ matches: [...], resources: [...] }), and WXT will automatically convert them to MV2 when necessary.`
|
|
2821
|
-
);
|
|
2822
|
-
}
|
|
2823
|
-
}
|
|
2824
|
-
function stripKeys(manifest) {
|
|
2825
|
-
let keysToRemove = [];
|
|
2826
|
-
if (wxt.config.manifestVersion === 2) {
|
|
2827
|
-
keysToRemove.push(...mv3OnlyKeys);
|
|
2828
|
-
if (wxt.config.browser === "firefox")
|
|
2829
|
-
keysToRemove.push(...firefoxMv3OnlyKeys);
|
|
2830
|
-
} else {
|
|
2831
|
-
keysToRemove.push(...mv2OnlyKeys);
|
|
2832
|
-
}
|
|
2833
|
-
keysToRemove.forEach((key) => {
|
|
2834
|
-
delete manifest[key];
|
|
2835
|
-
});
|
|
2836
|
-
}
|
|
2837
|
-
var mv2OnlyKeys = [
|
|
2838
|
-
"page_action",
|
|
2839
|
-
"browser_action",
|
|
2840
|
-
"automation",
|
|
2841
|
-
"content_capabilities",
|
|
2842
|
-
"converted_from_user_script",
|
|
2843
|
-
"current_locale",
|
|
2844
|
-
"differential_fingerprint",
|
|
2845
|
-
"event_rules",
|
|
2846
|
-
"file_browser_handlers",
|
|
2847
|
-
"file_system_provider_capabilities",
|
|
2848
|
-
"input_components",
|
|
2849
|
-
"nacl_modules",
|
|
2850
|
-
"natively_connectable",
|
|
2851
|
-
"offline_enabled",
|
|
2852
|
-
"platforms",
|
|
2853
|
-
"replacement_web_app",
|
|
2854
|
-
"system_indicator",
|
|
2855
|
-
"user_scripts"
|
|
2856
|
-
];
|
|
2857
|
-
var mv3OnlyKeys = [
|
|
2858
|
-
"action",
|
|
2859
|
-
"export",
|
|
2860
|
-
"optional_host_permissions",
|
|
2861
|
-
"side_panel"
|
|
2862
|
-
];
|
|
2863
|
-
var firefoxMv3OnlyKeys = ["host_permissions"];
|
|
2864
|
-
|
|
2865
|
-
// src/core/utils/building/rebuild.ts
|
|
2866
|
-
async function rebuild(allEntrypoints, entrypointGroups, existingOutput = {
|
|
2867
|
-
steps: [],
|
|
2868
|
-
publicAssets: []
|
|
2869
|
-
}) {
|
|
2870
|
-
const { default: ora } = await import("ora");
|
|
2871
|
-
const spinner = ora(`Preparing...`).start();
|
|
2872
|
-
await generateTypesDir(allEntrypoints).catch((err) => {
|
|
2873
|
-
wxt.logger.warn("Failed to update .wxt directory:", err);
|
|
2874
|
-
if (wxt.config.command === "build") throw err;
|
|
2875
|
-
});
|
|
2876
|
-
const newOutput = await buildEntrypoints(entrypointGroups, spinner);
|
|
2877
|
-
const mergedOutput = {
|
|
2878
|
-
steps: [...existingOutput.steps, ...newOutput.steps],
|
|
2879
|
-
publicAssets: [...existingOutput.publicAssets, ...newOutput.publicAssets]
|
|
2880
|
-
};
|
|
2881
|
-
const { manifest: newManifest, warnings: manifestWarnings } = await generateManifest(allEntrypoints, mergedOutput);
|
|
2882
|
-
const finalOutput = {
|
|
2883
|
-
manifest: newManifest,
|
|
2884
|
-
...newOutput
|
|
2885
|
-
};
|
|
2886
|
-
await writeManifest(newManifest, finalOutput);
|
|
2887
|
-
spinner.clear().stop();
|
|
2888
|
-
return {
|
|
2889
|
-
output: {
|
|
2890
|
-
manifest: newManifest,
|
|
2891
|
-
steps: [...existingOutput.steps, ...finalOutput.steps],
|
|
2892
|
-
publicAssets: [
|
|
2893
|
-
...existingOutput.publicAssets,
|
|
2894
|
-
...finalOutput.publicAssets
|
|
2895
|
-
]
|
|
2896
|
-
},
|
|
2897
|
-
manifest: newManifest,
|
|
2898
|
-
warnings: manifestWarnings
|
|
2899
|
-
};
|
|
2900
|
-
}
|
|
2901
|
-
|
|
2902
|
-
// src/core/utils/building/internal-build.ts
|
|
2903
|
-
import { relative as relative6 } from "node:path";
|
|
2904
|
-
|
|
2905
|
-
// src/core/utils/validation.ts
|
|
2906
|
-
function validateEntrypoints(entrypoints) {
|
|
2907
|
-
const errors = entrypoints.flatMap((entrypoint) => {
|
|
2908
|
-
switch (entrypoint.type) {
|
|
2909
|
-
case "content-script":
|
|
2910
|
-
return validateContentScriptEntrypoint(entrypoint);
|
|
2911
|
-
default:
|
|
2912
|
-
return validateBaseEntrypoint(entrypoint);
|
|
2913
|
-
}
|
|
2914
|
-
});
|
|
2915
|
-
let errorCount = 0;
|
|
2916
|
-
let warningCount = 0;
|
|
2917
|
-
for (const err of errors) {
|
|
2918
|
-
if (err.type === "warning") warningCount++;
|
|
2919
|
-
else errorCount++;
|
|
2920
|
-
}
|
|
2921
|
-
return {
|
|
2922
|
-
errors,
|
|
2923
|
-
errorCount,
|
|
2924
|
-
warningCount
|
|
2925
|
-
};
|
|
2926
|
-
}
|
|
2927
|
-
function validateContentScriptEntrypoint(definition) {
|
|
2928
|
-
const errors = validateBaseEntrypoint(definition);
|
|
2929
|
-
if (definition.options.matches == null) {
|
|
2930
|
-
errors.push({
|
|
2931
|
-
type: "error",
|
|
2932
|
-
message: "`matches` is required",
|
|
2933
|
-
value: definition.options.matches,
|
|
2934
|
-
entrypoint: definition
|
|
2935
|
-
});
|
|
2936
|
-
}
|
|
2937
|
-
return errors;
|
|
2938
|
-
}
|
|
2939
|
-
function validateBaseEntrypoint(definition) {
|
|
2940
|
-
const errors = [];
|
|
2941
|
-
if (definition.options.exclude != null && !Array.isArray(definition.options.exclude)) {
|
|
2942
|
-
errors.push({
|
|
2943
|
-
type: "error",
|
|
2944
|
-
message: "`exclude` must be an array of browser names",
|
|
2945
|
-
value: definition.options.exclude,
|
|
2946
|
-
entrypoint: definition
|
|
2947
|
-
});
|
|
2948
|
-
}
|
|
2949
|
-
if (definition.options.include != null && !Array.isArray(definition.options.include)) {
|
|
2950
|
-
errors.push({
|
|
2951
|
-
type: "error",
|
|
2952
|
-
message: "`include` must be an array of browser names",
|
|
2953
|
-
value: definition.options.include,
|
|
2954
|
-
entrypoint: definition
|
|
2955
|
-
});
|
|
2956
|
-
}
|
|
2957
|
-
return errors;
|
|
2958
|
-
}
|
|
2959
|
-
var ValidationError = class extends Error {
|
|
2960
|
-
};
|
|
2961
|
-
|
|
2962
|
-
// src/core/utils/building/internal-build.ts
|
|
2963
|
-
import { mergeJsonOutputs } from "@aklinker1/rollup-plugin-visualizer";
|
|
2964
|
-
import { isCI } from "ci-info";
|
|
2965
|
-
async function internalBuild() {
|
|
2966
|
-
await wxt.hooks.callHook("build:before", wxt);
|
|
2967
|
-
const verb = wxt.config.command === "serve" ? "Pre-rendering" : "Building";
|
|
2968
|
-
const target = `${wxt.config.browser}-mv${wxt.config.manifestVersion}`;
|
|
2969
|
-
wxt.logger.info(
|
|
2970
|
-
`${verb} ${pc5.cyan(target)} for ${pc5.cyan(wxt.config.mode)} with ${pc5.green(
|
|
2971
|
-
`${wxt.builder.name} ${wxt.builder.version}`
|
|
2972
|
-
)}`
|
|
2973
|
-
);
|
|
2974
|
-
const startTime = Date.now();
|
|
2975
|
-
await fs13.rm(wxt.config.outDir, { recursive: true, force: true });
|
|
2976
|
-
await fs13.ensureDir(wxt.config.outDir);
|
|
2977
|
-
const entrypoints = await findEntrypoints();
|
|
2978
|
-
wxt.logger.debug("Detected entrypoints:", entrypoints);
|
|
2979
|
-
const validationResults = validateEntrypoints(entrypoints);
|
|
2980
|
-
if (validationResults.errorCount + validationResults.warningCount > 0) {
|
|
2981
|
-
printValidationResults(validationResults);
|
|
2982
|
-
}
|
|
2983
|
-
if (validationResults.errorCount > 0) {
|
|
2984
|
-
throw new ValidationError(`Entrypoint validation failed`, {
|
|
2985
|
-
cause: validationResults
|
|
2986
|
-
});
|
|
2987
|
-
}
|
|
2988
|
-
const groups = groupEntrypoints(entrypoints);
|
|
2989
|
-
await wxt.hooks.callHook("entrypoints:grouped", wxt, groups);
|
|
2990
|
-
const { output, warnings } = await rebuild(entrypoints, groups, void 0);
|
|
2991
|
-
await wxt.hooks.callHook("build:done", wxt, output);
|
|
2992
|
-
await printBuildSummary(
|
|
2993
|
-
wxt.logger.success,
|
|
2994
|
-
`Built extension in ${formatDuration(Date.now() - startTime)}`,
|
|
2995
|
-
output
|
|
2996
|
-
);
|
|
2997
|
-
for (const warning of warnings) {
|
|
2998
|
-
wxt.logger.warn(...warning);
|
|
2999
|
-
}
|
|
3000
|
-
if (wxt.config.analysis.enabled) {
|
|
3001
|
-
await combineAnalysisStats();
|
|
3002
|
-
const statsPath = relative6(wxt.config.root, wxt.config.analysis.outputFile);
|
|
3003
|
-
wxt.logger.info(
|
|
3004
|
-
`Analysis complete:
|
|
3005
|
-
${pc5.gray("\u2514\u2500")} ${pc5.yellow(statsPath)}`
|
|
3006
|
-
);
|
|
3007
|
-
if (wxt.config.analysis.open) {
|
|
3008
|
-
if (isCI) {
|
|
3009
|
-
wxt.logger.debug(`Skipped opening ${pc5.yellow(statsPath)} in CI`);
|
|
3010
|
-
} else {
|
|
3011
|
-
wxt.logger.info(`Opening ${pc5.yellow(statsPath)} in browser...`);
|
|
3012
|
-
const { default: open } = await import("open");
|
|
3013
|
-
open(wxt.config.analysis.outputFile);
|
|
3014
|
-
}
|
|
3015
|
-
}
|
|
3016
|
-
}
|
|
3017
|
-
return output;
|
|
3018
|
-
}
|
|
3019
|
-
async function combineAnalysisStats() {
|
|
3020
|
-
const unixFiles = await glob4(`${wxt.config.analysis.outputName}-*.json`, {
|
|
3021
|
-
cwd: wxt.config.analysis.outputDir,
|
|
3022
|
-
absolute: true
|
|
3023
|
-
});
|
|
3024
|
-
const absolutePaths = unixFiles.map(unnormalizePath);
|
|
3025
|
-
await mergeJsonOutputs({
|
|
3026
|
-
inputs: absolutePaths,
|
|
3027
|
-
template: wxt.config.analysis.template,
|
|
3028
|
-
filename: wxt.config.analysis.outputFile
|
|
3029
|
-
});
|
|
3030
|
-
if (!wxt.config.analysis.keepArtifacts) {
|
|
3031
|
-
await Promise.all(absolutePaths.map((statsFile) => fs13.remove(statsFile)));
|
|
3032
|
-
}
|
|
3033
|
-
}
|
|
3034
|
-
function printValidationResults({
|
|
3035
|
-
errorCount,
|
|
3036
|
-
errors,
|
|
3037
|
-
warningCount
|
|
3038
|
-
}) {
|
|
3039
|
-
(errorCount > 0 ? wxt.logger.error : wxt.logger.warn)(
|
|
3040
|
-
`Entrypoint validation failed: ${errorCount} error${errorCount === 1 ? "" : "s"}, ${warningCount} warning${warningCount === 1 ? "" : "s"}`
|
|
3041
|
-
);
|
|
3042
|
-
const cwd = process.cwd();
|
|
3043
|
-
const entrypointErrors = errors.reduce((map, error) => {
|
|
3044
|
-
const entryErrors = map.get(error.entrypoint) ?? [];
|
|
3045
|
-
entryErrors.push(error);
|
|
3046
|
-
map.set(error.entrypoint, entryErrors);
|
|
3047
|
-
return map;
|
|
3048
|
-
}, /* @__PURE__ */ new Map());
|
|
3049
|
-
Array.from(entrypointErrors.entries()).forEach(([entrypoint, errors2]) => {
|
|
3050
|
-
wxt.logger.log(relative6(cwd, entrypoint.inputPath));
|
|
3051
|
-
console.log();
|
|
3052
|
-
errors2.forEach((err) => {
|
|
3053
|
-
const type = err.type === "error" ? pc5.red("ERROR") : pc5.yellow("WARN");
|
|
3054
|
-
const recieved = pc5.dim(`(recieved: ${JSON.stringify(err.value)})`);
|
|
3055
|
-
wxt.logger.log(` - ${type} ${err.message} ${recieved}`);
|
|
3056
|
-
});
|
|
3057
|
-
console.log();
|
|
3058
|
-
});
|
|
3059
|
-
}
|
|
3060
|
-
|
|
3061
|
-
// src/core/wxt.ts
|
|
3062
|
-
import { createHooks } from "hookable";
|
|
3063
|
-
|
|
3064
|
-
// src/core/package-managers/index.ts
|
|
3065
|
-
import {
|
|
3066
|
-
detectPackageManager,
|
|
3067
|
-
addDependency,
|
|
3068
|
-
addDevDependency,
|
|
3069
|
-
ensureDependencyInstalled,
|
|
3070
|
-
installDependencies,
|
|
3071
|
-
removeDependency
|
|
3072
|
-
} from "nypm";
|
|
3073
|
-
|
|
3074
|
-
// src/core/package-managers/npm.ts
|
|
3075
|
-
import path7 from "node:path";
|
|
3076
|
-
import { ensureDir as ensureDir3 } from "fs-extra";
|
|
3077
|
-
var npm = {
|
|
3078
|
-
overridesKey: "overrides",
|
|
3079
|
-
async downloadDependency(id, downloadDir) {
|
|
3080
|
-
await ensureDir3(downloadDir);
|
|
3081
|
-
const { execa } = await import("./execa-4UBDUBJZ.js");
|
|
3082
|
-
const res = await execa("npm", ["pack", id, "--json"], {
|
|
3083
|
-
cwd: downloadDir
|
|
3084
|
-
});
|
|
3085
|
-
const packed = JSON.parse(res.stdout);
|
|
3086
|
-
return path7.resolve(downloadDir, packed[0].filename);
|
|
3087
|
-
},
|
|
3088
|
-
async listDependencies(options) {
|
|
3089
|
-
const args = ["ls", "--json"];
|
|
3090
|
-
if (options?.all) {
|
|
3091
|
-
args.push("--depth", "Infinity");
|
|
3092
|
-
}
|
|
3093
|
-
const { execa } = await import("./execa-4UBDUBJZ.js");
|
|
3094
|
-
const res = await execa("npm", args, { cwd: options?.cwd });
|
|
3095
|
-
const project = JSON.parse(res.stdout);
|
|
3096
|
-
return flattenNpmListOutput([project]);
|
|
3097
|
-
}
|
|
3098
|
-
};
|
|
3099
|
-
function flattenNpmListOutput(projects) {
|
|
3100
|
-
const queue = projects.flatMap(
|
|
3101
|
-
(project) => {
|
|
3102
|
-
const acc = [];
|
|
3103
|
-
if (project.dependencies) acc.push(project.dependencies);
|
|
3104
|
-
if (project.devDependencies) acc.push(project.devDependencies);
|
|
3105
|
-
return acc;
|
|
3106
|
-
}
|
|
3107
|
-
);
|
|
3108
|
-
const dependencies = [];
|
|
3109
|
-
while (queue.length > 0) {
|
|
3110
|
-
Object.entries(queue.pop()).forEach(([name, meta]) => {
|
|
3111
|
-
dependencies.push({
|
|
3112
|
-
name,
|
|
3113
|
-
version: meta.version
|
|
3114
|
-
});
|
|
3115
|
-
if (meta.dependencies) queue.push(meta.dependencies);
|
|
3116
|
-
if (meta.devDependencies) queue.push(meta.devDependencies);
|
|
3117
|
-
});
|
|
3118
|
-
}
|
|
3119
|
-
return dedupeDependencies(dependencies);
|
|
3120
|
-
}
|
|
3121
|
-
function dedupeDependencies(dependencies) {
|
|
3122
|
-
const hashes = /* @__PURE__ */ new Set();
|
|
3123
|
-
return dependencies.filter((dep) => {
|
|
3124
|
-
const hash = `${dep.name}@${dep.version}`;
|
|
3125
|
-
if (hashes.has(hash)) {
|
|
3126
|
-
return false;
|
|
3127
|
-
} else {
|
|
3128
|
-
hashes.add(hash);
|
|
3129
|
-
return true;
|
|
3130
|
-
}
|
|
3131
|
-
});
|
|
3132
|
-
}
|
|
3133
|
-
|
|
3134
|
-
// src/core/package-managers/bun.ts
|
|
3135
|
-
var bun = {
|
|
3136
|
-
overridesKey: "overrides",
|
|
3137
|
-
// But also supports "resolutions"
|
|
3138
|
-
downloadDependency(...args) {
|
|
3139
|
-
return npm.downloadDependency(...args);
|
|
3140
|
-
},
|
|
3141
|
-
async listDependencies(options) {
|
|
3142
|
-
const args = ["pm", "ls"];
|
|
3143
|
-
if (options?.all) {
|
|
3144
|
-
args.push("--all");
|
|
3145
|
-
}
|
|
3146
|
-
const { execa } = await import("./execa-4UBDUBJZ.js");
|
|
3147
|
-
const res = await execa("bun", args, { cwd: options?.cwd });
|
|
3148
|
-
return dedupeDependencies(
|
|
3149
|
-
res.stdout.split("\n").slice(1).map((line) => line.trim()).map((line) => /.* (@?\S+)@(\S+)$/.exec(line)).filter((match) => !!match).map(([_, name, version2]) => ({ name, version: version2 }))
|
|
3150
|
-
);
|
|
3151
|
-
}
|
|
3152
|
-
};
|
|
3153
|
-
|
|
3154
|
-
// src/core/package-managers/yarn.ts
|
|
3155
|
-
var yarn = {
|
|
3156
|
-
overridesKey: "resolutions",
|
|
3157
|
-
downloadDependency(...args) {
|
|
3158
|
-
return npm.downloadDependency(...args);
|
|
3159
|
-
},
|
|
3160
|
-
async listDependencies(options) {
|
|
3161
|
-
const args = ["list", "--json"];
|
|
3162
|
-
if (options?.all) {
|
|
3163
|
-
args.push("--depth", "Infinity");
|
|
3164
|
-
}
|
|
3165
|
-
const { execa } = await import("./execa-4UBDUBJZ.js");
|
|
3166
|
-
const res = await execa("yarn", args, { cwd: options?.cwd });
|
|
3167
|
-
const tree = res.stdout.split("\n").map((line) => JSON.parse(line)).find((line) => line.type === "tree")?.data;
|
|
3168
|
-
if (tree == null) throw Error("'yarn list --json' did not output a tree");
|
|
3169
|
-
const queue = [...tree.trees];
|
|
3170
|
-
const dependencies = [];
|
|
3171
|
-
while (queue.length > 0) {
|
|
3172
|
-
const { name: treeName, children } = queue.pop();
|
|
3173
|
-
const match = /(@?\S+)@(\S+)$/.exec(treeName);
|
|
3174
|
-
if (match) {
|
|
3175
|
-
const [_, name, version2] = match;
|
|
3176
|
-
dependencies.push({ name, version: version2 });
|
|
3177
|
-
}
|
|
3178
|
-
if (children != null) {
|
|
3179
|
-
queue.push(...children);
|
|
3180
|
-
}
|
|
3181
|
-
}
|
|
3182
|
-
return dedupeDependencies(dependencies);
|
|
3183
|
-
}
|
|
3184
|
-
};
|
|
3185
|
-
|
|
3186
|
-
// src/core/package-managers/pnpm.ts
|
|
3187
|
-
var pnpm = {
|
|
3188
|
-
overridesKey: "resolutions",
|
|
3189
|
-
// "pnpm.overrides" has a higher priority, but I don't want to deal with nesting
|
|
3190
|
-
downloadDependency(...args) {
|
|
3191
|
-
return npm.downloadDependency(...args);
|
|
3192
|
-
},
|
|
3193
|
-
async listDependencies(options) {
|
|
3194
|
-
const args = ["ls", "-r", "--json"];
|
|
3195
|
-
if (options?.all) {
|
|
3196
|
-
args.push("--depth", "Infinity");
|
|
3197
|
-
}
|
|
3198
|
-
if (typeof process !== "undefined" && process.env.WXT_PNPM_IGNORE_WORKSPACE === "true") {
|
|
3199
|
-
args.push("--ignore-workspace");
|
|
3200
|
-
}
|
|
3201
|
-
const { execa } = await import("./execa-4UBDUBJZ.js");
|
|
3202
|
-
const res = await execa("pnpm", args, { cwd: options?.cwd });
|
|
3203
|
-
const projects = JSON.parse(res.stdout);
|
|
3204
|
-
return flattenNpmListOutput(projects);
|
|
3205
|
-
}
|
|
3206
|
-
};
|
|
3207
|
-
|
|
3208
|
-
// src/core/package-managers/index.ts
|
|
3209
|
-
async function createWxtPackageManager(root) {
|
|
3210
|
-
const pm = await detectPackageManager(root, {
|
|
3211
|
-
includeParentDirs: true
|
|
3212
|
-
});
|
|
3213
|
-
const requirePm = (cb) => {
|
|
3214
|
-
if (pm == null) throw Error("Could not detect package manager");
|
|
3215
|
-
return cb(pm);
|
|
3216
|
-
};
|
|
3217
|
-
return {
|
|
3218
|
-
get name() {
|
|
3219
|
-
return requirePm((pm2) => pm2.name);
|
|
3220
|
-
},
|
|
3221
|
-
get command() {
|
|
3222
|
-
return requirePm((pm2) => pm2.command);
|
|
3223
|
-
},
|
|
3224
|
-
get version() {
|
|
3225
|
-
return requirePm((pm2) => pm2.version);
|
|
3226
|
-
},
|
|
3227
|
-
get majorVersion() {
|
|
3228
|
-
return requirePm((pm2) => pm2.majorVersion);
|
|
3229
|
-
},
|
|
3230
|
-
get lockFile() {
|
|
3231
|
-
return requirePm((pm2) => pm2.lockFile);
|
|
3232
|
-
},
|
|
3233
|
-
get files() {
|
|
3234
|
-
return requirePm((pm2) => pm2.files);
|
|
3235
|
-
},
|
|
3236
|
-
addDependency,
|
|
3237
|
-
addDevDependency,
|
|
3238
|
-
ensureDependencyInstalled,
|
|
3239
|
-
installDependencies,
|
|
3240
|
-
removeDependency,
|
|
3241
|
-
get overridesKey() {
|
|
3242
|
-
return requirePm((pm2) => packageManagers[pm2.name].overridesKey);
|
|
3243
|
-
},
|
|
3244
|
-
downloadDependency(...args) {
|
|
3245
|
-
return requirePm(
|
|
3246
|
-
(pm2) => packageManagers[pm2.name].downloadDependency(...args)
|
|
3247
|
-
);
|
|
3248
|
-
},
|
|
3249
|
-
listDependencies(...args) {
|
|
3250
|
-
return requirePm(
|
|
3251
|
-
(pm2) => packageManagers[pm2.name].listDependencies(...args)
|
|
3252
|
-
);
|
|
3253
|
-
}
|
|
3254
|
-
};
|
|
3255
|
-
}
|
|
3256
|
-
var packageManagers = {
|
|
3257
|
-
npm,
|
|
3258
|
-
pnpm,
|
|
3259
|
-
bun,
|
|
3260
|
-
yarn
|
|
3261
|
-
};
|
|
3262
|
-
|
|
3263
|
-
// src/core/builders/vite/index.ts
|
|
3264
|
-
import { ViteNodeServer } from "vite-node/server";
|
|
3265
|
-
import { ViteNodeRunner } from "vite-node/client";
|
|
3266
|
-
import { installSourcemapsSupport } from "vite-node/source-map";
|
|
3267
|
-
async function createViteBuilder(wxtConfig, hooks, server) {
|
|
3268
|
-
const vite = await import("vite");
|
|
3269
|
-
const getBaseConfig = async () => {
|
|
3270
|
-
const config = await wxtConfig.vite(wxtConfig.env);
|
|
3271
|
-
config.root = wxtConfig.root;
|
|
3272
|
-
config.configFile = false;
|
|
3273
|
-
config.logLevel = "warn";
|
|
3274
|
-
config.mode = wxtConfig.mode;
|
|
3275
|
-
config.build ??= {};
|
|
3276
|
-
config.publicDir = wxtConfig.publicDir;
|
|
3277
|
-
config.build.copyPublicDir = false;
|
|
3278
|
-
config.build.outDir = wxtConfig.outDir;
|
|
3279
|
-
config.build.emptyOutDir = false;
|
|
3280
|
-
if (config.build.minify == null && wxtConfig.command === "serve") {
|
|
3281
|
-
config.build.minify = false;
|
|
3282
|
-
}
|
|
3283
|
-
if (config.build.sourcemap == null && wxtConfig.command === "serve") {
|
|
3284
|
-
config.build.sourcemap = "inline";
|
|
3285
|
-
}
|
|
3286
|
-
config.plugins ??= [];
|
|
3287
|
-
config.plugins.push(
|
|
3288
|
-
download(wxtConfig),
|
|
3289
|
-
devHtmlPrerender(wxtConfig, server),
|
|
3290
|
-
resolveVirtualModules(wxtConfig),
|
|
3291
|
-
devServerGlobals(wxtConfig, server),
|
|
3292
|
-
tsconfigPaths(wxtConfig),
|
|
3293
|
-
noopBackground(),
|
|
3294
|
-
globals(wxtConfig),
|
|
3295
|
-
excludeBrowserPolyfill(wxtConfig),
|
|
3296
|
-
defineImportMeta(),
|
|
3297
|
-
wxtPluginLoader(wxtConfig),
|
|
3298
|
-
resolveAppConfig(wxtConfig)
|
|
3299
|
-
);
|
|
3300
|
-
if (wxtConfig.analysis.enabled) {
|
|
3301
|
-
config.plugins.push(bundleAnalysis(wxtConfig));
|
|
3302
|
-
}
|
|
3303
|
-
return config;
|
|
3304
|
-
};
|
|
3305
|
-
const getLibModeConfig = (entrypoint) => {
|
|
3306
|
-
const entry = getRollupEntry(entrypoint);
|
|
3307
|
-
const plugins = [
|
|
3308
|
-
entrypointGroupGlobals(entrypoint)
|
|
3309
|
-
];
|
|
3310
|
-
if (entrypoint.type === "content-script-style" || entrypoint.type === "unlisted-style") {
|
|
3311
|
-
plugins.push(cssEntrypoints(entrypoint, wxtConfig));
|
|
3312
|
-
}
|
|
3313
|
-
const iifeReturnValueName = safeVarName(entrypoint.name);
|
|
3314
|
-
const libMode = {
|
|
3315
|
-
mode: wxtConfig.mode,
|
|
3316
|
-
plugins,
|
|
3317
|
-
esbuild: {
|
|
3318
|
-
// Add a footer with the returned value so it can return values to `scripting.executeScript`
|
|
3319
|
-
// Footer is added apart of esbuild to make sure it's not minified. It
|
|
3320
|
-
// get's removed if added to `build.rollupOptions.output.footer`
|
|
3321
|
-
// See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript#return_value
|
|
3322
|
-
footer: iifeReturnValueName + ";"
|
|
3323
|
-
},
|
|
3324
|
-
build: {
|
|
3325
|
-
lib: {
|
|
3326
|
-
entry,
|
|
3327
|
-
formats: ["iife"],
|
|
3328
|
-
name: iifeReturnValueName,
|
|
3329
|
-
fileName: entrypoint.name
|
|
3330
|
-
},
|
|
3331
|
-
rollupOptions: {
|
|
3332
|
-
output: {
|
|
3333
|
-
// There's only a single output for this build, so we use the desired bundle path for the
|
|
3334
|
-
// entry output (like "content-scripts/overlay.js")
|
|
3335
|
-
entryFileNames: getEntrypointBundlePath(
|
|
3336
|
-
entrypoint,
|
|
3337
|
-
wxtConfig.outDir,
|
|
3338
|
-
".js"
|
|
3339
|
-
),
|
|
3340
|
-
// Output content script CSS to `content-scripts/`, but all other scripts are written to
|
|
3341
|
-
// `assets/`.
|
|
3342
|
-
assetFileNames: ({ name }) => {
|
|
3343
|
-
if (entrypoint.type === "content-script" && name?.endsWith("css")) {
|
|
3344
|
-
return `content-scripts/${entrypoint.name}.[ext]`;
|
|
3345
|
-
} else {
|
|
3346
|
-
return `assets/${entrypoint.name}.[ext]`;
|
|
3347
|
-
}
|
|
3348
|
-
}
|
|
3349
|
-
}
|
|
3350
|
-
}
|
|
3351
|
-
},
|
|
3352
|
-
define: {
|
|
3353
|
-
// See https://github.com/aklinker1/vite-plugin-web-extension/issues/96
|
|
3354
|
-
"process.env.NODE_ENV": JSON.stringify(wxtConfig.mode)
|
|
3355
|
-
}
|
|
3356
|
-
};
|
|
3357
|
-
return libMode;
|
|
3358
|
-
};
|
|
3359
|
-
const getMultiPageConfig = (entrypoints) => {
|
|
3360
|
-
const htmlEntrypoints = new Set(
|
|
3361
|
-
entrypoints.filter(isHtmlEntrypoint).map((e) => e.name)
|
|
3362
|
-
);
|
|
3363
|
-
return {
|
|
3364
|
-
mode: wxtConfig.mode,
|
|
3365
|
-
plugins: [
|
|
3366
|
-
multipageMove(entrypoints, wxtConfig),
|
|
3367
|
-
entrypointGroupGlobals(entrypoints)
|
|
3368
|
-
],
|
|
3369
|
-
build: {
|
|
3370
|
-
rollupOptions: {
|
|
3371
|
-
input: entrypoints.reduce((input, entry) => {
|
|
3372
|
-
input[entry.name] = getRollupEntry(entry);
|
|
3373
|
-
return input;
|
|
3374
|
-
}, {}),
|
|
3375
|
-
output: {
|
|
3376
|
-
// Include a hash to prevent conflicts
|
|
3377
|
-
chunkFileNames: "chunks/[name]-[hash].js",
|
|
3378
|
-
entryFileNames: ({ name }) => {
|
|
3379
|
-
if (htmlEntrypoints.has(name)) return "chunks/[name]-[hash].js";
|
|
3380
|
-
return "[name].js";
|
|
3381
|
-
},
|
|
3382
|
-
// We can't control the "name", so we need a hash to prevent conflicts
|
|
3383
|
-
assetFileNames: "assets/[name]-[hash].[ext]"
|
|
3384
|
-
}
|
|
3385
|
-
}
|
|
3386
|
-
}
|
|
3387
|
-
};
|
|
3388
|
-
};
|
|
3389
|
-
const getCssConfig = (entrypoint) => {
|
|
3390
|
-
return {
|
|
3391
|
-
mode: wxtConfig.mode,
|
|
3392
|
-
plugins: [entrypointGroupGlobals(entrypoint)],
|
|
3393
|
-
build: {
|
|
3394
|
-
rollupOptions: {
|
|
3395
|
-
input: {
|
|
3396
|
-
[entrypoint.name]: entrypoint.inputPath
|
|
3397
|
-
},
|
|
3398
|
-
output: {
|
|
3399
|
-
assetFileNames: () => {
|
|
3400
|
-
if (entrypoint.type === "content-script-style") {
|
|
3401
|
-
return `content-scripts/${entrypoint.name}.[ext]`;
|
|
3402
|
-
} else {
|
|
3403
|
-
return `assets/${entrypoint.name}.[ext]`;
|
|
3404
|
-
}
|
|
3405
|
-
}
|
|
3406
|
-
}
|
|
3407
|
-
}
|
|
3408
|
-
}
|
|
3409
|
-
};
|
|
3410
|
-
};
|
|
3411
|
-
return {
|
|
3412
|
-
name: "Vite",
|
|
3413
|
-
version: vite.version,
|
|
3414
|
-
async importEntrypoint(path8) {
|
|
3415
|
-
switch (wxtConfig.experimental.entrypointImporter) {
|
|
3416
|
-
default:
|
|
3417
|
-
case "jiti": {
|
|
3418
|
-
return await importEntrypointFile(path8);
|
|
3419
|
-
}
|
|
3420
|
-
case "vite-runtime": {
|
|
3421
|
-
const baseConfig = await getBaseConfig();
|
|
3422
|
-
const envConfig = {
|
|
3423
|
-
plugins: [
|
|
3424
|
-
webextensionPolyfillMock(wxtConfig),
|
|
3425
|
-
removeEntrypointMainFunction(wxtConfig, path8)
|
|
3426
|
-
]
|
|
3427
|
-
};
|
|
3428
|
-
const config = vite.mergeConfig(baseConfig, envConfig);
|
|
3429
|
-
const server2 = await vite.createServer(config);
|
|
3430
|
-
await server2.listen();
|
|
3431
|
-
const runtime = await vite.createViteRuntime(server2, { hmr: false });
|
|
3432
|
-
const module = await runtime.executeUrl(path8);
|
|
3433
|
-
await server2.close();
|
|
3434
|
-
return module.default;
|
|
3435
|
-
}
|
|
3436
|
-
case "vite-node": {
|
|
3437
|
-
const baseConfig = await getBaseConfig();
|
|
3438
|
-
baseConfig.optimizeDeps ??= {};
|
|
3439
|
-
baseConfig.optimizeDeps.noDiscovery = true;
|
|
3440
|
-
baseConfig.optimizeDeps.include = [];
|
|
3441
|
-
const envConfig = {
|
|
3442
|
-
plugins: [
|
|
3443
|
-
webextensionPolyfillMock(wxtConfig),
|
|
3444
|
-
removeEntrypointMainFunction(wxtConfig, path8)
|
|
3445
|
-
]
|
|
3446
|
-
};
|
|
3447
|
-
const config = vite.mergeConfig(baseConfig, envConfig);
|
|
3448
|
-
const server2 = await vite.createServer(config);
|
|
3449
|
-
await server2.pluginContainer.buildStart({});
|
|
3450
|
-
const node = new ViteNodeServer(
|
|
3451
|
-
// @ts-ignore: Some weird type error...
|
|
3452
|
-
server2
|
|
3453
|
-
);
|
|
3454
|
-
installSourcemapsSupport({
|
|
3455
|
-
getSourceMap: (source) => node.getSourceMap(source)
|
|
3456
|
-
});
|
|
3457
|
-
const runner = new ViteNodeRunner({
|
|
3458
|
-
root: server2.config.root,
|
|
3459
|
-
base: server2.config.base,
|
|
3460
|
-
// when having the server and runner in a different context,
|
|
3461
|
-
// you will need to handle the communication between them
|
|
3462
|
-
// and pass to this function
|
|
3463
|
-
fetchModule(id) {
|
|
3464
|
-
return node.fetchModule(id);
|
|
3465
|
-
},
|
|
3466
|
-
resolveId(id, importer) {
|
|
3467
|
-
return node.resolveId(id, importer);
|
|
3468
|
-
}
|
|
3469
|
-
});
|
|
3470
|
-
const res = await runner.executeFile(path8);
|
|
3471
|
-
await server2.close();
|
|
3472
|
-
return res.default;
|
|
3473
|
-
}
|
|
3474
|
-
}
|
|
3475
|
-
},
|
|
3476
|
-
async build(group) {
|
|
3477
|
-
let entryConfig;
|
|
3478
|
-
if (Array.isArray(group)) entryConfig = getMultiPageConfig(group);
|
|
3479
|
-
else if (group.inputPath.endsWith(".css"))
|
|
3480
|
-
entryConfig = getCssConfig(group);
|
|
3481
|
-
else entryConfig = getLibModeConfig(group);
|
|
3482
|
-
const buildConfig = vite.mergeConfig(await getBaseConfig(), entryConfig);
|
|
3483
|
-
await hooks.callHook(
|
|
3484
|
-
"vite:build:extendConfig",
|
|
3485
|
-
toArray(group),
|
|
3486
|
-
buildConfig
|
|
3487
|
-
);
|
|
3488
|
-
const result = await vite.build(buildConfig);
|
|
3489
|
-
return {
|
|
3490
|
-
entrypoints: group,
|
|
3491
|
-
chunks: getBuildOutputChunks(result)
|
|
3492
|
-
};
|
|
3493
|
-
},
|
|
3494
|
-
async createServer(info) {
|
|
3495
|
-
const serverConfig = {
|
|
3496
|
-
server: {
|
|
3497
|
-
port: info.port,
|
|
3498
|
-
strictPort: true,
|
|
3499
|
-
host: info.hostname,
|
|
3500
|
-
origin: info.origin
|
|
3501
|
-
}
|
|
3502
|
-
};
|
|
3503
|
-
const baseConfig = await getBaseConfig();
|
|
3504
|
-
const finalConfig = vite.mergeConfig(baseConfig, serverConfig);
|
|
3505
|
-
await hooks.callHook("vite:devServer:extendConfig", finalConfig);
|
|
3506
|
-
const viteServer = await vite.createServer(finalConfig);
|
|
3507
|
-
const server2 = {
|
|
3508
|
-
async listen() {
|
|
3509
|
-
await viteServer.listen(info.port);
|
|
3510
|
-
},
|
|
3511
|
-
async close() {
|
|
3512
|
-
await viteServer.close();
|
|
3513
|
-
},
|
|
3514
|
-
transformHtml(...args) {
|
|
3515
|
-
return viteServer.transformIndexHtml(...args);
|
|
3516
|
-
},
|
|
3517
|
-
ws: {
|
|
3518
|
-
send(message, payload) {
|
|
3519
|
-
return viteServer.ws.send(message, payload);
|
|
3520
|
-
},
|
|
3521
|
-
on(message, cb) {
|
|
3522
|
-
viteServer.ws.on(message, cb);
|
|
3523
|
-
}
|
|
3524
|
-
},
|
|
3525
|
-
watcher: viteServer.watcher
|
|
3526
|
-
};
|
|
3527
|
-
return server2;
|
|
3528
|
-
}
|
|
3529
|
-
};
|
|
3530
|
-
}
|
|
3531
|
-
function getBuildOutputChunks(result) {
|
|
3532
|
-
if ("on" in result) throw Error("wxt does not support vite watch mode.");
|
|
3533
|
-
if (Array.isArray(result)) return result.flatMap(({ output }) => output);
|
|
3534
|
-
return result.output;
|
|
3535
|
-
}
|
|
3536
|
-
function getRollupEntry(entrypoint) {
|
|
3537
|
-
let virtualEntrypointType;
|
|
3538
|
-
switch (entrypoint.type) {
|
|
3539
|
-
case "background":
|
|
3540
|
-
case "unlisted-script":
|
|
3541
|
-
virtualEntrypointType = entrypoint.type;
|
|
3542
|
-
break;
|
|
3543
|
-
case "content-script":
|
|
3544
|
-
virtualEntrypointType = entrypoint.options.world === "MAIN" ? "content-script-main-world" : "content-script-isolated-world";
|
|
3545
|
-
break;
|
|
3546
|
-
}
|
|
3547
|
-
if (virtualEntrypointType) {
|
|
3548
|
-
const moduleId = `virtual:wxt-${virtualEntrypointType}-entrypoint`;
|
|
3549
|
-
return `${moduleId}?${entrypoint.inputPath}`;
|
|
3550
|
-
}
|
|
3551
|
-
return entrypoint.inputPath;
|
|
3552
|
-
}
|
|
3553
|
-
|
|
3554
|
-
// src/core/wxt.ts
|
|
3555
|
-
var wxt;
|
|
3556
|
-
async function registerWxt(command, inlineConfig = {}, getServer) {
|
|
3557
|
-
const hooks = createHooks();
|
|
3558
|
-
const config = await resolveConfig(inlineConfig, command);
|
|
3559
|
-
const server = await getServer?.(config);
|
|
3560
|
-
const builder = await createViteBuilder(config, hooks, server);
|
|
3561
|
-
const pm = await createWxtPackageManager(config.root);
|
|
3562
|
-
wxt = {
|
|
3563
|
-
config,
|
|
3564
|
-
hooks,
|
|
3565
|
-
get logger() {
|
|
3566
|
-
return config.logger;
|
|
3567
|
-
},
|
|
3568
|
-
async reloadConfig() {
|
|
3569
|
-
wxt.config = await resolveConfig(inlineConfig, command);
|
|
3570
|
-
},
|
|
3571
|
-
pm,
|
|
3572
|
-
builder,
|
|
3573
|
-
server
|
|
3574
|
-
};
|
|
3575
|
-
const initModule = async (module) => {
|
|
3576
|
-
if (module.hooks) wxt.hooks.addHooks(module.hooks);
|
|
3577
|
-
await module.setup?.(
|
|
3578
|
-
wxt,
|
|
3579
|
-
// @ts-expect-error: Untyped configKey field
|
|
3580
|
-
module.configKey ? config[module.configKey] : void 0
|
|
3581
|
-
);
|
|
3582
|
-
};
|
|
3583
|
-
for (const builtinModule of builtinModules) await initModule(builtinModule);
|
|
3584
|
-
for (const userModule of config.userModules) await initModule(userModule);
|
|
3585
|
-
wxt.hooks.addHooks(config.hooks);
|
|
3586
|
-
await wxt.hooks.callHook("ready", wxt);
|
|
3587
|
-
}
|
|
3588
|
-
|
|
3589
|
-
export {
|
|
3590
|
-
normalizePath,
|
|
3591
|
-
unnormalizePath,
|
|
3592
|
-
getEntrypointBundlePath,
|
|
3593
|
-
isHtmlEntrypoint,
|
|
3594
|
-
formatDuration,
|
|
3595
|
-
download,
|
|
3596
|
-
tsconfigPaths,
|
|
3597
|
-
globals,
|
|
3598
|
-
webextensionPolyfillMock,
|
|
3599
|
-
resolveAppConfig,
|
|
3600
|
-
kebabCaseAlphanumeric,
|
|
3601
|
-
vitePlugin,
|
|
3602
|
-
wxt,
|
|
3603
|
-
registerWxt,
|
|
3604
|
-
detectDevChanges,
|
|
3605
|
-
findEntrypoints,
|
|
3606
|
-
generateTypesDir,
|
|
3607
|
-
resolveConfig,
|
|
3608
|
-
printFileList,
|
|
3609
|
-
version,
|
|
3610
|
-
mapWxtOptionsToRegisteredContentScript,
|
|
3611
|
-
getContentScriptJs,
|
|
3612
|
-
getPackageJson,
|
|
3613
|
-
getContentScriptCssFiles,
|
|
3614
|
-
getContentScriptsCssMap,
|
|
3615
|
-
rebuild,
|
|
3616
|
-
internalBuild
|
|
3617
|
-
};
|