wxt 0.20.20 → 0.20.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtin-modules/favicon-permission.mjs +28 -0
- package/dist/builtin-modules/index.mjs +2 -1
- package/dist/cli/cli-utils.mjs +1 -1
- package/dist/core/builders/vite/index.mjs +13 -6
- package/dist/core/builders/vite/plugins/download.mjs +1 -0
- package/dist/core/clean.mjs +4 -4
- package/dist/core/create-server.mjs +3 -5
- package/dist/core/generate-wxt-dir.mjs +18 -1
- package/dist/core/initialize.mjs +14 -14
- package/dist/core/keyboard-shortcuts.mjs +2 -2
- package/dist/core/resolve-config.mjs +7 -0
- package/dist/core/utils/building/build-entrypoints.mjs +3 -3
- package/dist/core/utils/building/find-entrypoints.mjs +24 -10
- package/dist/core/utils/building/internal-build.mjs +7 -7
- package/dist/core/utils/env.mjs +22 -13
- package/dist/core/utils/i18n.mjs +1 -1
- package/dist/core/utils/log/printFileList.mjs +14 -14
- package/dist/core/utils/log/printHeader.mjs +2 -2
- package/dist/core/utils/manifest.mjs +12 -13
- package/dist/core/utils/picomatch-multiple.mjs +26 -0
- package/dist/core/utils/syntax-errors.mjs +2 -2
- package/dist/core/utils/theme-icons.mjs +71 -0
- package/dist/core/utils/transform.mjs +1 -1
- package/dist/core/zip.mjs +3 -3
- package/dist/index.d.mts +2 -2
- package/dist/types.d.mts +89 -10
- package/dist/utils/content-script-ui/iframe.d.mts +2 -2
- package/dist/utils/inject-script.d.mts +2 -2
- package/dist/utils/inject-script.mjs +3 -2
- package/dist/version.mjs +1 -1
- package/package.json +27 -19
- package/LICENSE +0 -21
- package/dist/core/utils/minimatch-multiple.mjs +0 -26
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { defineWxtModule } from "../modules.mjs";
|
|
2
|
+
//#region src/builtin-modules/favicon-permission.ts
|
|
3
|
+
/**
|
|
4
|
+
* Adds a template-literal type for the `_favicon/` paths served by Chrome's
|
|
5
|
+
* favicon API when the `favicon` permission is declared. With this module,
|
|
6
|
+
* `browser.runtime.getURL('/_favicon/?pageUrl=...')` type-checks without
|
|
7
|
+
* needing a `@ts-expect-error`.
|
|
8
|
+
*
|
|
9
|
+
* Extensions that load favicons from a content script must still add their own
|
|
10
|
+
* `web_accessible_resources` entry — this module intentionally does not touch
|
|
11
|
+
* the manifest. See the review thread on #1570 for context.
|
|
12
|
+
*
|
|
13
|
+
* @see https://developer.chrome.com/docs/extensions/how-to/ui/favicons
|
|
14
|
+
*/
|
|
15
|
+
var favicon_permission_default = defineWxtModule({
|
|
16
|
+
name: "wxt:built-in:favicon-permission",
|
|
17
|
+
setup(wxt) {
|
|
18
|
+
wxt.hooks.hook("prepare:publicPaths", (_, paths) => {
|
|
19
|
+
if (!wxt.config.manifest.permissions?.includes("favicon")) return;
|
|
20
|
+
paths.push({
|
|
21
|
+
type: "templateLiteral",
|
|
22
|
+
path: "_favicon/?${string}"
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
//#endregion
|
|
28
|
+
export { favicon_permission_default as default };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import favicon_permission_default from "./favicon-permission.mjs";
|
|
1
2
|
import unimport_default from "./unimport.mjs";
|
|
2
3
|
//#region src/builtin-modules/index.ts
|
|
3
|
-
const builtinModules = [unimport_default];
|
|
4
|
+
const builtinModules = [unimport_default, favicon_permission_default];
|
|
4
5
|
//#endregion
|
|
5
6
|
export { builtinModules };
|
package/dist/cli/cli-utils.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { formatDuration } from "../core/utils/time.mjs";
|
|
2
1
|
import { filterTruthy, toArray } from "../core/utils/arrays.mjs";
|
|
2
|
+
import { formatDuration } from "../core/utils/time.mjs";
|
|
3
3
|
import { registerWxt } from "../core/wxt.mjs";
|
|
4
4
|
import { printHeader } from "../core/utils/log/printHeader.mjs";
|
|
5
5
|
import "../core/utils/log/index.mjs";
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { normalizePath } from "../../utils/paths.mjs";
|
|
2
2
|
import "../../utils/index.mjs";
|
|
3
|
+
import { toArray } from "../../utils/arrays.mjs";
|
|
3
4
|
import { getEntrypointBundlePath, isHtmlEntrypoint } from "../../utils/entrypoints.mjs";
|
|
5
|
+
import { createExtensionEnvironment } from "../../utils/environments/extension-environment.mjs";
|
|
6
|
+
import "../../utils/environments/index.mjs";
|
|
7
|
+
import { safeVarName } from "../../utils/strings.mjs";
|
|
4
8
|
import { devHtmlPrerender } from "./plugins/devHtmlPrerender.mjs";
|
|
5
9
|
import { devServerGlobals } from "./plugins/devServerGlobals.mjs";
|
|
6
10
|
import { download } from "./plugins/download.mjs";
|
|
@@ -18,14 +22,10 @@ import { resolveAppConfig } from "./plugins/resolveAppConfig.mjs";
|
|
|
18
22
|
import { iifeFooter } from "./plugins/iifeFooter.mjs";
|
|
19
23
|
import { iifeAnonymous } from "./plugins/iifeAnonymous.mjs";
|
|
20
24
|
import "./plugins/index.mjs";
|
|
21
|
-
import { toArray } from "../../utils/arrays.mjs";
|
|
22
|
-
import { safeVarName } from "../../utils/strings.mjs";
|
|
23
|
-
import { createExtensionEnvironment } from "../../utils/environments/extension-environment.mjs";
|
|
24
|
-
import "../../utils/environments/index.mjs";
|
|
25
25
|
import { mkdir, readdir, rename, rmdir, stat } from "node:fs/promises";
|
|
26
26
|
import { dirname, extname, join, relative } from "node:path";
|
|
27
|
-
import { ViteNodeServer } from "vite-node/server";
|
|
28
27
|
import { ViteNodeRunner } from "vite-node/client";
|
|
28
|
+
import { ViteNodeServer } from "vite-node/server";
|
|
29
29
|
import { installSourcemapsSupport } from "vite-node/source-map";
|
|
30
30
|
//#region src/core/builders/vite/index.ts
|
|
31
31
|
async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
|
|
@@ -52,6 +52,10 @@ async function createViteBuilder(wxtConfig, hooks, getWxtDevServer) {
|
|
|
52
52
|
config.server.watch = { ignored: [`${wxtConfig.outBaseDir}/**`, `${wxtConfig.wxtDir}/**`] };
|
|
53
53
|
config.legacy ??= {};
|
|
54
54
|
config.legacy.skipWebSocketTokenCheck = true;
|
|
55
|
+
if (isRolldownVersion(vite.version)) {} else {
|
|
56
|
+
config.esbuild ??= {};
|
|
57
|
+
if (config.esbuild) config.esbuild.charset = "ascii";
|
|
58
|
+
}
|
|
55
59
|
const server = getWxtDevServer?.();
|
|
56
60
|
config.plugins ??= [];
|
|
57
61
|
config.plugins.push(download(wxtConfig), devHtmlPrerender(wxtConfig, server), resolveVirtualModules(wxtConfig), devServerGlobals(wxtConfig, server), tsconfigPaths(wxtConfig), noopBackground(), globals(wxtConfig), defineImportMeta(), wxtPluginLoader(wxtConfig), resolveAppConfig(wxtConfig));
|
|
@@ -263,7 +267,7 @@ function getRollupEntry(entrypoint) {
|
|
|
263
267
|
return entrypoint.inputPath;
|
|
264
268
|
}
|
|
265
269
|
/**
|
|
266
|
-
* Ensures the HTML files output by a
|
|
270
|
+
* Ensures the HTML files output by a multi-page build are in the correct
|
|
267
271
|
* location. This does two things:
|
|
268
272
|
*
|
|
269
273
|
* 1. Moves the HTML files to their final location at
|
|
@@ -310,5 +314,8 @@ async function removeEmptyDirs(dir) {
|
|
|
310
314
|
await rmdir(dir);
|
|
311
315
|
} catch {}
|
|
312
316
|
}
|
|
317
|
+
function isRolldownVersion(version) {
|
|
318
|
+
return Number(version.split(".")[0]) >= 8;
|
|
319
|
+
}
|
|
313
320
|
//#endregion
|
|
314
321
|
export { createViteBuilder };
|
package/dist/core/clean.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { registerWxt, wxt } from "./wxt.mjs";
|
|
|
2
2
|
import { rm } from "node:fs/promises";
|
|
3
3
|
import { glob } from "tinyglobby";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import
|
|
5
|
+
import { styleText } from "node:util";
|
|
6
6
|
//#region src/core/clean.ts
|
|
7
7
|
async function clean(config) {
|
|
8
8
|
if (typeof config === "string") config = { root: config };
|
|
@@ -15,7 +15,7 @@ async function clean(config) {
|
|
|
15
15
|
"**/.wxt",
|
|
16
16
|
`${path.relative(root, wxt.config.outBaseDir)}/*`
|
|
17
17
|
];
|
|
18
|
-
wxt.logger.debug("Looking for:", tempDirs.map(
|
|
18
|
+
wxt.logger.debug("Looking for:", tempDirs.map((dir) => styleText("cyan", dir)).join(", "));
|
|
19
19
|
const directories = await glob(tempDirs, {
|
|
20
20
|
cwd: root,
|
|
21
21
|
absolute: true,
|
|
@@ -27,13 +27,13 @@ async function clean(config) {
|
|
|
27
27
|
wxt.logger.debug("No generated files found.");
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
|
-
wxt.logger.debug("Found:", directories.map((dir) =>
|
|
30
|
+
wxt.logger.debug("Found:", directories.map((dir) => styleText("cyan", path.relative(root, dir))).join(", "));
|
|
31
31
|
for (const directory of directories) {
|
|
32
32
|
await rm(directory, {
|
|
33
33
|
force: true,
|
|
34
34
|
recursive: true
|
|
35
35
|
});
|
|
36
|
-
wxt.logger.debug("Deleted " +
|
|
36
|
+
wxt.logger.debug("Deleted " + styleText("cyan", path.relative(root, directory)));
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
@@ -12,7 +12,7 @@ import { createExtensionRunner } from "./runners/index.mjs";
|
|
|
12
12
|
import { createKeyboardShortcuts } from "./keyboard-shortcuts.mjs";
|
|
13
13
|
import { isBabelSyntaxError, logBabelSyntaxError } from "./utils/syntax-errors.mjs";
|
|
14
14
|
import { relative } from "node:path";
|
|
15
|
-
import
|
|
15
|
+
import { styleText } from "node:util";
|
|
16
16
|
import { debounce } from "perfect-debounce";
|
|
17
17
|
import chokidar from "chokidar";
|
|
18
18
|
import { Mutex } from "async-mutex";
|
|
@@ -172,7 +172,7 @@ function createFileReloader(server) {
|
|
|
172
172
|
server.restartBrowser();
|
|
173
173
|
return;
|
|
174
174
|
}
|
|
175
|
-
wxt.logger.info(`Changed: ${Array.from(new Set(fileChanges)).map((file) =>
|
|
175
|
+
wxt.logger.info(`Changed: ${Array.from(new Set(fileChanges)).map((file) => styleText("dim", relative(wxt.config.root, file))).join(", ")}`);
|
|
176
176
|
const allEntrypoints = await findEntrypoints();
|
|
177
177
|
try {
|
|
178
178
|
const { output: newOutput } = await rebuild(allEntrypoints, changes.rebuildGroups, changes.cachedOutput);
|
|
@@ -231,9 +231,7 @@ function reloadHtmlPages(groups, server) {
|
|
|
231
231
|
return { reloadedNames: htmlEntries.map((entry) => entry.name) };
|
|
232
232
|
}
|
|
233
233
|
function getFilenameList(names) {
|
|
234
|
-
return names.map((name) =>
|
|
235
|
-
return pc.cyan(name);
|
|
236
|
-
}).join(pc.dim(", "));
|
|
234
|
+
return names.map((name) => styleText("cyan", name)).join(styleText("dim", ", "));
|
|
237
235
|
}
|
|
238
236
|
/**
|
|
239
237
|
* Based on the current build output, return a list of files that are:
|
|
@@ -39,7 +39,7 @@ async function getPathsDeclarationEntry(entrypoints) {
|
|
|
39
39
|
const unions = [
|
|
40
40
|
` | ""`,
|
|
41
41
|
` | "/"`,
|
|
42
|
-
...paths.map(
|
|
42
|
+
...paths.map(normalizePublicPathEntry).sort((a, b) => a.path.localeCompare(b.path) || a.type.localeCompare(b.type)).map(renderPublicPathUnionMember)
|
|
43
43
|
].join("\n");
|
|
44
44
|
return {
|
|
45
45
|
path: "types/paths.d.ts",
|
|
@@ -59,6 +59,23 @@ declare module "wxt/browser" {
|
|
|
59
59
|
tsReference: true
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
|
+
function normalizePublicPathEntry(entry) {
|
|
63
|
+
if (typeof entry === "string") return {
|
|
64
|
+
type: "string",
|
|
65
|
+
path: normalizePath(entry)
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
type: entry.type,
|
|
69
|
+
path: normalizePath(entry.path)
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function renderPublicPathUnionMember(entry) {
|
|
73
|
+
const path = entry.path.startsWith("/") ? entry.path : `/${entry.path}`;
|
|
74
|
+
switch (entry.type) {
|
|
75
|
+
case "templateLiteral": return ` | \`${path}\``;
|
|
76
|
+
case "string": return ` | "${path}"`;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
62
79
|
function getEntrypointPublicExt(entry) {
|
|
63
80
|
if (isHtmlEntrypoint(entry)) return ".html";
|
|
64
81
|
switch (entry.type) {
|
package/dist/core/initialize.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { pathExists } from "./utils/fs.mjs";
|
|
|
2
2
|
import { readdir, rename } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { consola as consola$1 } from "consola";
|
|
5
|
-
import
|
|
5
|
+
import { styleText } from "node:util";
|
|
6
6
|
import prompts from "prompts";
|
|
7
7
|
import { downloadTemplate } from "giget";
|
|
8
8
|
//#region src/core/initialize.ts
|
|
@@ -22,7 +22,7 @@ async function initialize(options) {
|
|
|
22
22
|
type: () => defaultTemplate == null ? "select" : void 0,
|
|
23
23
|
message: "Choose a template",
|
|
24
24
|
choices: templates.map((template) => ({
|
|
25
|
-
title: TEMPLATE_COLORS[template.name]
|
|
25
|
+
title: TEMPLATE_COLORS[template.name] ? styleText(TEMPLATE_COLORS[template.name], template.name) : template.name,
|
|
26
26
|
value: template
|
|
27
27
|
}))
|
|
28
28
|
},
|
|
@@ -32,19 +32,19 @@ async function initialize(options) {
|
|
|
32
32
|
message: "Package Manager",
|
|
33
33
|
choices: [
|
|
34
34
|
{
|
|
35
|
-
title:
|
|
35
|
+
title: styleText("red", "npm"),
|
|
36
36
|
value: "npm"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
|
-
title:
|
|
39
|
+
title: styleText("yellow", "pnpm"),
|
|
40
40
|
value: "pnpm"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
|
-
title:
|
|
43
|
+
title: styleText("cyan", "yarn"),
|
|
44
44
|
value: "yarn"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
|
-
title:
|
|
47
|
+
title: styleText("magenta", "bun"),
|
|
48
48
|
value: "bun"
|
|
49
49
|
}
|
|
50
50
|
]
|
|
@@ -62,12 +62,12 @@ async function initialize(options) {
|
|
|
62
62
|
await cloneProject(input);
|
|
63
63
|
const cdPath = path.relative(process.cwd(), path.resolve(input.directory));
|
|
64
64
|
console.log();
|
|
65
|
-
consola$1.log(`✨ WXT project created with the ${TEMPLATE_COLORS[input.template.name]
|
|
65
|
+
consola$1.log(`✨ WXT project created with the ${TEMPLATE_COLORS[input.template.name] ? styleText(TEMPLATE_COLORS[input.template.name], input.template.name) : input.template.name} template.`);
|
|
66
66
|
console.log();
|
|
67
67
|
consola$1.log("Next steps:");
|
|
68
68
|
let step = 0;
|
|
69
|
-
if (cdPath !== "") consola$1.log(` ${++step}.`,
|
|
70
|
-
consola$1.log(` ${++step}.`,
|
|
69
|
+
if (cdPath !== "") consola$1.log(` ${++step}.`, styleText("cyan", `cd ${cdPath}`));
|
|
70
|
+
consola$1.log(` ${++step}.`, styleText("cyan", `${input.packageManager} install`));
|
|
71
71
|
console.log();
|
|
72
72
|
}
|
|
73
73
|
async function listTemplates() {
|
|
@@ -109,11 +109,11 @@ async function cloneProject({ directory, template }) {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
const TEMPLATE_COLORS = {
|
|
112
|
-
vanilla:
|
|
113
|
-
vue:
|
|
114
|
-
react:
|
|
115
|
-
svelte:
|
|
116
|
-
solid:
|
|
112
|
+
vanilla: "blue",
|
|
113
|
+
vue: "green",
|
|
114
|
+
react: "cyan",
|
|
115
|
+
svelte: "red",
|
|
116
|
+
solid: "blue"
|
|
117
117
|
};
|
|
118
118
|
const TEMPLATE_SORT_WEIGHT = {
|
|
119
119
|
vanilla: 0,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { wxt } from "./wxt.mjs";
|
|
2
|
-
import
|
|
2
|
+
import { styleText } from "node:util";
|
|
3
3
|
import readline from "node:readline";
|
|
4
4
|
//#region src/core/keyboard-shortcuts.ts
|
|
5
5
|
/** Function that creates a keyboard shortcut handler for the extension. */
|
|
@@ -21,7 +21,7 @@ function createKeyboardShortcuts(server) {
|
|
|
21
21
|
rl?.removeListener("line", handleInput);
|
|
22
22
|
},
|
|
23
23
|
printHelp(flags) {
|
|
24
|
-
if (flags.canReopenBrowser) wxt.logger.info(`${
|
|
24
|
+
if (flags.canReopenBrowser) wxt.logger.info(`${styleText("dim", "Press")} ${styleText("bold", "o + enter")} ${styleText("dim", "to reopen the browser")}`);
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
}
|
|
@@ -91,11 +91,16 @@ async function resolveConfig(inlineConfig, command) {
|
|
|
91
91
|
const host = mergedConfig.dev?.server?.host ?? mergedConfig.dev?.server?.hostname ?? "localhost";
|
|
92
92
|
let port = mergedConfig.dev?.server?.port;
|
|
93
93
|
const origin = mergedConfig.dev?.server?.origin ?? mergedConfig.dev?.server?.hostname ?? "localhost";
|
|
94
|
+
const strictPort = mergedConfig.dev?.server?.strictPort ?? false;
|
|
94
95
|
if (port == null || !isFinite(port)) port = await getPort({
|
|
95
96
|
host,
|
|
96
97
|
port: 3e3,
|
|
97
98
|
portRange: [3001, 3010]
|
|
98
99
|
});
|
|
100
|
+
else if (!strictPort) port = await getPort({
|
|
101
|
+
host,
|
|
102
|
+
port
|
|
103
|
+
});
|
|
99
104
|
const originWithProtocolAndPort = [
|
|
100
105
|
origin.match(/^https?:\/\//) ? "" : "http://",
|
|
101
106
|
origin,
|
|
@@ -105,6 +110,7 @@ async function resolveConfig(inlineConfig, command) {
|
|
|
105
110
|
host,
|
|
106
111
|
port,
|
|
107
112
|
origin: originWithProtocolAndPort,
|
|
113
|
+
strictPort,
|
|
108
114
|
watchDebounce: safeStringToNumber(process.env.WXT_WATCH_DEBOUNCE) ?? 800
|
|
109
115
|
};
|
|
110
116
|
}
|
|
@@ -142,6 +148,7 @@ async function resolveConfig(inlineConfig, command) {
|
|
|
142
148
|
userConfigMetadata: userConfigMetadata ?? {},
|
|
143
149
|
alias,
|
|
144
150
|
experimental: defu(mergedConfig.experimental, {}),
|
|
151
|
+
suppressWarnings: mergedConfig.suppressWarnings ?? {},
|
|
145
152
|
dev: {
|
|
146
153
|
server: devServerConfig,
|
|
147
154
|
reloadCommand
|
|
@@ -3,15 +3,15 @@ import { wxt } from "../../wxt.mjs";
|
|
|
3
3
|
import { getPublicFiles } from "../fs.mjs";
|
|
4
4
|
import { copyFile, mkdir, writeFile } from "node:fs/promises";
|
|
5
5
|
import { dirname, resolve } from "path";
|
|
6
|
-
import
|
|
6
|
+
import { styleText } from "node:util";
|
|
7
7
|
//#region src/core/utils/building/build-entrypoints.ts
|
|
8
8
|
async function buildEntrypoints(groups, spinner) {
|
|
9
9
|
const steps = [];
|
|
10
10
|
for (let i = 0; i < groups.length; i++) {
|
|
11
11
|
const group = groups[i];
|
|
12
12
|
const groupNames = toArray(group).map((e) => e.name);
|
|
13
|
-
const groupNameColored = groupNames.join(
|
|
14
|
-
spinner.update({ text:
|
|
13
|
+
const groupNameColored = groupNames.join(styleText("dim", ", "));
|
|
14
|
+
spinner.update({ text: styleText("dim", `[${i + 1}/${groups.length}]`) + ` ${groupNameColored}` });
|
|
15
15
|
try {
|
|
16
16
|
steps.push(await wxt.builder.build(group));
|
|
17
17
|
} catch (err) {
|
|
@@ -5,10 +5,10 @@ import { wxt } from "../../wxt.mjs";
|
|
|
5
5
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
6
6
|
import { glob } from "tinyglobby";
|
|
7
7
|
import { relative, resolve } from "path";
|
|
8
|
+
import { styleText } from "node:util";
|
|
8
9
|
import { parseHTML } from "linkedom";
|
|
9
10
|
import { camelCase } from "scule";
|
|
10
|
-
import
|
|
11
|
-
import { minimatch } from "minimatch";
|
|
11
|
+
import picomatch from "picomatch";
|
|
12
12
|
import JSON5 from "json5";
|
|
13
13
|
//#region src/core/utils/building/find-entrypoints.ts
|
|
14
14
|
/**
|
|
@@ -31,7 +31,7 @@ async function findEntrypoints() {
|
|
|
31
31
|
const entrypointInfos = relativePaths.reduce((results, relativePath) => {
|
|
32
32
|
const inputPath = resolve(wxt.config.entrypointsDir, relativePath);
|
|
33
33
|
const name = getEntrypointName(wxt.config.entrypointsDir, inputPath);
|
|
34
|
-
const matchingGlob = pathGlobs.find((glob) =>
|
|
34
|
+
const matchingGlob = pathGlobs.find((glob) => picomatch(glob)(relativePath));
|
|
35
35
|
if (matchingGlob) {
|
|
36
36
|
const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
|
|
37
37
|
results.push({
|
|
@@ -90,7 +90,7 @@ async function findEntrypoints() {
|
|
|
90
90
|
await wxt.hooks.callHook("entrypoints:resolved", wxt, entrypoints);
|
|
91
91
|
wxt.logger.debug("All entrypoints:", entrypoints);
|
|
92
92
|
const skippedEntrypointNames = entrypoints.filter((item) => item.skipped).map((item) => item.name);
|
|
93
|
-
if (skippedEntrypointNames.length) wxt.logger.warn(["The following entrypoints have been skipped:", ...skippedEntrypointNames.map((item) => `${
|
|
93
|
+
if (skippedEntrypointNames.length) wxt.logger.warn(["The following entrypoints have been skipped:", ...skippedEntrypointNames.map((item) => `${styleText("dim", "-")} ${styleText("cyan", item)}`)].join("\n"));
|
|
94
94
|
return entrypoints;
|
|
95
95
|
}
|
|
96
96
|
/** Returns a map of input paths to the file's options. */
|
|
@@ -157,16 +157,30 @@ async function getPopupEntrypoint(info, options) {
|
|
|
157
157
|
const strictOptions = resolvePerBrowserOptions({
|
|
158
158
|
...perBrowserOptions,
|
|
159
159
|
defaultTitle: title,
|
|
160
|
-
|
|
160
|
+
actionType: type
|
|
161
161
|
}, wxt.config.browser);
|
|
162
|
-
if (strictOptions.
|
|
162
|
+
if (strictOptions.actionType && strictOptions.actionType !== "page_action") strictOptions.actionType = "browser_action";
|
|
163
|
+
const opts = {
|
|
164
|
+
...strictOptions,
|
|
165
|
+
themeIcons
|
|
166
|
+
};
|
|
167
|
+
let _actionType = opts.actionType;
|
|
168
|
+
Object.defineProperty(opts, "actionType", {
|
|
169
|
+
get: () => _actionType,
|
|
170
|
+
set: (v) => _actionType = v,
|
|
171
|
+
enumerable: true,
|
|
172
|
+
configurable: true
|
|
173
|
+
});
|
|
174
|
+
Object.defineProperty(opts, "mv2Key", {
|
|
175
|
+
get: () => _actionType,
|
|
176
|
+
set: (v) => _actionType = v,
|
|
177
|
+
enumerable: true,
|
|
178
|
+
configurable: true
|
|
179
|
+
});
|
|
163
180
|
return {
|
|
164
181
|
type: "popup",
|
|
165
182
|
name: "popup",
|
|
166
|
-
options:
|
|
167
|
-
...strictOptions,
|
|
168
|
-
themeIcons
|
|
169
|
-
},
|
|
183
|
+
options: opts,
|
|
170
184
|
inputPath: info.inputPath,
|
|
171
185
|
outputDir: wxt.config.outDir
|
|
172
186
|
};
|
|
@@ -10,8 +10,8 @@ import { ValidationError, validateEntrypoints } from "../validation.mjs";
|
|
|
10
10
|
import { mkdir, rm } from "node:fs/promises";
|
|
11
11
|
import { glob } from "tinyglobby";
|
|
12
12
|
import { relative } from "node:path";
|
|
13
|
+
import { styleText } from "node:util";
|
|
13
14
|
import { mergeJsonOutputs } from "@aklinker1/rollup-plugin-visualizer";
|
|
14
|
-
import pc from "picocolors";
|
|
15
15
|
import { isCI } from "ci-info";
|
|
16
16
|
//#region src/core/utils/building/internal-build.ts
|
|
17
17
|
/**
|
|
@@ -29,7 +29,7 @@ async function internalBuild() {
|
|
|
29
29
|
await wxt.hooks.callHook("build:before", wxt);
|
|
30
30
|
const verb = wxt.config.command === "serve" ? "Pre-rendering" : "Building";
|
|
31
31
|
const target = `${wxt.config.browser}-mv${wxt.config.manifestVersion}`;
|
|
32
|
-
wxt.logger.info(`${verb} ${
|
|
32
|
+
wxt.logger.info(`${verb} ${styleText("cyan", target)} for ${styleText("cyan", wxt.config.mode)} with ${styleText("green", `${wxt.builder.name} ${wxt.builder.version}`)}`);
|
|
33
33
|
const startTime = Date.now();
|
|
34
34
|
await rm(wxt.config.outDir, {
|
|
35
35
|
recursive: true,
|
|
@@ -50,10 +50,10 @@ async function internalBuild() {
|
|
|
50
50
|
if (wxt.config.analysis.enabled) {
|
|
51
51
|
await combineAnalysisStats();
|
|
52
52
|
const statsPath = relative(wxt.config.root, wxt.config.analysis.outputFile);
|
|
53
|
-
wxt.logger.info(`Analysis complete:\n ${
|
|
54
|
-
if (wxt.config.analysis.open) if (isCI) wxt.logger.debug(`Skipped opening ${
|
|
53
|
+
wxt.logger.info(`Analysis complete:\n ${styleText("gray", "└─")} ${styleText("yellow", statsPath)}`);
|
|
54
|
+
if (wxt.config.analysis.open) if (isCI) wxt.logger.debug(`Skipped opening ${styleText("yellow", statsPath)} in CI`);
|
|
55
55
|
else {
|
|
56
|
-
wxt.logger.info(`Opening ${
|
|
56
|
+
wxt.logger.info(`Opening ${styleText("yellow", statsPath)} in browser...`);
|
|
57
57
|
const { default: open } = await import("open");
|
|
58
58
|
await open(wxt.config.analysis.outputFile);
|
|
59
59
|
}
|
|
@@ -85,8 +85,8 @@ function printValidationResults({ errorCount, errors, warningCount }) {
|
|
|
85
85
|
Array.from(entrypointErrors.entries()).forEach(([entrypoint, errors]) => {
|
|
86
86
|
wxt.logger.log(relative(cwd, entrypoint.inputPath) + "\n");
|
|
87
87
|
errors.forEach((err) => {
|
|
88
|
-
const type = err.type === "error" ?
|
|
89
|
-
const received =
|
|
88
|
+
const type = err.type === "error" ? styleText("red", "ERROR") : styleText("yellow", "WARN");
|
|
89
|
+
const received = styleText("dim", `(received: ${JSON.stringify(err.value)})`);
|
|
90
90
|
wxt.logger.log(` - ${type} ${err.message} ${received}`);
|
|
91
91
|
});
|
|
92
92
|
console.log();
|
package/dist/core/utils/env.mjs
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
|
-
import { config } from "dotenv";
|
|
2
1
|
import { expand } from "dotenv-expand";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { parseEnv } from "node:util";
|
|
3
4
|
//#region src/core/utils/env.ts
|
|
4
5
|
/** Load environment files based on the current mode and browser. */
|
|
5
6
|
function loadEnv(mode, browser) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
]
|
|
7
|
+
const envFiles = [
|
|
8
|
+
`.env`,
|
|
9
|
+
`.env.local`,
|
|
10
|
+
`.env.${mode}`,
|
|
11
|
+
`.env.${mode}.local`,
|
|
12
|
+
`.env.${browser}`,
|
|
13
|
+
`.env.${browser}.local`,
|
|
14
|
+
`.env.${mode}.${browser}`,
|
|
15
|
+
`.env.${mode}.${browser}.local`
|
|
16
|
+
];
|
|
17
|
+
const parsed = Object.fromEntries(envFiles.flatMap((filePath) => {
|
|
18
|
+
if (!existsSync(filePath)) return [];
|
|
19
|
+
try {
|
|
20
|
+
const parsedEnv = parseEnv(readFileSync(filePath, "utf-8"));
|
|
21
|
+
return Object.entries(parsedEnv);
|
|
22
|
+
} catch {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
18
25
|
}));
|
|
26
|
+
expand({ parsed });
|
|
27
|
+
return parsed;
|
|
19
28
|
}
|
|
20
29
|
//#endregion
|
|
21
30
|
export { loadEnv };
|
package/dist/core/utils/i18n.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const predefinedMessages = {
|
|
3
3
|
"@@extension_id": {
|
|
4
4
|
message: "<browser.runtime.id>",
|
|
5
|
-
description: "The extension or app ID; you might use this string to construct URLs for resources inside the extension. Even
|
|
5
|
+
description: "The extension or app ID; you might use this string to construct URLs for resources inside the extension. Even non-localized extensions can use this message.\nNote: You can't use this message in a manifest file."
|
|
6
6
|
},
|
|
7
7
|
"@@ui_locale": {
|
|
8
8
|
message: "<browser.i18n.getUiLocale()>",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { printTable } from "./printTable.mjs";
|
|
2
2
|
import { lstat } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import
|
|
4
|
+
import { styleText } from "node:util";
|
|
5
5
|
import { filesize } from "filesize";
|
|
6
6
|
//#region src/core/utils/log/printFileList.ts
|
|
7
7
|
async function printFileList(log, header, baseDir, files) {
|
|
@@ -9,26 +9,26 @@ async function printFileList(log, header, baseDir, files) {
|
|
|
9
9
|
const fileRows = await Promise.all(files.map(async (file, i) => {
|
|
10
10
|
const parts = [path.relative(process.cwd(), baseDir) + path.sep, path.relative(baseDir, file)];
|
|
11
11
|
const prefix = i === files.length - 1 ? " └─" : " ├─";
|
|
12
|
-
const
|
|
12
|
+
const chunkColor = getChunkColor(file);
|
|
13
13
|
const stats = await lstat(file);
|
|
14
14
|
totalSize += stats.size;
|
|
15
15
|
const size = String(filesize(stats.size));
|
|
16
|
-
return [`${
|
|
16
|
+
return [`${styleText("gray", prefix)} ${styleText("dim", parts[0])}${styleText(chunkColor, parts[1])}`, styleText("dim", size)];
|
|
17
17
|
}));
|
|
18
|
-
fileRows.push([`${
|
|
18
|
+
fileRows.push([`${styleText("cyan", "Σ Total size:")} ${String(filesize(totalSize))}`]);
|
|
19
19
|
printTable(log, header, fileRows);
|
|
20
20
|
}
|
|
21
|
-
const DEFAULT_COLOR =
|
|
21
|
+
const DEFAULT_COLOR = "blue";
|
|
22
22
|
const CHUNK_COLORS = {
|
|
23
|
-
".js.map":
|
|
24
|
-
".cjs.map":
|
|
25
|
-
".mjs.map":
|
|
26
|
-
".html":
|
|
27
|
-
".css":
|
|
28
|
-
".js":
|
|
29
|
-
".cjs":
|
|
30
|
-
".mjs":
|
|
31
|
-
".zip":
|
|
23
|
+
".js.map": "gray",
|
|
24
|
+
".cjs.map": "gray",
|
|
25
|
+
".mjs.map": "gray",
|
|
26
|
+
".html": "green",
|
|
27
|
+
".css": "magenta",
|
|
28
|
+
".js": "cyan",
|
|
29
|
+
".cjs": "cyan",
|
|
30
|
+
".mjs": "cyan",
|
|
31
|
+
".zip": "yellow"
|
|
32
32
|
};
|
|
33
33
|
function getChunkColor(filename) {
|
|
34
34
|
return Object.entries(CHUNK_COLORS).find(([key]) => filename.endsWith(key))?.[1] ?? DEFAULT_COLOR;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { version } from "../../../version.mjs";
|
|
2
2
|
import { consola as consola$1 } from "consola";
|
|
3
|
-
import
|
|
3
|
+
import { styleText } from "node:util";
|
|
4
4
|
//#region src/core/utils/log/printHeader.ts
|
|
5
5
|
function printHeader() {
|
|
6
|
-
consola$1.log(`\n${
|
|
6
|
+
consola$1.log(`\n${styleText("gray", "WXT")} ${styleText(["bold", "grey"], version)}`);
|
|
7
7
|
}
|
|
8
8
|
//#endregion
|
|
9
9
|
export { printHeader };
|
|
@@ -5,6 +5,7 @@ import { writeFileIfDifferent } from "./fs.mjs";
|
|
|
5
5
|
import { ContentSecurityPolicy } from "./content-security-policy.mjs";
|
|
6
6
|
import { hashContentScriptOptions, mapWxtOptionsToContentScript } from "./content-scripts.mjs";
|
|
7
7
|
import { getPackageJson } from "./package.mjs";
|
|
8
|
+
import { addDiscoveredThemeIcons } from "./theme-icons.mjs";
|
|
8
9
|
import { mkdir } from "node:fs/promises";
|
|
9
10
|
import { resolve } from "path";
|
|
10
11
|
import defu from "defu";
|
|
@@ -54,7 +55,9 @@ async function generateManifest(allEntrypoints, buildOutput) {
|
|
|
54
55
|
}
|
|
55
56
|
manifest.version = version;
|
|
56
57
|
manifest.version_name = wxt.config.browser === "firefox" || versionName === version ? void 0 : versionName;
|
|
58
|
+
if (wxt.config.browser === "firefox" && !userManifest.browser_specific_settings?.gecko?.data_collection_permissions && !wxt.config.suppressWarnings?.firefoxDataCollection) wxt.logger.warn("Firefox requires `data_collection_permissions` for new extensions from November 3, 2025. Existing extensions are exempt for now.\nFor more details, see: https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/\nTo suppress this warning, set `suppressWarnings.firefoxDataCollection` to `true` in your wxt config.\n");
|
|
57
59
|
addEntrypoints(manifest, entrypoints, buildOutput);
|
|
60
|
+
if (wxt.config.browser === "firefox") addDiscoveredThemeIcons(manifest, buildOutput);
|
|
58
61
|
if (wxt.config.command === "serve") addDevModeCsp(manifest);
|
|
59
62
|
if (wxt.config.command === "serve") addDevModePermissions(manifest);
|
|
60
63
|
await wxt.hooks.callHook("build:manifestGenerated", wxt, manifest);
|
|
@@ -136,25 +139,18 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
|
|
|
136
139
|
if (popup.options.browserStyle) options.browser_style = popup.options.browserStyle;
|
|
137
140
|
if (popup.options.defaultArea) options.default_area = popup.options.defaultArea;
|
|
138
141
|
if (popup.options.themeIcons) options.theme_icons = popup.options.themeIcons;
|
|
139
|
-
|
|
140
|
-
|
|
142
|
+
const actionKey = manifest.manifest_version === 2 ? popup.options.actionType ?? "browser_action" : wxt.config.browser === "firefox" ? popup.options.actionType ?? "action" : "action";
|
|
143
|
+
manifest[actionKey] = {
|
|
144
|
+
...manifest[actionKey],
|
|
141
145
|
...options,
|
|
142
146
|
default_popup
|
|
143
147
|
};
|
|
144
|
-
else {
|
|
145
|
-
const key = popup.options.mv2Key ?? "browser_action";
|
|
146
|
-
manifest[key] = {
|
|
147
|
-
...manifest[key],
|
|
148
|
-
...options,
|
|
149
|
-
default_popup
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
148
|
}
|
|
153
149
|
if (devtools) manifest.devtools_page = getEntrypointBundlePath(devtools, wxt.config.outDir, ".html");
|
|
154
150
|
if (options) {
|
|
155
151
|
const page = getEntrypointBundlePath(options, wxt.config.outDir, ".html");
|
|
156
152
|
manifest.options_ui = {
|
|
157
|
-
open_in_tab: options.options.openInTab,
|
|
153
|
+
open_in_tab: options.options.openInTab ?? false,
|
|
158
154
|
browser_style: wxt.config.browser === "firefox" ? options.options.browserStyle : void 0,
|
|
159
155
|
chrome_style: wxt.config.browser !== "firefox" ? options.options.chromeStyle : void 0,
|
|
160
156
|
page
|
|
@@ -363,13 +359,15 @@ function stripKeys(manifest) {
|
|
|
363
359
|
if (wxt.config.manifestVersion === 2) {
|
|
364
360
|
keysToRemove.push(...mv3OnlyKeys);
|
|
365
361
|
if (wxt.config.browser === "firefox") keysToRemove.push(...firefoxMv3OnlyKeys);
|
|
366
|
-
} else
|
|
362
|
+
} else {
|
|
363
|
+
keysToRemove.push(...mv2OnlyKeys);
|
|
364
|
+
if (wxt.config.browser !== "firefox") keysToRemove.push(...chromeMv2OnlyKeys);
|
|
365
|
+
}
|
|
367
366
|
keysToRemove.forEach((key) => {
|
|
368
367
|
delete manifest[key];
|
|
369
368
|
});
|
|
370
369
|
}
|
|
371
370
|
const mv2OnlyKeys = [
|
|
372
|
-
"page_action",
|
|
373
371
|
"browser_action",
|
|
374
372
|
"automation",
|
|
375
373
|
"content_capabilities",
|
|
@@ -393,6 +391,7 @@ const mv3OnlyKeys = [
|
|
|
393
391
|
"optional_host_permissions",
|
|
394
392
|
"side_panel"
|
|
395
393
|
];
|
|
394
|
+
const chromeMv2OnlyKeys = ["page_action"];
|
|
396
395
|
const firefoxMv3OnlyKeys = ["host_permissions"];
|
|
397
396
|
const DEFAULT_MV3_EXTENSION_PAGES_CSP = "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';";
|
|
398
397
|
const DEFAULT_MV3_SANDBOX_CSP = "sandbox allow-scripts allow-forms allow-popups allow-modals; script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self';";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import picomatch from "picomatch";
|
|
2
|
+
//#region src/core/utils/picomatch-multiple.ts
|
|
3
|
+
/**
|
|
4
|
+
* Run [`picomatch`](https://npmjs.com/package/picomatch) against multiple
|
|
5
|
+
* patterns.
|
|
6
|
+
*
|
|
7
|
+
* Supports negated patterns, the order does not matter. If your `search` string
|
|
8
|
+
* matches any of the negative patterns, it will return `false`.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* picomatchMultiple('a.json', ['*.json', '!b.json']); // => true
|
|
13
|
+
* picomatchMultiple('b.json', ['*.json', '!b.json']); // => false
|
|
14
|
+
* ```;
|
|
15
|
+
*/
|
|
16
|
+
function picomatchMultiple(search, patterns, options) {
|
|
17
|
+
if (patterns == null) return false;
|
|
18
|
+
const negatePatterns = [];
|
|
19
|
+
const positivePatterns = [];
|
|
20
|
+
for (const pattern of patterns) if (pattern[0] === "!") negatePatterns.push(pattern.slice(1));
|
|
21
|
+
else positivePatterns.push(pattern);
|
|
22
|
+
if (negatePatterns.some((negatePattern) => picomatch(negatePattern, options)(search))) return false;
|
|
23
|
+
return positivePatterns.some((positivePattern) => picomatch(positivePattern, options)(search));
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { picomatchMultiple };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { wxt } from "../wxt.mjs";
|
|
2
2
|
import { relative } from "node:path";
|
|
3
|
-
import
|
|
3
|
+
import { styleText } from "node:util";
|
|
4
4
|
//#region src/core/utils/syntax-errors.ts
|
|
5
5
|
function isBabelSyntaxError(error) {
|
|
6
6
|
return error instanceof SyntaxError && error.code === "BABEL_PARSER_SYNTAX_ERROR";
|
|
@@ -9,7 +9,7 @@ function logBabelSyntaxError(error) {
|
|
|
9
9
|
let filename = relative(wxt.config.root, error.id);
|
|
10
10
|
if (filename.startsWith("..")) filename = error.id;
|
|
11
11
|
let message = error.message.replace(/\(\d+:\d+\)$/, `(${filename}:${error.loc.line}:${error.loc.column + 1})`);
|
|
12
|
-
if (error.frame) message += "\n\n" +
|
|
12
|
+
if (error.frame) message += "\n\n" + styleText("red", error.frame);
|
|
13
13
|
wxt.logger.error(message);
|
|
14
14
|
}
|
|
15
15
|
//#endregion
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { normalizePath } from "./paths.mjs";
|
|
2
|
+
import { wxt } from "../wxt.mjs";
|
|
3
|
+
//#region src/core/utils/theme-icons.ts
|
|
4
|
+
/**
|
|
5
|
+
* Firefox only.
|
|
6
|
+
*
|
|
7
|
+
* If the manifest has an `action` (MV3) or `browser_action` (MV2) and the user
|
|
8
|
+
* has not already set `theme_icons` on it, discover light/dark icon pairs from
|
|
9
|
+
* the public assets and attach them.
|
|
10
|
+
*/
|
|
11
|
+
function addDiscoveredThemeIcons(manifest, buildOutput) {
|
|
12
|
+
const action = manifest.action ?? manifest.browser_action;
|
|
13
|
+
if (action == null) return;
|
|
14
|
+
if (action.theme_icons != null) return;
|
|
15
|
+
const themeIcons = discoverThemeIcons(buildOutput);
|
|
16
|
+
if (themeIcons == null) return;
|
|
17
|
+
action.theme_icons = themeIcons;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Scan `publicAssets` for paired `-light`/`-dark` icon files and return the
|
|
21
|
+
* sizes where both variants exist, sorted ascending. Returns `undefined` if no
|
|
22
|
+
* complete pairs are found so callers can short-circuit.
|
|
23
|
+
*/
|
|
24
|
+
function discoverThemeIcons(buildOutput) {
|
|
25
|
+
const bySize = /* @__PURE__ */ new Map();
|
|
26
|
+
for (const asset of buildOutput.publicAssets) for (const regex of themeIconRegex) {
|
|
27
|
+
const match = asset.fileName.match(regex);
|
|
28
|
+
if (match?.groups == null) continue;
|
|
29
|
+
const size = Number(match.groups.size);
|
|
30
|
+
const variant = match.groups.variant;
|
|
31
|
+
const entry = bySize.get(size) ?? {};
|
|
32
|
+
const incoming = normalizePath(asset.fileName);
|
|
33
|
+
const existing = entry[variant];
|
|
34
|
+
if (existing != null && existing !== incoming) {
|
|
35
|
+
wxt.logger.warn(`Multiple theme icon files matched size ${size} variant "${variant}": keeping "${existing}", ignoring "${incoming}". Use a single naming pattern per (size, variant).`);
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
entry[variant] = incoming;
|
|
39
|
+
bySize.set(size, entry);
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
const pairs = [];
|
|
43
|
+
for (const [size, entry] of bySize) {
|
|
44
|
+
if (entry.light != null && entry.dark != null) {
|
|
45
|
+
pairs.push({
|
|
46
|
+
light: entry.light,
|
|
47
|
+
dark: entry.dark,
|
|
48
|
+
size
|
|
49
|
+
});
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const present = entry.light != null ? "light" : "dark";
|
|
53
|
+
const missing = entry.light != null ? "dark" : "light";
|
|
54
|
+
const file = entry.light ?? entry.dark;
|
|
55
|
+
wxt.logger.warn(`Skipping theme icon size ${size}: found ${present} variant ("${file}") but no matching ${missing} variant. Add the missing file to include this size in theme_icons.`);
|
|
56
|
+
}
|
|
57
|
+
pairs.sort((a, b) => a.size - b.size);
|
|
58
|
+
return pairs.length > 0 ? pairs : void 0;
|
|
59
|
+
}
|
|
60
|
+
const themeIconRegex = [
|
|
61
|
+
/^icon-(?<variant>light|dark)-(?<size>[0-9]+)\.png$/,
|
|
62
|
+
/^icon-(?<variant>light|dark)-(?<size>[0-9]+)x[0-9]+\.png$/,
|
|
63
|
+
/^icon-(?<size>[0-9]+)-(?<variant>light|dark)\.png$/,
|
|
64
|
+
/^icon-(?<size>[0-9]+)x[0-9]+-(?<variant>light|dark)\.png$/,
|
|
65
|
+
/^icons?[/\\](?<variant>light|dark)-(?<size>[0-9]+)\.png$/,
|
|
66
|
+
/^icons?[/\\](?<variant>light|dark)-(?<size>[0-9]+)x[0-9]+\.png$/,
|
|
67
|
+
/^icons?[/\\](?<size>[0-9]+)-(?<variant>light|dark)\.png$/,
|
|
68
|
+
/^icons?[/\\](?<size>[0-9]+)x[0-9]+-(?<variant>light|dark)\.png$/
|
|
69
|
+
];
|
|
70
|
+
//#endregion
|
|
71
|
+
export { addDiscoveredThemeIcons };
|
|
@@ -137,7 +137,7 @@ function removeSideEffectImports(mod) {
|
|
|
137
137
|
}
|
|
138
138
|
/**
|
|
139
139
|
* Util to get the AST as a simple JSON object, stripping out large objects and
|
|
140
|
-
* file locations to keep it
|
|
140
|
+
* file locations to keep it readable.
|
|
141
141
|
*/
|
|
142
142
|
function getSimpleAstJson(ast) {
|
|
143
143
|
if (!ast) return ast;
|
package/dist/core/zip.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { normalizePath } from "./utils/paths.mjs";
|
|
2
2
|
import "./utils/index.mjs";
|
|
3
|
-
import { formatDuration } from "./utils/time.mjs";
|
|
4
3
|
import { safeFilename } from "./utils/strings.mjs";
|
|
4
|
+
import { formatDuration } from "./utils/time.mjs";
|
|
5
5
|
import { registerWxt, wxt } from "./wxt.mjs";
|
|
6
6
|
import { findEntrypoints } from "./utils/building/find-entrypoints.mjs";
|
|
7
7
|
import { printFileList } from "./utils/log/printFileList.mjs";
|
|
@@ -9,7 +9,7 @@ import "./utils/log/index.mjs";
|
|
|
9
9
|
import { getPackageJson } from "./utils/package.mjs";
|
|
10
10
|
import { internalBuild } from "./utils/building/internal-build.mjs";
|
|
11
11
|
import "./utils/building/index.mjs";
|
|
12
|
-
import {
|
|
12
|
+
import { picomatchMultiple } from "./utils/picomatch-multiple.mjs";
|
|
13
13
|
import { mkdir, readFile } from "node:fs/promises";
|
|
14
14
|
import { glob } from "tinyglobby";
|
|
15
15
|
import path from "node:path";
|
|
@@ -69,7 +69,7 @@ async function zipDir(directory, outputPath, options) {
|
|
|
69
69
|
onlyFiles: true,
|
|
70
70
|
expandDirectories: false
|
|
71
71
|
})).filter((relativePath) => {
|
|
72
|
-
return
|
|
72
|
+
return picomatchMultiple(relativePath, options?.include) || !picomatchMultiple(relativePath, options?.exclude);
|
|
73
73
|
}), ...(options?.additionalFiles ?? []).map((file) => path.relative(directory, file))];
|
|
74
74
|
for (const file of filesToZip) {
|
|
75
75
|
const absolutePath = path.resolve(directory, file);
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BaseScriptEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UnlistedScriptEntrypoint, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig } from "./types.mjs";
|
|
1
|
+
import { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BaseScriptEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FirefoxDataCollectionPermissions, FirefoxDataCollectionType, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, PublicPathEntry, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UnlistedScriptEntrypoint, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig } from "./types.mjs";
|
|
2
2
|
import { build } from "./core/build.mjs";
|
|
3
3
|
import { clean } from "./core/clean.mjs";
|
|
4
4
|
import { defineConfig } from "./core/define-config.mjs";
|
|
@@ -9,4 +9,4 @@ import { prepare } from "./core/prepare.mjs";
|
|
|
9
9
|
import { zip } from "./core/zip.mjs";
|
|
10
10
|
import { normalizePath } from "./core/utils/paths.mjs";
|
|
11
11
|
import { version } from "./version.mjs";
|
|
12
|
-
export { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BaseScriptEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UnlistedScriptEntrypoint, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig, build, clean, createServer, defineConfig, defineRunnerConfig, defineWebExtConfig, initialize, normalizePath, prepare, version, zip };
|
|
12
|
+
export { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BaseScriptEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FirefoxDataCollectionPermissions, FirefoxDataCollectionType, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, PublicPathEntry, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UnlistedScriptEntrypoint, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig, build, clean, createServer, defineConfig, defineRunnerConfig, defineWebExtConfig, initialize, normalizePath, prepare, version, zip };
|
package/dist/types.d.mts
CHANGED
|
@@ -164,6 +164,25 @@ interface InlineConfig {
|
|
|
164
164
|
* function that returns an object or promise.
|
|
165
165
|
*/
|
|
166
166
|
manifest?: UserManifest | Promise<UserManifest> | UserManifestFn;
|
|
167
|
+
/**
|
|
168
|
+
* Suppress specific warnings during the build process.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* export default defineConfig({
|
|
173
|
+
* suppressWarnings: {
|
|
174
|
+
* firefoxDataCollection: true,
|
|
175
|
+
* },
|
|
176
|
+
* })
|
|
177
|
+
* ```;
|
|
178
|
+
*/
|
|
179
|
+
suppressWarnings?: {
|
|
180
|
+
/**
|
|
181
|
+
* Suppress warnings for:
|
|
182
|
+
* https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent
|
|
183
|
+
*/
|
|
184
|
+
firefoxDataCollection?: boolean;
|
|
185
|
+
};
|
|
167
186
|
/**
|
|
168
187
|
* Configure browser startup. Options set here can be overridden in a
|
|
169
188
|
* `web-ext.config.ts` file.
|
|
@@ -233,7 +252,7 @@ interface InlineConfig {
|
|
|
233
252
|
*/
|
|
234
253
|
sourcesRoot?: string;
|
|
235
254
|
/**
|
|
236
|
-
* [
|
|
255
|
+
* [Picomatch](https://www.npmjs.com/package/picomatch) patterns of files to
|
|
237
256
|
* include when creating a ZIP of all your source code for Firefox. Patterns
|
|
238
257
|
* are relative to your `config.zip.sourcesRoot`.
|
|
239
258
|
*
|
|
@@ -247,7 +266,7 @@ interface InlineConfig {
|
|
|
247
266
|
*/
|
|
248
267
|
includeSources?: string[];
|
|
249
268
|
/**
|
|
250
|
-
* [
|
|
269
|
+
* [Picomatch](https://www.npmjs.com/package/picomatch) patterns of files to
|
|
251
270
|
* exclude when creating a ZIP of all your source code for Firefox. Patterns
|
|
252
271
|
* are relative to your `config.zip.sourcesRoot`.
|
|
253
272
|
*
|
|
@@ -260,7 +279,7 @@ interface InlineConfig {
|
|
|
260
279
|
*/
|
|
261
280
|
excludeSources?: string[];
|
|
262
281
|
/**
|
|
263
|
-
* [
|
|
282
|
+
* [Picomatch](https://www.npmjs.com/package/picomatch) patterns of files to
|
|
264
283
|
* exclude when zipping the extension.
|
|
265
284
|
*
|
|
266
285
|
* @example
|
|
@@ -389,6 +408,14 @@ interface InlineConfig {
|
|
|
389
408
|
* @default 'http://localhost:3000'
|
|
390
409
|
*/
|
|
391
410
|
origin?: string;
|
|
411
|
+
/**
|
|
412
|
+
* Whether the dev server should fail if the specified port is already in
|
|
413
|
+
* use. When `false` and a `port` is specified, the next available port
|
|
414
|
+
* will be used instead of throwing an error.
|
|
415
|
+
*
|
|
416
|
+
* @default false
|
|
417
|
+
*/
|
|
418
|
+
strictPort?: boolean;
|
|
392
419
|
/**
|
|
393
420
|
* Hostname to run the dev server on.
|
|
394
421
|
*
|
|
@@ -430,8 +457,8 @@ interface InlineConfig {
|
|
|
430
457
|
* set in WXT's config instead of Vite's.
|
|
431
458
|
*
|
|
432
459
|
* This is a function because any vite plugins added need to be recreated for
|
|
433
|
-
* each individual build step,
|
|
434
|
-
* fail when reused.
|
|
460
|
+
* each individual build step, in case they have internal state causing them
|
|
461
|
+
* to fail when reused.
|
|
435
462
|
*/
|
|
436
463
|
vite?: (env: ConfigEnv) => WxtViteConfig | Promise<WxtViteConfig>;
|
|
437
464
|
}
|
|
@@ -703,7 +730,15 @@ interface ThemeIcon {
|
|
|
703
730
|
size: number;
|
|
704
731
|
}
|
|
705
732
|
interface PopupEntrypointOptions extends BaseEntrypointOptions {
|
|
706
|
-
/**
|
|
733
|
+
/**
|
|
734
|
+
* The type of action to use in the manifest.
|
|
735
|
+
*
|
|
736
|
+
* In MV2, defaults to `"browser_action"`. In MV3, `"browser_action"` is
|
|
737
|
+
* converted to `"action"`, while `"page_action"` is kept as-is (Firefox MV3
|
|
738
|
+
* only).
|
|
739
|
+
*/
|
|
740
|
+
actionType?: PerBrowserOption<'browser_action' | 'page_action'>;
|
|
741
|
+
/** @deprecated Use `actionType` instead. */
|
|
707
742
|
mv2Key?: PerBrowserOption<'browser_action' | 'page_action'>;
|
|
708
743
|
defaultIcon?: Record<string, string>;
|
|
709
744
|
defaultTitle?: PerBrowserOption<string>;
|
|
@@ -872,16 +907,42 @@ type PerBrowserMap<T> = {
|
|
|
872
907
|
* `PerBrowserOption`, like `defaultIcon`.
|
|
873
908
|
*/
|
|
874
909
|
type ResolvedPerBrowserOptions<T, TOmitted extends keyof T = never> = { [key in keyof Omit<T, TOmitted>]: T[key] extends PerBrowserOption<infer U> ? U : T[key] } & { [key in TOmitted]: T[key] };
|
|
910
|
+
/**
|
|
911
|
+
* Firefox data collection permission types for personal data. See:
|
|
912
|
+
* https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/#specifying-data-types
|
|
913
|
+
*/
|
|
914
|
+
type FirefoxDataCollectionType = 'locationInfo' | 'browsingActivity' | 'websiteContent' | 'websiteActivity' | 'searchTerms' | 'bookmarksInfo' | 'healthInfo' | 'contactInfo' | 'socialInfo' | (string & {});
|
|
915
|
+
/**
|
|
916
|
+
* Firefox data collection permissions configuration. See:
|
|
917
|
+
* https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/#specifying-data-types
|
|
918
|
+
*/
|
|
919
|
+
interface FirefoxDataCollectionPermissions {
|
|
920
|
+
/**
|
|
921
|
+
* Required data collection permissions. Users must opt in to use the
|
|
922
|
+
* extension. Can include personal data types or "none" to explicitly indicate
|
|
923
|
+
* no data collection.
|
|
924
|
+
*/
|
|
925
|
+
required?: Array<FirefoxDataCollectionType | 'none'>;
|
|
926
|
+
/**
|
|
927
|
+
* Optional data collection permissions. Users can opt in after installation.
|
|
928
|
+
* Can include personal data types or "technicalAndInteraction" (which can
|
|
929
|
+
* only be optional).
|
|
930
|
+
*/
|
|
931
|
+
optional?: Array<FirefoxDataCollectionType | 'technicalAndInteraction'>;
|
|
932
|
+
}
|
|
875
933
|
/**
|
|
876
934
|
* Manifest customization available in the `wxt.config.ts` file. You cannot
|
|
877
935
|
* configure entrypoints here, they are configured inline.
|
|
878
936
|
*/
|
|
879
937
|
type UserManifest = { [key in keyof Browser.runtime.ManifestV3 as key extends 'action' | 'background' | 'chrome_url_overrides' | 'devtools_page' | 'manifest_version' | 'options_page' | 'options_ui' | 'permissions' | 'sandbox' | 'web_accessible_resources' ? never : key]?: Browser.runtime.ManifestV3[key] } & {
|
|
880
938
|
action?: Browser.runtime.ManifestV3['action'] & {
|
|
881
|
-
|
|
939
|
+
default_area?: 'navbar' | 'menupanel' | 'tabstrip' | 'personaltoolbar';
|
|
940
|
+
theme_icons?: ThemeIcon[];
|
|
882
941
|
};
|
|
883
942
|
browser_action?: Browser.runtime.ManifestV2['browser_action'] & {
|
|
884
943
|
browser_style?: boolean;
|
|
944
|
+
default_area?: 'navbar' | 'menupanel' | 'tabstrip' | 'personaltoolbar';
|
|
945
|
+
theme_icons?: ThemeIcon[];
|
|
885
946
|
};
|
|
886
947
|
page_action?: Browser.runtime.ManifestV2['page_action'] & {
|
|
887
948
|
browser_style?: boolean;
|
|
@@ -892,6 +953,11 @@ type UserManifest = { [key in keyof Browser.runtime.ManifestV3 as key extends 'a
|
|
|
892
953
|
strict_min_version?: string;
|
|
893
954
|
strict_max_version?: string;
|
|
894
955
|
update_url?: string;
|
|
956
|
+
/**
|
|
957
|
+
* Firefox data collection permissions configuration. See:
|
|
958
|
+
* https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/#specifying-data-types
|
|
959
|
+
*/
|
|
960
|
+
data_collection_permissions?: FirefoxDataCollectionPermissions;
|
|
895
961
|
};
|
|
896
962
|
gecko_android?: {
|
|
897
963
|
strict_min_version?: string;
|
|
@@ -1080,14 +1146,18 @@ interface WxtHooks {
|
|
|
1080
1146
|
*
|
|
1081
1147
|
* @example
|
|
1082
1148
|
* wxt.hooks.hook('prepare:publicPaths', (wxt, paths) => {
|
|
1083
|
-
* paths.push('
|
|
1149
|
+
* paths.push('icons/128.png');
|
|
1150
|
+
* paths.push({
|
|
1151
|
+
* type: 'templateLiteral',
|
|
1152
|
+
* path: '_favicon/?${string}',
|
|
1153
|
+
* });
|
|
1084
1154
|
* });
|
|
1085
1155
|
*
|
|
1086
1156
|
* @param wxt The configured WXT object
|
|
1087
1157
|
* @param paths This list of paths TypeScript allows `browser.runtime.getURL`
|
|
1088
1158
|
* to be called with.
|
|
1089
1159
|
*/
|
|
1090
|
-
'prepare:publicPaths': (wxt: Wxt, paths:
|
|
1160
|
+
'prepare:publicPaths': (wxt: Wxt, paths: PublicPathEntry[]) => HookResult;
|
|
1091
1161
|
/**
|
|
1092
1162
|
* Called before the build is started in both dev mode and build mode.
|
|
1093
1163
|
*
|
|
@@ -1296,11 +1366,16 @@ interface ResolvedConfig$1 {
|
|
|
1296
1366
|
/** Import aliases to absolute paths. */
|
|
1297
1367
|
alias: Record<string, string>;
|
|
1298
1368
|
experimental: {};
|
|
1369
|
+
/** List of warning identifiers to suppress during the build process. */
|
|
1370
|
+
suppressWarnings: {
|
|
1371
|
+
firefoxDataCollection?: boolean;
|
|
1372
|
+
};
|
|
1299
1373
|
dev: {
|
|
1300
1374
|
/** Only defined during dev command */server?: {
|
|
1301
1375
|
host: string;
|
|
1302
1376
|
port: number;
|
|
1303
1377
|
origin: string;
|
|
1378
|
+
strictPort: boolean;
|
|
1304
1379
|
/**
|
|
1305
1380
|
* The milliseconds to debounce when a file is saved before reloading. The
|
|
1306
1381
|
* only way to set this option is to set the `WXT_WATCH_DEBOUNCE`
|
|
@@ -1490,6 +1565,10 @@ interface GeneratedPublicFile extends ResolvedBasePublicFile {
|
|
|
1490
1565
|
/** Text to write to the file. */
|
|
1491
1566
|
contents: string;
|
|
1492
1567
|
}
|
|
1568
|
+
type PublicPathEntry = string | {
|
|
1569
|
+
type: 'string' | 'templateLiteral';
|
|
1570
|
+
path: string;
|
|
1571
|
+
};
|
|
1493
1572
|
type WxtPlugin = () => void;
|
|
1494
1573
|
type WxtDirEntry = WxtDirTypeReferenceEntry | WxtDirFileEntry;
|
|
1495
1574
|
/**
|
|
@@ -1517,4 +1596,4 @@ interface WxtDirFileEntry {
|
|
|
1517
1596
|
tsReference?: boolean;
|
|
1518
1597
|
}
|
|
1519
1598
|
//#endregion
|
|
1520
|
-
export { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BaseScriptEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig$1 as ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UnlistedScriptEntrypoint, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig };
|
|
1599
|
+
export { BackgroundDefinition, BackgroundEntrypoint, BackgroundEntrypointOptions, BaseContentScriptEntrypointOptions, BaseEntrypoint, BaseEntrypointOptions, BaseScriptEntrypointOptions, BuildOutput, BuildStepOutput, ConfigEnv, ContentScriptDefinition, ContentScriptEntrypoint, CopiedPublicFile, Dependency, Entrypoint, EntrypointGroup, EntrypointInfo, EslintGlobalsPropValue, Eslintrc, ExtensionRunner, ExtensionRunnerConfig, FirefoxDataCollectionPermissions, FirefoxDataCollectionType, FsCache, GeneratedPublicFile, GenericEntrypoint, HookResult, InlineConfig, IsolatedWorldContentScriptDefinition, IsolatedWorldContentScriptEntrypointOptions, Logger, MainWorldContentScriptDefinition, MainWorldContentScriptEntrypointOptions, OnContentScriptStopped, OptionsEntrypoint, OptionsEntrypointOptions, OutputAsset, OutputChunk, OutputFile, PerBrowserMap, PerBrowserOption, PopupEntrypoint, PopupEntrypointOptions, PublicPathEntry, ReloadContentScriptPayload, ResolvedBasePublicFile, ResolvedConfig$1 as ResolvedConfig, ResolvedEslintrc, ResolvedPerBrowserOptions, ResolvedPublicFile, ServerInfo, SidepanelEntrypoint, SidepanelEntrypointOptions, TargetBrowser, TargetManifestVersion, ThemeIcon, UnlistedScriptDefinition, UnlistedScriptEntrypoint, UserConfig, UserManifest, UserManifestFn, WebExtConfig, Wxt, WxtBuilder, WxtBuilderServer, WxtCommand, WxtDevServer, WxtDirEntry, WxtDirFileEntry, WxtDirTypeReferenceEntry, WxtHooks, WxtModule, WxtModuleOptions, WxtModuleSetup, WxtModuleWithMetadata, WxtPackageManager, WxtPlugin, WxtResolvedUnimportOptions, WxtUnimportOptions, WxtViteConfig };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ContentScriptContext } from "../content-script-context.mjs";
|
|
2
2
|
import { ContentScriptUi, ContentScriptUiOptions } from "./types.mjs";
|
|
3
|
-
import * as wxt_browser0 from "wxt/browser";
|
|
3
|
+
import * as _$wxt_browser0 from "wxt/browser";
|
|
4
4
|
|
|
5
5
|
//#region src/utils/content-script-ui/iframe.d.ts
|
|
6
6
|
/**
|
|
@@ -20,7 +20,7 @@ type IframeContentScriptUiOptions<TMounted> = ContentScriptUiOptions<TMounted> &
|
|
|
20
20
|
* The path to the HTML page that will be shown in the iframe. This string
|
|
21
21
|
* is passed into `browser.runtime.getURL`.
|
|
22
22
|
*/
|
|
23
|
-
page: wxt_browser0.HtmlPublicPath;
|
|
23
|
+
page: _$wxt_browser0.HtmlPublicPath;
|
|
24
24
|
/**
|
|
25
25
|
* Callback executed when mounting the UI. Use this function to customize
|
|
26
26
|
* the iframe or wrapper element's appearance. It is called every time
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as wxt_browser0 from "wxt/browser";
|
|
1
|
+
import * as _$wxt_browser0 from "wxt/browser";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/inject-script.d.ts
|
|
4
|
-
type ScriptPublicPath = Extract<wxt_browser0.PublicPath, `${string}.js`>;
|
|
4
|
+
type ScriptPublicPath = Extract<_$wxt_browser0.PublicPath, `${string}.js`>;
|
|
5
5
|
/**
|
|
6
6
|
* This function can only be called inside content scripts.
|
|
7
7
|
*
|
|
@@ -15,9 +15,10 @@ import { browser } from "wxt/browser";
|
|
|
15
15
|
async function injectScript(path, options) {
|
|
16
16
|
const url = browser.runtime.getURL(path);
|
|
17
17
|
const script = document.createElement("script");
|
|
18
|
-
|
|
18
|
+
const isManifestV2 = browser.runtime.getManifest().manifest_version === 2;
|
|
19
|
+
if (isManifestV2) script.text = await fetch(url).then((res) => res.text());
|
|
19
20
|
else script.src = url;
|
|
20
|
-
const loadedPromise = makeLoadedPromise(script);
|
|
21
|
+
const loadedPromise = isManifestV2 ? void 0 : makeLoadedPromise(script);
|
|
21
22
|
await options?.modifyScript?.(script);
|
|
22
23
|
(document.head ?? document.documentElement).append(script);
|
|
23
24
|
if (!options?.keepInDom) script.remove();
|
package/dist/version.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wxt",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.20.
|
|
4
|
+
"version": "0.20.22",
|
|
5
5
|
"description": "⚡ Next-gen Web Extension Framework",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"wxt": "bun run src/cli/index.ts",
|
|
9
|
+
"build": "buildc -- bun run tsdown --config-loader unrun",
|
|
10
|
+
"check": "bun run build && bun run --sequential 'check:*'",
|
|
11
|
+
"check:default": "check",
|
|
12
|
+
"check:tsc-virtual": "tsc --noEmit -p src/virtual",
|
|
13
|
+
"test": "buildc --deps-only -- vitest",
|
|
14
|
+
"test:coverage": "bun run test run --coverage",
|
|
15
|
+
"sync-releases": "pnpx changelogen@latest gh release",
|
|
16
|
+
"prepack": "bun run build"
|
|
17
|
+
},
|
|
7
18
|
"dependencies": {
|
|
8
19
|
"@1natsu/wait-element": "^4.1.2",
|
|
9
20
|
"@aklinker1/rollup-plugin-visualizer": "5.12.0",
|
|
10
21
|
"@webext-core/fake-browser": "^1.3.4",
|
|
11
22
|
"@webext-core/isolated-element": "^1.1.3",
|
|
12
23
|
"@webext-core/match-patterns": "^1.0.3",
|
|
24
|
+
"@wxt-dev/browser": "^0.1.40",
|
|
13
25
|
"@wxt-dev/storage": "^1.0.0",
|
|
14
26
|
"async-mutex": "^0.5.0",
|
|
15
27
|
"c12": "^3.3.3",
|
|
@@ -18,20 +30,18 @@
|
|
|
18
30
|
"ci-info": "^4.4.0",
|
|
19
31
|
"consola": "^3.4.2",
|
|
20
32
|
"defu": "^6.1.4",
|
|
21
|
-
"dotenv": "^17.3.1",
|
|
22
33
|
"dotenv-expand": "^12.0.3",
|
|
23
34
|
"esbuild": "^0.27.1",
|
|
24
|
-
"filesize": "^11.0.
|
|
35
|
+
"filesize": "^11.0.15",
|
|
25
36
|
"get-port-please": "^3.2.0",
|
|
26
37
|
"giget": "^1.2.3 || ^2.0.0 || ^3.0.0",
|
|
27
|
-
"hookable": "^6.0
|
|
38
|
+
"hookable": "^6.1.0",
|
|
28
39
|
"import-meta-resolve": "^4.2.0",
|
|
29
40
|
"is-wsl": "^3.1.1",
|
|
30
41
|
"json5": "^2.2.3",
|
|
31
42
|
"jszip": "^3.10.1",
|
|
32
43
|
"linkedom": "^0.18.12",
|
|
33
44
|
"magicast": "^0.5.2",
|
|
34
|
-
"minimatch": "^10.2.4",
|
|
35
45
|
"nano-spawn": "^2.0.0",
|
|
36
46
|
"nanospinner": "^1.2.2",
|
|
37
47
|
"normalize-path": "^3.0.0",
|
|
@@ -39,7 +49,7 @@
|
|
|
39
49
|
"ohash": "^2.0.11",
|
|
40
50
|
"open": "^11.0.0",
|
|
41
51
|
"perfect-debounce": "^2.1.0",
|
|
42
|
-
"
|
|
52
|
+
"picomatch": "^4.0.3",
|
|
43
53
|
"prompts": "^2.4.2",
|
|
44
54
|
"publish-browser-extension": "^2.3.0 || ^3.0.2 || ^4.0.4",
|
|
45
55
|
"scule": "^1.3.0",
|
|
@@ -47,8 +57,7 @@
|
|
|
47
57
|
"unimport": "^3.13.1 || ^4.0.0 || ^5.0.0 || ^6.0.0",
|
|
48
58
|
"vite": "^5.4.19 || ^6.3.4 || ^7.0.0 || ^8.0.0-0",
|
|
49
59
|
"vite-node": "^3.2.4 || ^5.0.0 || ^6.0.0",
|
|
50
|
-
"web-ext-run": "^0.2.4"
|
|
51
|
-
"@wxt-dev/browser": "^0.1.38"
|
|
60
|
+
"web-ext-run": "^0.2.4"
|
|
52
61
|
},
|
|
53
62
|
"peerDependencies": {
|
|
54
63
|
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0"
|
|
@@ -59,17 +68,22 @@
|
|
|
59
68
|
}
|
|
60
69
|
},
|
|
61
70
|
"devDependencies": {
|
|
71
|
+
"@aklinker1/buildc": "^1.1.7",
|
|
62
72
|
"@faker-js/faker": "^10.3.0",
|
|
73
|
+
"@types/bun": "^1.3.5",
|
|
74
|
+
"@types/fs-extra": "^11.0.4",
|
|
63
75
|
"@types/lodash.merge": "^4.6.9",
|
|
64
76
|
"@types/node": "^20.17.6",
|
|
65
77
|
"@types/normalize-path": "^3.0.2",
|
|
78
|
+
"@types/picomatch": "^4.0.2",
|
|
66
79
|
"@types/prompts": "^2.4.9",
|
|
67
|
-
"eslint": "^10.
|
|
80
|
+
"eslint": "^10.1.0",
|
|
68
81
|
"extract-zip": "^2.0.1",
|
|
69
82
|
"happy-dom": "^20.8.3",
|
|
70
83
|
"lodash.merge": "^4.6.2",
|
|
71
84
|
"oxlint": "^1.51.0",
|
|
72
85
|
"publint": "^0.3.18",
|
|
86
|
+
"tsdown": "^0.21.0",
|
|
73
87
|
"typescript": "^5.9.3",
|
|
74
88
|
"vitest": "^4.0.18",
|
|
75
89
|
"vitest-plugin-random-seed": "^1.1.2"
|
|
@@ -192,14 +206,8 @@
|
|
|
192
206
|
"default": "./dist/modules.mjs"
|
|
193
207
|
}
|
|
194
208
|
},
|
|
195
|
-
"
|
|
196
|
-
"
|
|
197
|
-
"
|
|
198
|
-
"check": "pnpm build && pnpm run --reporter-hide-prefix /^check:.*/",
|
|
199
|
-
"check:default": "check",
|
|
200
|
-
"check:tsc-virtual": "tsc --noEmit -p src/virtual",
|
|
201
|
-
"test": "buildc --deps-only -- vitest",
|
|
202
|
-
"test:coverage": "pnpm test run --coverage",
|
|
203
|
-
"sync-releases": "pnpx changelogen@latest gh release"
|
|
209
|
+
"engines": {
|
|
210
|
+
"node": ">=20.12.0",
|
|
211
|
+
"bun": ">=1.2.0"
|
|
204
212
|
}
|
|
205
|
-
}
|
|
213
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2023 Aaron
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { minimatch } from "minimatch";
|
|
2
|
-
//#region src/core/utils/minimatch-multiple.ts
|
|
3
|
-
/**
|
|
4
|
-
* Run [`minimatch`](https://npmjs.com/package/minimatch) against multiple
|
|
5
|
-
* patterns.
|
|
6
|
-
*
|
|
7
|
-
* Supports negated patterns, the order does not matter. If your `search` string
|
|
8
|
-
* matches any of the negative patterns, it will return `false`.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* minimatchMultiple('a.json', ['*.json', '!b.json']); // => true
|
|
13
|
-
* minimatchMultiple('b.json', ['*.json', '!b.json']); // => false
|
|
14
|
-
* ```;
|
|
15
|
-
*/
|
|
16
|
-
function minimatchMultiple(search, patterns, options) {
|
|
17
|
-
if (patterns == null) return false;
|
|
18
|
-
const negatePatterns = [];
|
|
19
|
-
const positivePatterns = [];
|
|
20
|
-
for (const pattern of patterns) if (pattern[0] === "!") negatePatterns.push(pattern.slice(1));
|
|
21
|
-
else positivePatterns.push(pattern);
|
|
22
|
-
if (negatePatterns.some((negatePattern) => minimatch(search, negatePattern, options))) return false;
|
|
23
|
-
return positivePatterns.some((positivePattern) => minimatch(search, positivePattern, options));
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
26
|
-
export { minimatchMultiple };
|