wxt 0.21.2 → 0.21.4
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/escape-unicode.mjs +34 -0
- package/dist/builtin-modules/index.mjs +6 -1
- package/dist/builtin-modules/unimport.mjs +3 -3
- package/dist/cli/cli-utils.mjs +5 -2
- package/dist/core/builders/vite/index.mjs +8 -1
- package/dist/core/builders/vite/plugins/devHtmlPrerender.mjs +2 -2
- package/dist/core/initialize.d.mts +3 -3
- package/dist/core/initialize.mjs +33 -47
- package/dist/core/keyboard-shortcuts.mjs +1 -0
- package/dist/core/package-managers/bun.mjs +5 -2
- package/dist/core/package-managers/npm.mjs +10 -4
- package/dist/core/package-managers/pnpm.mjs +5 -2
- package/dist/core/package-managers/yarn.mjs +5 -2
- package/dist/core/resolve-config.mjs +17 -20
- package/dist/core/utils/building/find-entrypoints.mjs +3 -3
- package/dist/core/utils/building/internal-build.mjs +3 -3
- package/dist/core/utils/building/rebuild.mjs +1 -1
- package/dist/core/utils/create-file-reloader.mjs +3 -3
- package/dist/core/utils/env.mjs +5 -1
- package/dist/core/utils/fs.mjs +6 -1
- package/dist/core/utils/log/index.mjs +1 -0
- package/dist/core/utils/log/printFileList.mjs +3 -3
- package/dist/core/utils/log/wxtLogger.mjs +32 -0
- package/dist/core/utils/manifest.mjs +6 -6
- package/dist/core/utils/paths.mjs +2 -2
- package/dist/core/utils/spinner.mjs +69 -0
- package/dist/core/utils/strings.mjs +2 -2
- package/dist/core/zip.mjs +6 -13
- package/dist/index.d.mts +2 -2
- package/dist/inline/get-port-please/index.mjs +196 -0
- package/dist/inline/is-wsl/index.mjs +44 -0
- package/dist/inline/normalize-path/index.mjs +23 -0
- package/dist/inline/ohash/index.mjs +113 -0
- package/dist/inline/scule/index.mjs +50 -0
- package/dist/types.d.mts +49 -34
- package/dist/utils/content-script-ui/iframe.d.mts +2 -0
- package/dist/utils/content-script-ui/iframe.mjs +2 -0
- package/dist/utils/content-script-ui/integrated.d.mts +2 -0
- package/dist/utils/content-script-ui/integrated.mjs +2 -0
- package/dist/utils/content-script-ui/shadow-root.d.mts +2 -0
- package/dist/utils/content-script-ui/shadow-root.mjs +2 -0
- package/dist/version.mjs +1 -1
- package/package.json +16 -19
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { addViteConfig, defineWxtModule } from "../modules.mjs";
|
|
2
|
+
//#region src/builtin-modules/escape-unicode.ts
|
|
3
|
+
var escape_unicode_default = defineWxtModule({
|
|
4
|
+
name: "wxt:built-in:escape-unicode",
|
|
5
|
+
setup(wxt) {
|
|
6
|
+
if (!wxt.config.experimental.escapeUnicode) return;
|
|
7
|
+
addViteConfig(wxt, () => ({ plugins: [escapeUnicodePlugin(wxt)] }));
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
function escapeUnicodePlugin(wxt) {
|
|
11
|
+
return {
|
|
12
|
+
name: "wxt:escape-unicode",
|
|
13
|
+
generateBundle: (_, bundle) => {
|
|
14
|
+
const start = Date.now();
|
|
15
|
+
for (const key of Object.keys(bundle)) {
|
|
16
|
+
const chunk = bundle[key];
|
|
17
|
+
if (chunk.type === "chunk") chunk.code = escapeNonCharacterUnicode(chunk.code);
|
|
18
|
+
}
|
|
19
|
+
const end = Date.now();
|
|
20
|
+
wxt.logger.info("Escaped UTF8 non-characters in " + (end - start) + "ms");
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* See:
|
|
26
|
+
*
|
|
27
|
+
* - https://github.com/rolldown/rolldown/issues/8805#issuecomment-4103480096
|
|
28
|
+
* - https://github.com/rolldown/rolldown/issues/8805#issuecomment-5134001768
|
|
29
|
+
*/
|
|
30
|
+
function escapeNonCharacterUnicode(text) {
|
|
31
|
+
return text.replace(/[\uFDD0-\uFDEF\uFFFE\uFFFF]|[\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/gu, (m) => "\\u" + m.codePointAt(0).toString(16));
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { escape_unicode_default as default };
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import favicon_permission_default from "./favicon-permission.mjs";
|
|
2
2
|
import unimport_default from "./unimport.mjs";
|
|
3
|
+
import escape_unicode_default from "./escape-unicode.mjs";
|
|
3
4
|
//#region src/builtin-modules/index.ts
|
|
4
|
-
const builtinModules = [
|
|
5
|
+
const builtinModules = [
|
|
6
|
+
unimport_default,
|
|
7
|
+
favicon_permission_default,
|
|
8
|
+
escape_unicode_default
|
|
9
|
+
];
|
|
5
10
|
//#endregion
|
|
6
11
|
export { builtinModules };
|
|
@@ -55,13 +55,13 @@ async function getImportsModuleEntry(wxt, unimport) {
|
|
|
55
55
|
tsReference: true
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
-
async function getEslintConfigEntry(unimport,
|
|
58
|
+
async function getEslintConfigEntry(unimport, configVersion, options) {
|
|
59
59
|
const globals = (await unimport.getImports()).map((i) => i.as ?? i.name).filter(Boolean).sort().reduce((globals, name) => {
|
|
60
60
|
globals[name] = options.eslintrc.globalsPropValue;
|
|
61
61
|
return globals;
|
|
62
62
|
}, {});
|
|
63
|
-
if (
|
|
64
|
-
|
|
63
|
+
if (configVersion === 8) return getEslint8ConfigEntry(options, globals);
|
|
64
|
+
return getEslint9ConfigEntry(options, globals);
|
|
65
65
|
}
|
|
66
66
|
function getEslint8ConfigEntry(options, globals) {
|
|
67
67
|
return {
|
package/dist/cli/cli-utils.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { formatDuration } from "../core/utils/time.mjs";
|
|
|
4
4
|
import { printHeader } from "../core/utils/log/printHeader.mjs";
|
|
5
5
|
import "../core/utils/log/index.mjs";
|
|
6
6
|
import { ValidationError } from "../core/utils/validation.mjs";
|
|
7
|
-
import
|
|
7
|
+
import { x } from "tinyexec";
|
|
8
8
|
import consola, { LogLevels } from "consola";
|
|
9
9
|
//#region src/cli/cli-utils.ts
|
|
10
10
|
/**
|
|
@@ -47,7 +47,10 @@ function createAliasedCommand(base, name, alias, bin, docsUrl) {
|
|
|
47
47
|
const aliasedCommand = base.command(`${name} [...args]`, `Alias for ${alias} (${docsUrl})`).allowUnknownOptions().action(async () => {
|
|
48
48
|
try {
|
|
49
49
|
await registerWxt("build");
|
|
50
|
-
await
|
|
50
|
+
await x(bin, process.argv.slice(process.argv.indexOf(aliasedCommand.name) + 1), {
|
|
51
|
+
throwOnError: true,
|
|
52
|
+
nodeOptions: { stdio: "inherit" }
|
|
53
|
+
});
|
|
51
54
|
} catch {
|
|
52
55
|
process.exit(1);
|
|
53
56
|
}
|
|
@@ -347,7 +347,14 @@ async function removeEmptyDirs(dir) {
|
|
|
347
347
|
const files = await readdir(dir);
|
|
348
348
|
for (const file of files) {
|
|
349
349
|
const filePath = join(dir, file);
|
|
350
|
-
|
|
350
|
+
let stats;
|
|
351
|
+
try {
|
|
352
|
+
stats = await stat(filePath);
|
|
353
|
+
} catch (err) {
|
|
354
|
+
if (err?.code === "ENOENT") continue;
|
|
355
|
+
throw err;
|
|
356
|
+
}
|
|
357
|
+
if (stats.isDirectory()) await removeEmptyDirs(filePath);
|
|
351
358
|
}
|
|
352
359
|
try {
|
|
353
360
|
await rmdir(dir);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { normalizePath } from "../../../utils/paths.mjs";
|
|
2
2
|
import { getEntrypointName } from "../../../utils/entrypoints.mjs";
|
|
3
3
|
import "../../../utils/index.mjs";
|
|
4
|
+
import { c } from "../../../../inline/ohash/index.mjs";
|
|
4
5
|
import { dirname, relative, resolve } from "node:path";
|
|
5
6
|
import { parseHTML } from "linkedom";
|
|
6
|
-
import { hash } from "ohash";
|
|
7
7
|
//#region src/core/builders/vite/plugins/devHtmlPrerender.ts
|
|
8
8
|
const inlineScriptContents = {};
|
|
9
9
|
/**
|
|
@@ -48,7 +48,7 @@ function devHtmlPrerender(config, server) {
|
|
|
48
48
|
const { document } = parseHTML(await server.transformHtml(url, html, originalUrl));
|
|
49
49
|
document.querySelectorAll("script:not([src])").forEach((script) => {
|
|
50
50
|
const textContent = script.textContent ?? "";
|
|
51
|
-
const key =
|
|
51
|
+
const key = c(textContent);
|
|
52
52
|
inlineScriptContents[key] = textContent;
|
|
53
53
|
const virtualScript = document.createElement("script");
|
|
54
54
|
virtualScript.type = "module";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
//#region src/core/initialize.d.ts
|
|
2
2
|
declare function initialize(options: {
|
|
3
|
-
directory
|
|
4
|
-
template
|
|
5
|
-
packageManager
|
|
3
|
+
directory?: string;
|
|
4
|
+
template?: string;
|
|
5
|
+
packageManager?: string;
|
|
6
6
|
}): Promise<void>;
|
|
7
7
|
//#endregion
|
|
8
8
|
export { initialize };
|
package/dist/core/initialize.mjs
CHANGED
|
@@ -1,73 +1,60 @@
|
|
|
1
1
|
import { pathExists } from "./utils/fs.mjs";
|
|
2
|
+
import { createSpinner } from "./utils/spinner.mjs";
|
|
2
3
|
import { readdir, rename } from "node:fs/promises";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { consola as consola$1 } from "consola";
|
|
5
6
|
import { styleText } from "node:util";
|
|
6
|
-
import
|
|
7
|
+
import { question, select } from "@topcli/prompts";
|
|
7
8
|
import { downloadTemplate } from "giget";
|
|
8
9
|
//#region src/core/initialize.ts
|
|
9
10
|
async function initialize(options) {
|
|
10
11
|
consola$1.info("Initializing new project");
|
|
11
12
|
const templates = await listTemplates();
|
|
12
|
-
const
|
|
13
|
-
const
|
|
13
|
+
const inputTemplateName = options.template ? templates.find((template) => template.name === options.template.toLowerCase().trim())?.name : void 0;
|
|
14
|
+
const directory = options.directory ?? await question("Project Directory", { defaultValue: "." });
|
|
15
|
+
if (!directory) throw Error("Directory is required");
|
|
16
|
+
const templateName = inputTemplateName ?? await select("Choose a template", { choices: templates.map((template) => ({
|
|
17
|
+
label: TEMPLATE_COLORS[template.name] ? styleText(TEMPLATE_COLORS[template.name], template.name) : template.name,
|
|
18
|
+
value: template.name
|
|
19
|
+
})) });
|
|
20
|
+
const template = templates.find((t) => t.name === templateName);
|
|
21
|
+
if (!template) throw Error("Unknown template: " + templateName);
|
|
22
|
+
const packageManager = options.packageManager ?? await select("Package Manager", { choices: [
|
|
14
23
|
{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
message: "Project Directory",
|
|
18
|
-
initial: options.directory
|
|
24
|
+
label: styleText("magenta", "bun"),
|
|
25
|
+
value: "bun"
|
|
19
26
|
},
|
|
20
27
|
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
message: "Choose a template",
|
|
24
|
-
choices: templates.map((template) => ({
|
|
25
|
-
title: TEMPLATE_COLORS[template.name] ? styleText(TEMPLATE_COLORS[template.name], template.name) : template.name,
|
|
26
|
-
value: template
|
|
27
|
-
}))
|
|
28
|
+
label: styleText("red", "npm"),
|
|
29
|
+
value: "npm"
|
|
28
30
|
},
|
|
29
31
|
{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
value: "bun"
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
title: styleText("red", "npm"),
|
|
40
|
-
value: "npm"
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
title: styleText("yellow", "pnpm"),
|
|
44
|
-
value: "pnpm"
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
title: styleText("cyan", "yarn"),
|
|
48
|
-
value: "yarn"
|
|
49
|
-
}
|
|
50
|
-
]
|
|
32
|
+
label: styleText("yellow", "pnpm"),
|
|
33
|
+
value: "pnpm"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: styleText("cyan", "yarn"),
|
|
37
|
+
value: "yarn"
|
|
51
38
|
}
|
|
52
|
-
]
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (await pathExists(input.directory)) {
|
|
57
|
-
if (!((await readdir(input.directory)).filter((dir) => dir !== ".git").length === 0)) {
|
|
58
|
-
consola$1.error(`The directory ${path.resolve(input.directory)} is not empty. Aborted.`);
|
|
39
|
+
] });
|
|
40
|
+
if (await pathExists(directory)) {
|
|
41
|
+
if (!((await readdir(directory)).filter((dir) => dir !== ".git").length === 0)) {
|
|
42
|
+
consola$1.error(`The directory ${path.resolve(directory)} is not empty. Aborted.`);
|
|
59
43
|
process.exit(1);
|
|
60
44
|
}
|
|
61
45
|
}
|
|
62
|
-
await cloneProject(
|
|
63
|
-
|
|
46
|
+
await cloneProject({
|
|
47
|
+
directory,
|
|
48
|
+
template
|
|
49
|
+
});
|
|
50
|
+
const cdPath = path.relative(process.cwd(), path.resolve(directory));
|
|
64
51
|
console.log();
|
|
65
|
-
consola$1.log(`✨ WXT project created with the ${TEMPLATE_COLORS[
|
|
52
|
+
consola$1.log(`✨ WXT project created with the ${TEMPLATE_COLORS[template.name] ? styleText(TEMPLATE_COLORS[template.name], template.name) : template.name} template.`);
|
|
66
53
|
console.log();
|
|
67
54
|
consola$1.log("Next steps:");
|
|
68
55
|
let step = 0;
|
|
69
56
|
if (cdPath !== "") consola$1.log(` ${++step}.`, styleText("cyan", `cd ${cdPath}`));
|
|
70
|
-
consola$1.log(` ${++step}.`, styleText("cyan", `${
|
|
57
|
+
consola$1.log(` ${++step}.`, styleText("cyan", `${packageManager} install`));
|
|
71
58
|
console.log();
|
|
72
59
|
}
|
|
73
60
|
async function listTemplates() {
|
|
@@ -94,7 +81,6 @@ async function listTemplatesGithub() {
|
|
|
94
81
|
return await res.json();
|
|
95
82
|
}
|
|
96
83
|
async function cloneProject({ directory, template }) {
|
|
97
|
-
const { createSpinner } = await import("nanospinner");
|
|
98
84
|
const spinner = createSpinner("Downloading template").start();
|
|
99
85
|
try {
|
|
100
86
|
await downloadTemplate(`gh:${REPO}/${template.path}`, {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { dedupeDependencies, npm } from "./npm.mjs";
|
|
2
|
-
import
|
|
2
|
+
import { x } from "tinyexec";
|
|
3
3
|
//#region src/core/package-managers/bun.ts
|
|
4
4
|
const bun = {
|
|
5
5
|
overridesKey: "overrides",
|
|
@@ -9,7 +9,10 @@ const bun = {
|
|
|
9
9
|
async listDependencies(options) {
|
|
10
10
|
const args = ["pm", "ls"];
|
|
11
11
|
if (options?.all) args.push("--all");
|
|
12
|
-
return dedupeDependencies((await
|
|
12
|
+
return dedupeDependencies((await x("bun", args, {
|
|
13
|
+
throwOnError: true,
|
|
14
|
+
nodeOptions: { cwd: options?.cwd }
|
|
15
|
+
})).stdout.split("\n").slice(1).map((line) => line.trim()).map((line) => /.* (@?\S+)@(\S+)$/.exec(line)).filter((match) => !!match).map(([_, name, version]) => ({
|
|
13
16
|
name,
|
|
14
17
|
version
|
|
15
18
|
})));
|
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
import { mkdir } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import
|
|
3
|
+
import { x } from "tinyexec";
|
|
4
4
|
//#region src/core/package-managers/npm.ts
|
|
5
5
|
const npm = {
|
|
6
6
|
overridesKey: "overrides",
|
|
7
7
|
async downloadDependency(id, downloadDir) {
|
|
8
8
|
await mkdir(downloadDir, { recursive: true });
|
|
9
|
-
const res = await
|
|
9
|
+
const res = await x("npm", [
|
|
10
10
|
"pack",
|
|
11
11
|
id,
|
|
12
12
|
"--json"
|
|
13
|
-
], {
|
|
13
|
+
], {
|
|
14
|
+
throwOnError: true,
|
|
15
|
+
nodeOptions: { cwd: downloadDir }
|
|
16
|
+
});
|
|
14
17
|
const packed = JSON.parse(res.stdout);
|
|
15
18
|
return path.resolve(downloadDir, packed[0].filename);
|
|
16
19
|
},
|
|
17
20
|
async listDependencies(options) {
|
|
18
21
|
const args = ["ls", "--json"];
|
|
19
22
|
if (options?.all) args.push("--depth", "Infinity");
|
|
20
|
-
const res = await
|
|
23
|
+
const res = await x("npm", args, {
|
|
24
|
+
throwOnError: true,
|
|
25
|
+
nodeOptions: { cwd: options?.cwd }
|
|
26
|
+
});
|
|
21
27
|
return flattenNpmListOutput([JSON.parse(res.stdout)]);
|
|
22
28
|
}
|
|
23
29
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { flattenNpmListOutput, npm } from "./npm.mjs";
|
|
2
|
-
import
|
|
2
|
+
import { x } from "tinyexec";
|
|
3
3
|
//#region src/core/package-managers/pnpm.ts
|
|
4
4
|
const pnpm = {
|
|
5
5
|
overridesKey: "resolutions",
|
|
@@ -14,7 +14,10 @@ const pnpm = {
|
|
|
14
14
|
];
|
|
15
15
|
if (options?.all) args.push("--depth", "Infinity");
|
|
16
16
|
if (typeof process !== "undefined" && process.env.WXT_PNPM_IGNORE_WORKSPACE === "true") args.push("--ignore-workspace");
|
|
17
|
-
const res = await
|
|
17
|
+
const res = await x("pnpm", args, {
|
|
18
|
+
throwOnError: true,
|
|
19
|
+
nodeOptions: { cwd: options?.cwd }
|
|
20
|
+
});
|
|
18
21
|
return flattenNpmListOutput(JSON.parse(res.stdout));
|
|
19
22
|
}
|
|
20
23
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { dedupeDependencies, npm } from "./npm.mjs";
|
|
2
|
-
import
|
|
2
|
+
import { x } from "tinyexec";
|
|
3
3
|
//#region src/core/package-managers/yarn.ts
|
|
4
4
|
const yarn = {
|
|
5
5
|
overridesKey: "resolutions",
|
|
@@ -9,7 +9,10 @@ const yarn = {
|
|
|
9
9
|
async listDependencies(options) {
|
|
10
10
|
const args = ["list", "--json"];
|
|
11
11
|
if (options?.all) args.push("--depth", "Infinity");
|
|
12
|
-
const tree = (await
|
|
12
|
+
const tree = (await x("yarn", args, {
|
|
13
|
+
throwOnError: true,
|
|
14
|
+
nodeOptions: { cwd: options?.cwd }
|
|
15
|
+
})).stdout.trimEnd().split("\n").map((line) => JSON.parse(line)).find((line) => line.type === "tree")?.data;
|
|
13
16
|
if (tree == null) throw Error("'yarn list --json' did not output a tree");
|
|
14
17
|
const queue = [...tree.trees];
|
|
15
18
|
const dependencies = [];
|
|
@@ -5,19 +5,19 @@ import { createFsCache } from "./utils/cache.mjs";
|
|
|
5
5
|
import { getEslintVersion } from "./utils/eslint.mjs";
|
|
6
6
|
import { safeStringToNumber } from "./utils/number.mjs";
|
|
7
7
|
import { loadEnv } from "./utils/env.mjs";
|
|
8
|
+
import { v } from "../inline/get-port-please/index.mjs";
|
|
8
9
|
import { createSafariRunner } from "./runners/safari.mjs";
|
|
10
|
+
import { d } from "../inline/is-wsl/index.mjs";
|
|
9
11
|
import { createWslRunner } from "./runners/wsl.mjs";
|
|
10
12
|
import { createManualRunner } from "./runners/manual.mjs";
|
|
13
|
+
import { createWxtLogger } from "./utils/log/wxtLogger.mjs";
|
|
11
14
|
import { pathExists } from "./utils/fs.mjs";
|
|
12
15
|
import { glob } from "tinyglobby";
|
|
13
16
|
import path from "node:path";
|
|
14
17
|
import { loadConfig } from "c12";
|
|
15
|
-
import { resolve as resolve$1 } from "import-meta-resolve";
|
|
16
18
|
import consola, { LogLevels } from "consola";
|
|
17
19
|
import defu from "defu";
|
|
18
|
-
import { getPort } from "get-port-please";
|
|
19
20
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
20
|
-
import isWsl from "is-wsl";
|
|
21
21
|
//#region src/core/resolve-config.ts
|
|
22
22
|
/**
|
|
23
23
|
* Given an inline config, discover the config file if necessary, merge the
|
|
@@ -41,7 +41,7 @@ async function resolveConfig(inlineConfig, command) {
|
|
|
41
41
|
}
|
|
42
42
|
const mergedConfig = await mergeInlineConfig(inlineConfig, userConfig);
|
|
43
43
|
const debug = mergedConfig.debug ?? false;
|
|
44
|
-
const logger = mergedConfig.logger ?? consola;
|
|
44
|
+
const logger = createWxtLogger(mergedConfig.logger ?? consola);
|
|
45
45
|
if (debug) logger.level = LogLevels.debug;
|
|
46
46
|
const browser = mergedConfig.browser ?? "chrome";
|
|
47
47
|
const targetBrowsers = mergedConfig.targetBrowsers ?? [];
|
|
@@ -94,12 +94,12 @@ async function resolveConfig(inlineConfig, command) {
|
|
|
94
94
|
let port = mergedConfig.dev?.server?.port;
|
|
95
95
|
const origin = mergedConfig.dev?.server?.origin ?? "localhost";
|
|
96
96
|
const strictPort = mergedConfig.dev?.server?.strictPort ?? false;
|
|
97
|
-
if (port == null || !isFinite(port)) port = await
|
|
97
|
+
if (port == null || !isFinite(port)) port = await v({
|
|
98
98
|
host,
|
|
99
99
|
port: 3e3,
|
|
100
100
|
portRange: [3001, 3010]
|
|
101
101
|
});
|
|
102
|
-
else if (!strictPort) port = await
|
|
102
|
+
else if (!strictPort) port = await v({
|
|
103
103
|
host,
|
|
104
104
|
port
|
|
105
105
|
});
|
|
@@ -142,7 +142,7 @@ async function resolveConfig(inlineConfig, command) {
|
|
|
142
142
|
wxtModuleDir,
|
|
143
143
|
root,
|
|
144
144
|
webExt,
|
|
145
|
-
runner: command === "serve" ? await resolveRunner(browser, logger,
|
|
145
|
+
runner: command === "serve" ? await resolveRunner(browser, logger, webExt.config) : createManualRunner(),
|
|
146
146
|
srcDir,
|
|
147
147
|
typesDir,
|
|
148
148
|
wxtDir,
|
|
@@ -150,7 +150,7 @@ async function resolveConfig(inlineConfig, command) {
|
|
|
150
150
|
analysis: resolveAnalysisConfig(root, mergedConfig),
|
|
151
151
|
userConfigMetadata: userConfigMetadata ?? {},
|
|
152
152
|
alias,
|
|
153
|
-
experimental: defu(mergedConfig.experimental, {}),
|
|
153
|
+
experimental: defu(mergedConfig.experimental, { escapeUnicode: false }),
|
|
154
154
|
suppressWarnings: mergedConfig.suppressWarnings ?? {},
|
|
155
155
|
watchOptions: mergedConfig.watchOptions ?? {},
|
|
156
156
|
dev: {
|
|
@@ -342,17 +342,14 @@ async function getUnimportOptions(wxtDir, srcDir, logger, config) {
|
|
|
342
342
|
return defu(config.imports ?? {}, defaultOptions);
|
|
343
343
|
}
|
|
344
344
|
async function getUnimportEslintOptions(logger, wxtDir, options) {
|
|
345
|
-
const inlineEnabled = options === false ? false : options?.eslintrc?.enabled ??
|
|
345
|
+
const inlineEnabled = options === false ? false : options?.eslintrc?.enabled ?? true;
|
|
346
346
|
const version = await getEslintVersion();
|
|
347
347
|
const major = parseInt(version[0]);
|
|
348
348
|
let enabled;
|
|
349
349
|
switch (inlineEnabled) {
|
|
350
|
-
case "auto":
|
|
350
|
+
case "auto": logger.warn(`\`imports.eslintrc.enabled: "auto"\` is deprecated. Use \`true\` instead.`);
|
|
351
351
|
case true:
|
|
352
|
-
if (
|
|
353
|
-
if (inlineEnabled === true) logger.warn("Could not determine installed ESLint version, `eslint-auto-imports.mjs` not generated");
|
|
354
|
-
enabled = false;
|
|
355
|
-
} else if (major <= 8) enabled = 8;
|
|
352
|
+
if (major <= 8) enabled = 8;
|
|
356
353
|
else if (major >= 9) enabled = 9;
|
|
357
354
|
else enabled = false;
|
|
358
355
|
break;
|
|
@@ -366,14 +363,14 @@ async function getUnimportEslintOptions(logger, wxtDir, options) {
|
|
|
366
363
|
}
|
|
367
364
|
/** Returns the path to `node_modules/wxt`. */
|
|
368
365
|
function resolveWxtModuleDir() {
|
|
369
|
-
const url = resolve
|
|
366
|
+
const url = import.meta.resolve("wxt", import.meta.url);
|
|
370
367
|
return path.resolve(fileURLToPath(url), "../..");
|
|
371
368
|
}
|
|
372
369
|
async function isDirMissing(dir) {
|
|
373
370
|
return !await pathExists(dir);
|
|
374
371
|
}
|
|
375
372
|
function logMissingDir(logger, name, expected) {
|
|
376
|
-
logger.
|
|
373
|
+
logger.warnOnce(`${name} directory not found: ./${normalizePath(path.relative(process.cwd(), expected))}`);
|
|
377
374
|
}
|
|
378
375
|
/** Map of `ConfigEnv` commands to their default modes. */
|
|
379
376
|
const COMMAND_MODES = {
|
|
@@ -393,7 +390,7 @@ async function mergeBuilderConfig(logger, inlineConfig, userConfig) {
|
|
|
393
390
|
async function resolveWxtUserModules(root, modulesDir, modules = []) {
|
|
394
391
|
const importer = pathToFileURL(path.join(root, "index.js")).href;
|
|
395
392
|
const npmModules = await Promise.all(modules.map(async (moduleId) => {
|
|
396
|
-
const mod = await import(resolve
|
|
393
|
+
const mod = await import(import.meta.resolve(moduleId, importer));
|
|
397
394
|
if (mod.default == null) throw Error("Module missing default export: " + moduleId);
|
|
398
395
|
return {
|
|
399
396
|
...mod.default,
|
|
@@ -427,12 +424,12 @@ async function resolveWxtUserModules(root, modulesDir, modules = []) {
|
|
|
427
424
|
}));
|
|
428
425
|
return [...npmModules, ...localModules];
|
|
429
426
|
}
|
|
430
|
-
async function resolveRunner(browser, logger,
|
|
427
|
+
async function resolveRunner(browser, logger, webExt) {
|
|
431
428
|
if (browser === "safari") return createSafariRunner();
|
|
432
|
-
if (
|
|
429
|
+
if (d) return createWslRunner();
|
|
433
430
|
try {
|
|
434
431
|
const { createWebExtRunner } = await import("./runners/web-ext.mjs");
|
|
435
|
-
return
|
|
432
|
+
return webExt.disabled ? createManualRunner() : createWebExtRunner();
|
|
436
433
|
} catch (err) {
|
|
437
434
|
if (err?.code !== "ERR_MODULE_NOT_FOUND") throw err;
|
|
438
435
|
logger.debug("Error loading the web-ext runner", err);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { CSS_EXTENSIONS_PATTERN } from "../paths.mjs";
|
|
2
2
|
import { getEntrypointName, isHtmlEntrypoint, isJsEntrypoint, resolvePerBrowserOptions } from "../entrypoints.mjs";
|
|
3
|
+
import { s } from "../../../inline/scule/index.mjs";
|
|
3
4
|
import { VIRTUAL_NOOP_BACKGROUND_MODULE_ID } from "../constants.mjs";
|
|
4
5
|
import { wxt } from "../../wxt.mjs";
|
|
5
6
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
6
7
|
import { glob } from "tinyglobby";
|
|
7
8
|
import { relative, resolve } from "path";
|
|
8
9
|
import { parseHTML } from "linkedom";
|
|
9
|
-
import { camelCase } from "scule";
|
|
10
10
|
import { styleText } from "node:util";
|
|
11
11
|
import picomatch from "picomatch";
|
|
12
12
|
import JSON5 from "json5";
|
|
@@ -118,8 +118,8 @@ async function importHtmlEntrypoint(info) {
|
|
|
118
118
|
metaTags.forEach((tag) => {
|
|
119
119
|
const name = tag.name;
|
|
120
120
|
let key;
|
|
121
|
-
if (name.startsWith("manifest.")) key =
|
|
122
|
-
else if (name.startsWith("wxt.")) key =
|
|
121
|
+
if (name.startsWith("manifest.")) key = s(name.slice(9));
|
|
122
|
+
else if (name.startsWith("wxt.")) key = s(name.slice(4));
|
|
123
123
|
else return;
|
|
124
124
|
try {
|
|
125
125
|
res[key] = JSON5.parse(tag.content);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { unnormalizePath } from "../paths.mjs";
|
|
2
|
+
import { isCI } from "../env.mjs";
|
|
2
3
|
import { wxt } from "../../wxt.mjs";
|
|
3
4
|
import { findEntrypoints } from "./find-entrypoints.mjs";
|
|
4
5
|
import { groupEntrypoints } from "./group-entrypoints.mjs";
|
|
@@ -12,7 +13,7 @@ import { glob } from "tinyglobby";
|
|
|
12
13
|
import { relative } from "node:path";
|
|
13
14
|
import { mergeJsonOutputs } from "@aklinker1/rollup-plugin-visualizer";
|
|
14
15
|
import { styleText } from "node:util";
|
|
15
|
-
import
|
|
16
|
+
import open from "tiny-open";
|
|
16
17
|
//#region src/core/utils/building/internal-build.ts
|
|
17
18
|
/**
|
|
18
19
|
* Builds the extension based on an internal config. No more config discovery is
|
|
@@ -51,10 +52,9 @@ async function internalBuild() {
|
|
|
51
52
|
await combineAnalysisStats();
|
|
52
53
|
const statsPath = relative(wxt.config.root, wxt.config.analysis.outputFile);
|
|
53
54
|
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
|
+
if (wxt.config.analysis.open) if (isCI()) wxt.logger.debug(`Skipped opening ${styleText("yellow", statsPath)} in CI`);
|
|
55
56
|
else {
|
|
56
57
|
wxt.logger.info(`Opening ${styleText("yellow", statsPath)} in browser...`);
|
|
57
|
-
const { default: open } = await import("open");
|
|
58
58
|
await open(wxt.config.analysis.outputFile);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { wxt } from "../../wxt.mjs";
|
|
2
2
|
import { buildEntrypoints } from "./build-entrypoints.mjs";
|
|
3
|
+
import { createSpinner } from "../spinner.mjs";
|
|
3
4
|
import { generateWxtDir } from "../../generate-wxt-dir.mjs";
|
|
4
5
|
import { generateManifest, writeManifest } from "../manifest.mjs";
|
|
5
|
-
import { createSpinner } from "nanospinner";
|
|
6
6
|
//#region src/core/utils/building/rebuild.ts
|
|
7
7
|
/**
|
|
8
8
|
* Given a configuration, list of entrypoints, and an existing, partial output,
|
|
@@ -12,18 +12,18 @@ import "./building/index.mjs";
|
|
|
12
12
|
import { isBabelSyntaxError, logBabelSyntaxError } from "./syntax-errors.mjs";
|
|
13
13
|
import { relative } from "node:path";
|
|
14
14
|
import { styleText } from "node:util";
|
|
15
|
-
import {
|
|
15
|
+
import { withLock } from "superlock";
|
|
16
16
|
//#region src/core/utils/create-file-reloader.ts
|
|
17
17
|
/**
|
|
18
18
|
* Returns a function responsible for reloading different parts of the extension
|
|
19
19
|
* when a file changes.
|
|
20
20
|
*/
|
|
21
21
|
function createFileReloader(server) {
|
|
22
|
-
const
|
|
22
|
+
const fileChangedLock = withLock();
|
|
23
23
|
const changeQueue = [];
|
|
24
24
|
let processLoop;
|
|
25
25
|
const processQueue = async () => {
|
|
26
|
-
await
|
|
26
|
+
await fileChangedLock(async () => {
|
|
27
27
|
const fileChanges = changeQueue.splice(0, changeQueue.length).map(([_, file]) => file);
|
|
28
28
|
if (fileChanges.length === 0) return;
|
|
29
29
|
if (server.currentOutput == null) return;
|
package/dist/core/utils/env.mjs
CHANGED
|
@@ -2,6 +2,10 @@ import { expand } from "dotenv-expand";
|
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { parseEnv } from "node:util";
|
|
4
4
|
//#region src/core/utils/env.ts
|
|
5
|
+
/** Returns true when running in a CI environment. */
|
|
6
|
+
function isCI() {
|
|
7
|
+
return !!process.env.CI && process.env.CI !== "false";
|
|
8
|
+
}
|
|
5
9
|
/** Load environment files based on the current mode and browser. */
|
|
6
10
|
function loadEnv(mode, browser) {
|
|
7
11
|
const envFiles = [
|
|
@@ -27,4 +31,4 @@ function loadEnv(mode, browser) {
|
|
|
27
31
|
return parsed;
|
|
28
32
|
}
|
|
29
33
|
//#endregion
|
|
30
|
-
export { loadEnv };
|
|
34
|
+
export { isCI, loadEnv };
|
package/dist/core/utils/fs.mjs
CHANGED
|
@@ -32,5 +32,10 @@ async function getPublicFiles() {
|
|
|
32
32
|
expandDirectories: false
|
|
33
33
|
})).map(unnormalizePath);
|
|
34
34
|
}
|
|
35
|
+
function getBytesDisplay(bytes) {
|
|
36
|
+
if (bytes < 1e3) return `${bytes} B`;
|
|
37
|
+
if (bytes < 999995) return `${(bytes / 1e3).toFixed(2)} kB`;
|
|
38
|
+
return `${(bytes / 1e6).toFixed(2)} MB`;
|
|
39
|
+
}
|
|
35
40
|
//#endregion
|
|
36
|
-
export { getPublicFiles, pathExists, readJson, writeFileIfDifferent };
|
|
41
|
+
export { getBytesDisplay, getPublicFiles, pathExists, readJson, writeFileIfDifferent };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { wxt } from "../../wxt.mjs";
|
|
2
|
+
import { getBytesDisplay } from "../fs.mjs";
|
|
2
3
|
import { printTable } from "./printTable.mjs";
|
|
3
4
|
import { lstat } from "node:fs/promises";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { styleText } from "node:util";
|
|
6
|
-
import { filesize } from "filesize";
|
|
7
7
|
//#region src/core/utils/log/printFileList.ts
|
|
8
8
|
async function printFileList(log, header, baseDir, files) {
|
|
9
9
|
let totalSize = 0;
|
|
@@ -15,13 +15,13 @@ async function printFileList(log, header, baseDir, files) {
|
|
|
15
15
|
try {
|
|
16
16
|
const stats = await lstat(file);
|
|
17
17
|
totalSize += stats.size;
|
|
18
|
-
size =
|
|
18
|
+
size = getBytesDisplay(stats.size);
|
|
19
19
|
} catch (ex) {
|
|
20
20
|
wxt.logger.warn(`Could not get stats of '${file}' error: ${ex}`);
|
|
21
21
|
}
|
|
22
22
|
return [`${styleText("gray", prefix)} ${styleText("dim", parts[0])}${styleText(chunkColor, parts[1])}`, styleText("dim", size)];
|
|
23
23
|
}));
|
|
24
|
-
fileRows.push([`${styleText("cyan", "Σ Total size:")} ${
|
|
24
|
+
fileRows.push([`${styleText("cyan", "Σ Total size:")} ${getBytesDisplay(totalSize)}`]);
|
|
25
25
|
printTable(log, header, fileRows);
|
|
26
26
|
}
|
|
27
27
|
const DEFAULT_COLOR = "blue";
|