wxt 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/cli.cjs +1870 -0
- package/dist/{client/index.d.ts → client.d.ts} +1 -2
- package/dist/client.js +22 -0
- package/dist/index.cjs +782 -461
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +54 -6
- package/dist/index.js +787 -466
- package/dist/index.js.map +1 -1
- package/dist/virtual-modules/background-entrypoint.js +129 -0
- package/dist/virtual-modules/background-entrypoint.js.map +1 -0
- package/dist/virtual-modules/content-script-entrypoint.js +28 -0
- package/dist/virtual-modules/content-script-entrypoint.js.map +1 -0
- package/dist/virtual-modules/reload-html.js +58 -0
- package/dist/virtual-modules/reload-html.js.map +1 -0
- package/package.json +14 -12
- package/dist/cli/index.cjs +0 -1549
- package/dist/cli/index.cjs.map +0 -1
- package/dist/client/index.cjs +0 -51
- package/dist/client/index.cjs.map +0 -1
- package/dist/client/index.js +0 -22
- package/dist/client/index.js.map +0 -1
- package/templates/template-vars.d.ts +0 -11
- package/templates/virtual-background.ts +0 -13
- package/templates/virtual-content-script.ts +0 -9
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/core/utils/getInternalConfig.ts
|
|
2
2
|
import path2, { resolve as resolve7 } from "node:path";
|
|
3
|
-
import * as
|
|
3
|
+
import * as vite2 from "vite";
|
|
4
4
|
import { consola as consola2 } from "consola";
|
|
5
5
|
|
|
6
6
|
// src/core/utils/importTsFile.ts
|
|
@@ -11,7 +11,7 @@ import { resolve } from "path";
|
|
|
11
11
|
import { scanExports } from "unimport";
|
|
12
12
|
async function importTsFile(root, path5) {
|
|
13
13
|
const clientImports = await scanExports(
|
|
14
|
-
resolve(root, "node_modules/wxt/dist/client
|
|
14
|
+
resolve(root, "node_modules/wxt/dist/client.js")
|
|
15
15
|
);
|
|
16
16
|
const jiti = createJITI(__filename, {
|
|
17
17
|
cache: false,
|
|
@@ -38,6 +38,106 @@ async function importTsFile(root, path5) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
// src/core/vite-plugins/devHtmlPrerender.ts
|
|
42
|
+
import * as vite from "vite";
|
|
43
|
+
|
|
44
|
+
// src/core/utils/entrypoints.ts
|
|
45
|
+
import path, { relative, resolve as resolve2 } from "node:path";
|
|
46
|
+
function getEntrypointName(entrypointsDir, inputPath) {
|
|
47
|
+
const relativePath = path.relative(entrypointsDir, inputPath);
|
|
48
|
+
const name = relativePath.split(/[\.\/]/, 2)[0];
|
|
49
|
+
return name;
|
|
50
|
+
}
|
|
51
|
+
function getEntrypointOutputFile(entrypoint, ext) {
|
|
52
|
+
return resolve2(entrypoint.outputDir, `${entrypoint.name}${ext}`);
|
|
53
|
+
}
|
|
54
|
+
function getEntrypointBundlePath(entrypoint, outDir, ext) {
|
|
55
|
+
return relative(outDir, getEntrypointOutputFile(entrypoint, ext));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/core/vite-plugins/devHtmlPrerender.ts
|
|
59
|
+
import { parseHTML } from "linkedom";
|
|
60
|
+
import { dirname, isAbsolute, relative as relative2, resolve as resolve3 } from "path";
|
|
61
|
+
function devHtmlPrerender(config) {
|
|
62
|
+
return {
|
|
63
|
+
apply: "build",
|
|
64
|
+
name: "wxt:dev-html-prerender",
|
|
65
|
+
config(userConfig) {
|
|
66
|
+
return vite.mergeConfig(
|
|
67
|
+
{
|
|
68
|
+
resolve: {
|
|
69
|
+
alias: {
|
|
70
|
+
"@wxt/reload-html": resolve3(
|
|
71
|
+
config.root,
|
|
72
|
+
"node_modules/wxt/dist/virtual-modules/reload-html.js"
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
userConfig
|
|
78
|
+
);
|
|
79
|
+
},
|
|
80
|
+
async transform(html, id) {
|
|
81
|
+
const server = config.server;
|
|
82
|
+
if (config.command !== "serve" || server == null || !id.endsWith(".html"))
|
|
83
|
+
return;
|
|
84
|
+
const originalUrl = `${server.origin}${id}`;
|
|
85
|
+
const name = getEntrypointName(config.entrypointsDir, id);
|
|
86
|
+
const url = `${server.origin}/${name}.html`;
|
|
87
|
+
const serverHtml = await server.transformIndexHtml(
|
|
88
|
+
url,
|
|
89
|
+
html,
|
|
90
|
+
originalUrl
|
|
91
|
+
);
|
|
92
|
+
const { document } = parseHTML(serverHtml);
|
|
93
|
+
const pointToDevServer = (querySelector, attr) => {
|
|
94
|
+
document.querySelectorAll(querySelector).forEach((element) => {
|
|
95
|
+
const src = element.getAttribute(attr);
|
|
96
|
+
if (!src)
|
|
97
|
+
return;
|
|
98
|
+
if (isAbsolute(src)) {
|
|
99
|
+
element.setAttribute(attr, server.origin + src);
|
|
100
|
+
} else if (src.startsWith(".")) {
|
|
101
|
+
const abs = resolve3(dirname(id), src);
|
|
102
|
+
const pathname = relative2(config.root, abs);
|
|
103
|
+
element.setAttribute(attr, `${server.origin}/${pathname}`);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
pointToDevServer("script[type=module]", "src");
|
|
108
|
+
pointToDevServer("link[rel=stylesheet]", "href");
|
|
109
|
+
const reloader = document.createElement("script");
|
|
110
|
+
reloader.src = "@wxt/reload-html";
|
|
111
|
+
reloader.type = "module";
|
|
112
|
+
document.head.appendChild(reloader);
|
|
113
|
+
const newHtml = document.toString();
|
|
114
|
+
config.logger.debug("Transformed " + id);
|
|
115
|
+
config.logger.debug("Old HTML:\n" + html);
|
|
116
|
+
config.logger.debug("New HTML:\n" + newHtml);
|
|
117
|
+
return newHtml;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/core/vite-plugins/devServerGlobals.ts
|
|
123
|
+
function devServerGlobals(internalConfig) {
|
|
124
|
+
return {
|
|
125
|
+
name: "wxt:dev-server-globals",
|
|
126
|
+
config(config) {
|
|
127
|
+
if (internalConfig.server == null || internalConfig.command == "build")
|
|
128
|
+
return;
|
|
129
|
+
config.define ??= {};
|
|
130
|
+
config.define.__DEV_SERVER_PROTOCOL__ = JSON.stringify("ws:");
|
|
131
|
+
config.define.__DEV_SERVER_HOSTNAME__ = JSON.stringify(
|
|
132
|
+
internalConfig.server.hostname
|
|
133
|
+
);
|
|
134
|
+
config.define.__DEV_SERVER_PORT__ = JSON.stringify(
|
|
135
|
+
internalConfig.server.port
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
41
141
|
// src/core/utils/network.ts
|
|
42
142
|
import dns from "node:dns";
|
|
43
143
|
|
|
@@ -107,61 +207,8 @@ function download(config) {
|
|
|
107
207
|
};
|
|
108
208
|
}
|
|
109
209
|
|
|
110
|
-
// src/core/vite-plugins/unimport.ts
|
|
111
|
-
import { createUnimport } from "unimport";
|
|
112
|
-
|
|
113
|
-
// src/core/utils/auto-imports.ts
|
|
114
|
-
import { mergeConfig } from "vite";
|
|
115
|
-
function getUnimportOptions(config) {
|
|
116
|
-
const defaultOptions = {
|
|
117
|
-
debugLog: config.logger.debug,
|
|
118
|
-
imports: [
|
|
119
|
-
{ name: "*", as: "browser", from: "webextension-polyfill" },
|
|
120
|
-
{ name: "defineConfig", from: "wxt" }
|
|
121
|
-
],
|
|
122
|
-
presets: [{ package: "wxt/client" }],
|
|
123
|
-
warn: config.logger.warn,
|
|
124
|
-
dirs: ["components", "composables", "hooks", "utils"]
|
|
125
|
-
};
|
|
126
|
-
return mergeConfig(
|
|
127
|
-
defaultOptions,
|
|
128
|
-
config.imports
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// src/core/vite-plugins/unimport.ts
|
|
133
|
-
function unimport(config) {
|
|
134
|
-
const options = getUnimportOptions(config);
|
|
135
|
-
const unimport2 = createUnimport(options);
|
|
136
|
-
return {
|
|
137
|
-
name: "wxt:unimport",
|
|
138
|
-
async config() {
|
|
139
|
-
await unimport2.scanImportsFromDir(void 0, { cwd: config.srcDir });
|
|
140
|
-
},
|
|
141
|
-
async transform(code, id) {
|
|
142
|
-
return unimport2.injectImports(code, id);
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// src/core/vite-plugins/multipageMove.ts
|
|
148
|
-
import { dirname, extname, resolve as resolve3 } from "node:path";
|
|
149
|
-
|
|
150
|
-
// src/core/utils/entrypoints.ts
|
|
151
|
-
import path, { relative, resolve as resolve2 } from "node:path";
|
|
152
|
-
function getEntrypointName(entrypointsDir, inputPath) {
|
|
153
|
-
const relativePath = path.relative(entrypointsDir, inputPath);
|
|
154
|
-
const name = relativePath.split(/[\.\/]/, 2)[0];
|
|
155
|
-
return name;
|
|
156
|
-
}
|
|
157
|
-
function getEntrypointOutputFile(entrypoint, ext) {
|
|
158
|
-
return resolve2(entrypoint.outputDir, `${entrypoint.name}${ext}`);
|
|
159
|
-
}
|
|
160
|
-
function getEntrypointBundlePath(entrypoint, outDir, ext) {
|
|
161
|
-
return relative(outDir, getEntrypointOutputFile(entrypoint, ext));
|
|
162
|
-
}
|
|
163
|
-
|
|
164
210
|
// src/core/vite-plugins/multipageMove.ts
|
|
211
|
+
import { dirname as dirname2, extname, resolve as resolve4 } from "node:path";
|
|
165
212
|
import fs, { ensureDir } from "fs-extra";
|
|
166
213
|
function multipageMove(entrypoints, config) {
|
|
167
214
|
return {
|
|
@@ -187,10 +234,10 @@ function multipageMove(entrypoints, config) {
|
|
|
187
234
|
);
|
|
188
235
|
continue;
|
|
189
236
|
}
|
|
190
|
-
const oldAbsPath =
|
|
191
|
-
const newAbsPath =
|
|
192
|
-
await ensureDir(
|
|
193
|
-
await fs.move(oldAbsPath, newAbsPath);
|
|
237
|
+
const oldAbsPath = resolve4(config.outDir, oldBundlePath);
|
|
238
|
+
const newAbsPath = resolve4(config.outDir, newBundlePath);
|
|
239
|
+
await ensureDir(dirname2(newAbsPath));
|
|
240
|
+
await fs.move(oldAbsPath, newAbsPath, { overwrite: true });
|
|
194
241
|
const renamedChunk = {
|
|
195
242
|
...bundle[oldBundlePath],
|
|
196
243
|
fileName: newBundlePath
|
|
@@ -202,47 +249,39 @@ function multipageMove(entrypoints, config) {
|
|
|
202
249
|
};
|
|
203
250
|
}
|
|
204
251
|
|
|
205
|
-
// src/core/vite-plugins/
|
|
206
|
-
import {
|
|
207
|
-
|
|
208
|
-
|
|
252
|
+
// src/core/vite-plugins/unimport.ts
|
|
253
|
+
import { createUnimport } from "unimport";
|
|
254
|
+
|
|
255
|
+
// src/core/utils/auto-imports.ts
|
|
256
|
+
import { mergeConfig as mergeConfig2 } from "vite";
|
|
257
|
+
function getUnimportOptions(config) {
|
|
258
|
+
const defaultOptions = {
|
|
259
|
+
debugLog: config.logger.debug,
|
|
260
|
+
imports: [
|
|
261
|
+
{ name: "*", as: "browser", from: "webextension-polyfill" },
|
|
262
|
+
{ name: "defineConfig", from: "wxt" }
|
|
263
|
+
],
|
|
264
|
+
presets: [{ package: "wxt/client" }],
|
|
265
|
+
warn: config.logger.warn,
|
|
266
|
+
dirs: ["components", "composables", "hooks", "utils"]
|
|
267
|
+
};
|
|
268
|
+
return mergeConfig2(
|
|
269
|
+
defaultOptions,
|
|
270
|
+
config.imports
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// src/core/vite-plugins/unimport.ts
|
|
275
|
+
function unimport(config) {
|
|
276
|
+
const options = getUnimportOptions(config);
|
|
277
|
+
const unimport2 = createUnimport(options);
|
|
209
278
|
return {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
const originalUrl = `${server.origin}${id}`;
|
|
217
|
-
const name = getEntrypointName(config.entrypointsDir, id);
|
|
218
|
-
const url = `${server.origin}/${name}.html`;
|
|
219
|
-
const serverHtml = await server.transformIndexHtml(
|
|
220
|
-
url,
|
|
221
|
-
html,
|
|
222
|
-
originalUrl
|
|
223
|
-
);
|
|
224
|
-
const { document } = parseHTML(serverHtml);
|
|
225
|
-
const pointToDevServer = (querySelector, attr) => {
|
|
226
|
-
document.querySelectorAll(querySelector).forEach((element) => {
|
|
227
|
-
const src = element.getAttribute(attr);
|
|
228
|
-
if (!src)
|
|
229
|
-
return;
|
|
230
|
-
if (isAbsolute(src)) {
|
|
231
|
-
element.setAttribute(attr, server.origin + src);
|
|
232
|
-
} else if (src.startsWith(".")) {
|
|
233
|
-
const abs = resolve4(dirname2(id), src);
|
|
234
|
-
const pathname = relative2(config.root, abs);
|
|
235
|
-
element.setAttribute(attr, `${server.origin}/${pathname}`);
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
};
|
|
239
|
-
pointToDevServer("script[type=module]", "src");
|
|
240
|
-
pointToDevServer("link[rel=stylesheet]", "href");
|
|
241
|
-
const newHtml = document.toString();
|
|
242
|
-
config.logger.debug("Transformed " + id);
|
|
243
|
-
config.logger.debug("Old HTML:\n" + html);
|
|
244
|
-
config.logger.debug("New HTML:\n" + newHtml);
|
|
245
|
-
return newHtml;
|
|
279
|
+
name: "wxt:unimport",
|
|
280
|
+
async config() {
|
|
281
|
+
await unimport2.scanImportsFromDir(void 0, { cwd: config.srcDir });
|
|
282
|
+
},
|
|
283
|
+
async transform(code, id) {
|
|
284
|
+
return unimport2.injectImports(code, id);
|
|
246
285
|
}
|
|
247
286
|
};
|
|
248
287
|
}
|
|
@@ -267,10 +306,13 @@ function virtualEntrypoin(type, config) {
|
|
|
267
306
|
return;
|
|
268
307
|
const inputPath = id.replace(resolvedVirtualId, "");
|
|
269
308
|
const template = await fs2.readFile(
|
|
270
|
-
resolve5(
|
|
309
|
+
resolve5(
|
|
310
|
+
config.root,
|
|
311
|
+
`node_modules/wxt/dist/virtual-modules/${type}-entrypoint.js`
|
|
312
|
+
),
|
|
271
313
|
"utf-8"
|
|
272
314
|
);
|
|
273
|
-
return template.
|
|
315
|
+
return template.replace(`virtual:user-${type}`, inputPath);
|
|
274
316
|
}
|
|
275
317
|
};
|
|
276
318
|
}
|
|
@@ -334,6 +376,11 @@ function getGlobals(config) {
|
|
|
334
376
|
name: "__IS_OPERA__",
|
|
335
377
|
value: config.browser === "opera",
|
|
336
378
|
type: `boolean`
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
name: "__COMMAND__",
|
|
382
|
+
value: config.command,
|
|
383
|
+
type: `"build" | "serve"`
|
|
337
384
|
}
|
|
338
385
|
];
|
|
339
386
|
}
|
|
@@ -378,7 +425,7 @@ async function getInternalConfig(config, command) {
|
|
|
378
425
|
path2.resolve(root, config.configFile ?? "wxt.config.ts")
|
|
379
426
|
);
|
|
380
427
|
}
|
|
381
|
-
const merged =
|
|
428
|
+
const merged = vite2.mergeConfig(
|
|
382
429
|
baseConfig,
|
|
383
430
|
userConfig
|
|
384
431
|
);
|
|
@@ -401,7 +448,7 @@ async function getInternalConfig(config, command) {
|
|
|
401
448
|
};
|
|
402
449
|
finalConfig.vite.root = root;
|
|
403
450
|
finalConfig.vite.configFile = false;
|
|
404
|
-
finalConfig.vite.logLevel = "
|
|
451
|
+
finalConfig.vite.logLevel = "warn";
|
|
405
452
|
finalConfig.vite.build ??= {};
|
|
406
453
|
finalConfig.vite.build.outDir = outDir;
|
|
407
454
|
finalConfig.vite.build.emptyOutDir = false;
|
|
@@ -415,6 +462,7 @@ async function getInternalConfig(config, command) {
|
|
|
415
462
|
finalConfig.vite.plugins.push(
|
|
416
463
|
virtualEntrypoin("content-script", finalConfig)
|
|
417
464
|
);
|
|
465
|
+
finalConfig.vite.plugins.push(devServerGlobals(finalConfig));
|
|
418
466
|
finalConfig.vite.define ??= {};
|
|
419
467
|
getGlobals(finalConfig).forEach((global) => {
|
|
420
468
|
finalConfig.vite.define[global.name] = JSON.stringify(global.value);
|
|
@@ -422,27 +470,258 @@ async function getInternalConfig(config, command) {
|
|
|
422
470
|
return finalConfig;
|
|
423
471
|
}
|
|
424
472
|
|
|
425
|
-
// src/
|
|
426
|
-
import
|
|
473
|
+
// src/index.ts
|
|
474
|
+
import pc3 from "picocolors";
|
|
475
|
+
import * as vite6 from "vite";
|
|
476
|
+
|
|
477
|
+
// src/core/utils/arrays.ts
|
|
478
|
+
function every(array, predicate) {
|
|
479
|
+
for (let i = 0; i < array.length; i++)
|
|
480
|
+
if (!predicate(array[i], i))
|
|
481
|
+
return false;
|
|
482
|
+
return true;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// src/core/utils/detectDevChanges.ts
|
|
486
|
+
function detectDevChanges(changedFiles, currentOutput) {
|
|
487
|
+
if (currentOutput == null)
|
|
488
|
+
return { type: "no-change" };
|
|
489
|
+
const changedSteps = new Set(
|
|
490
|
+
changedFiles.flatMap(
|
|
491
|
+
(changedFile) => findEffectedSteps(changedFile, currentOutput)
|
|
492
|
+
)
|
|
493
|
+
);
|
|
494
|
+
if (changedSteps.size === 0)
|
|
495
|
+
return { type: "no-change" };
|
|
496
|
+
const unchangedOutput = {
|
|
497
|
+
manifest: currentOutput.manifest,
|
|
498
|
+
steps: [],
|
|
499
|
+
publicAssets: []
|
|
500
|
+
};
|
|
501
|
+
const changedOutput = {
|
|
502
|
+
manifest: currentOutput.manifest,
|
|
503
|
+
steps: [],
|
|
504
|
+
publicAssets: []
|
|
505
|
+
};
|
|
506
|
+
for (const step of currentOutput.steps) {
|
|
507
|
+
if (changedSteps.has(step)) {
|
|
508
|
+
changedOutput.steps.push(step);
|
|
509
|
+
} else {
|
|
510
|
+
unchangedOutput.steps.push(step);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
for (const asset of currentOutput.publicAssets) {
|
|
514
|
+
if (changedSteps.has(asset)) {
|
|
515
|
+
changedOutput.publicAssets.push(asset);
|
|
516
|
+
} else {
|
|
517
|
+
unchangedOutput.publicAssets.push(asset);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
const isOnlyHtmlChanges = changedFiles.length > 0 && every(changedFiles, ([_, file]) => file.endsWith(".html"));
|
|
521
|
+
if (isOnlyHtmlChanges) {
|
|
522
|
+
return {
|
|
523
|
+
type: "html-reload",
|
|
524
|
+
cachedOutput: unchangedOutput,
|
|
525
|
+
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
const isOnlyContentScripts = changedOutput.steps.length > 0 && every(
|
|
529
|
+
changedOutput.steps.flatMap((step) => step.entrypoints),
|
|
530
|
+
(entry) => entry.type === "content-script"
|
|
531
|
+
);
|
|
532
|
+
if (isOnlyContentScripts) {
|
|
533
|
+
return {
|
|
534
|
+
type: "content-script-reload",
|
|
535
|
+
cachedOutput: unchangedOutput,
|
|
536
|
+
changedSteps: changedOutput.steps,
|
|
537
|
+
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
return {
|
|
541
|
+
type: "extension-reload",
|
|
542
|
+
cachedOutput: unchangedOutput,
|
|
543
|
+
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
function findEffectedSteps(changedFile, currentOutput) {
|
|
547
|
+
const changes = [];
|
|
548
|
+
const changedPath = changedFile[1];
|
|
549
|
+
const isChunkEffected = (chunk) => (
|
|
550
|
+
// If it's an HTML file with the same path, is is effected because HTML files need to be pre-rendered
|
|
551
|
+
// TODO: use bundle path to support `<name>/index.html`?
|
|
552
|
+
chunk.type === "asset" && changedPath.endsWith(chunk.fileName) || // If it's a chunk that depends on the changed file, it is effected
|
|
553
|
+
chunk.type === "chunk" && chunk.moduleIds.includes(changedPath)
|
|
554
|
+
);
|
|
555
|
+
for (const step of currentOutput.steps) {
|
|
556
|
+
const effectedChunk = step.chunks.find((chunk) => isChunkEffected(chunk));
|
|
557
|
+
if (effectedChunk)
|
|
558
|
+
changes.push(step);
|
|
559
|
+
}
|
|
560
|
+
const effectedAsset = currentOutput.publicAssets.find(
|
|
561
|
+
(chunk) => isChunkEffected(chunk)
|
|
562
|
+
);
|
|
563
|
+
if (effectedAsset)
|
|
564
|
+
changes.push(effectedAsset);
|
|
565
|
+
return changes;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// src/index.ts
|
|
569
|
+
import { Mutex } from "async-mutex";
|
|
570
|
+
import { consola as consola3 } from "consola";
|
|
571
|
+
import { relative as relative6 } from "node:path";
|
|
572
|
+
|
|
573
|
+
// src/core/build/buildEntrypoints.ts
|
|
574
|
+
import * as vite3 from "vite";
|
|
575
|
+
|
|
576
|
+
// src/core/utils/removeEmptyDirs.ts
|
|
427
577
|
import fs4 from "fs-extra";
|
|
428
|
-
import
|
|
429
|
-
|
|
430
|
-
|
|
578
|
+
import path3 from "path";
|
|
579
|
+
async function removeEmptyDirs(dir) {
|
|
580
|
+
const files = await fs4.readdir(dir);
|
|
581
|
+
for (const file of files) {
|
|
582
|
+
const filePath = path3.join(dir, file);
|
|
583
|
+
const stats = await fs4.stat(filePath);
|
|
584
|
+
if (stats.isDirectory()) {
|
|
585
|
+
await removeEmptyDirs(filePath);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
try {
|
|
589
|
+
await fs4.rmdir(dir);
|
|
590
|
+
} catch {
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// src/core/build/buildEntrypoints.ts
|
|
431
595
|
import glob from "fast-glob";
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
await
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
596
|
+
import fs5 from "fs-extra";
|
|
597
|
+
import { dirname as dirname4, resolve as resolve8 } from "path";
|
|
598
|
+
async function buildEntrypoints(groups, config) {
|
|
599
|
+
const steps = [];
|
|
600
|
+
for (const group of groups) {
|
|
601
|
+
const step = Array.isArray(group) ? await buildMultipleEntrypoints(group, config) : await buildSingleEntrypoint(group, config);
|
|
602
|
+
steps.push(step);
|
|
603
|
+
}
|
|
604
|
+
const publicAssets = await copyPublicDirectory(config);
|
|
605
|
+
await removeEmptyDirs(config.outDir);
|
|
606
|
+
return { publicAssets, steps };
|
|
607
|
+
}
|
|
608
|
+
async function buildSingleEntrypoint(entrypoint, config) {
|
|
609
|
+
const isVirtual = ["background", "content-script"].includes(entrypoint.type);
|
|
610
|
+
const entry = isVirtual ? `virtual:wxt-${entrypoint.type}?${entrypoint.inputPath}` : entrypoint.inputPath;
|
|
611
|
+
const libMode = {
|
|
612
|
+
build: {
|
|
613
|
+
lib: {
|
|
614
|
+
entry,
|
|
615
|
+
formats: ["iife"],
|
|
616
|
+
name: entrypoint.name,
|
|
617
|
+
fileName: entrypoint.name
|
|
618
|
+
},
|
|
619
|
+
rollupOptions: {
|
|
620
|
+
output: {
|
|
621
|
+
// There's only a single output for this build, so we use the desired bundle path for the
|
|
622
|
+
// entry output (like "content-scripts/overlay.js")
|
|
623
|
+
entryFileNames: getEntrypointBundlePath(
|
|
624
|
+
entrypoint,
|
|
625
|
+
config.outDir,
|
|
626
|
+
".js"
|
|
627
|
+
),
|
|
628
|
+
// Output content script CSS to assets/ with a hash to prevent conflicts. Defaults to
|
|
629
|
+
// "[name].[ext]" in lib mode, which usually results in "style.css". That means multiple
|
|
630
|
+
// content scripts with styles would overwrite each other if it weren't changed below.
|
|
631
|
+
assetFileNames: `assets/${entrypoint.name}.[ext]`
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
const entryConfig = vite3.mergeConfig(
|
|
637
|
+
libMode,
|
|
638
|
+
config.vite
|
|
639
|
+
);
|
|
640
|
+
const result = await vite3.build(entryConfig);
|
|
641
|
+
return {
|
|
642
|
+
entrypoints: entrypoint,
|
|
643
|
+
chunks: getBuildOutputChunks(result)
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
async function buildMultipleEntrypoints(entrypoints, config) {
|
|
647
|
+
const multiPage = {
|
|
648
|
+
plugins: [multipageMove(entrypoints, config)],
|
|
649
|
+
build: {
|
|
650
|
+
rollupOptions: {
|
|
651
|
+
input: entrypoints.reduce((input, entry) => {
|
|
652
|
+
input[entry.name] = entry.inputPath;
|
|
653
|
+
return input;
|
|
654
|
+
}, {}),
|
|
655
|
+
output: {
|
|
656
|
+
// Include a hash to prevent conflicts
|
|
657
|
+
chunkFileNames: "chunks/[name]-[hash].js",
|
|
658
|
+
// Include a hash to prevent conflicts
|
|
659
|
+
entryFileNames: "chunks/[name]-[hash].js",
|
|
660
|
+
// We can't control the "name", so we need a hash to prevent conflicts
|
|
661
|
+
assetFileNames: "assets/[name]-[hash].[ext]"
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
const entryConfig = vite3.mergeConfig(
|
|
667
|
+
multiPage,
|
|
668
|
+
config.vite
|
|
669
|
+
);
|
|
670
|
+
const result = await vite3.build(entryConfig);
|
|
671
|
+
return {
|
|
672
|
+
entrypoints,
|
|
673
|
+
chunks: getBuildOutputChunks(result)
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
function getBuildOutputChunks(result) {
|
|
677
|
+
if ("on" in result)
|
|
678
|
+
throw Error("wxt does not support vite watch mode.");
|
|
679
|
+
if (Array.isArray(result))
|
|
680
|
+
return result.flatMap(({ output }) => output);
|
|
681
|
+
return result.output;
|
|
682
|
+
}
|
|
683
|
+
async function copyPublicDirectory(config) {
|
|
684
|
+
const publicAssets = [];
|
|
685
|
+
if (!await fs5.exists(config.publicDir))
|
|
686
|
+
return publicAssets;
|
|
687
|
+
const files = await glob("**/*", { cwd: config.publicDir });
|
|
688
|
+
for (const file of files) {
|
|
689
|
+
const srcPath = resolve8(config.publicDir, file);
|
|
690
|
+
const outPath = resolve8(config.outDir, file);
|
|
691
|
+
await fs5.ensureDir(dirname4(outPath));
|
|
692
|
+
await fs5.copyFile(srcPath, outPath);
|
|
693
|
+
publicAssets.push({
|
|
694
|
+
type: "asset",
|
|
695
|
+
fileName: file,
|
|
696
|
+
name: file,
|
|
697
|
+
needsCodeReference: false,
|
|
698
|
+
source: await fs5.readFile(srcPath)
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
return publicAssets;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// src/core/build/findEntrypoints.ts
|
|
705
|
+
import { relative as relative3, resolve as resolve9 } from "path";
|
|
706
|
+
import fs6 from "fs-extra";
|
|
707
|
+
import picomatch from "picomatch";
|
|
708
|
+
import { parseHTML as parseHTML2 } from "linkedom";
|
|
709
|
+
import JSON5 from "json5";
|
|
710
|
+
import glob2 from "fast-glob";
|
|
711
|
+
async function findEntrypoints(config) {
|
|
712
|
+
const relativePaths = await glob2("**/*", {
|
|
713
|
+
cwd: config.entrypointsDir
|
|
714
|
+
});
|
|
715
|
+
relativePaths.sort();
|
|
716
|
+
const pathGlobs = Object.keys(PATH_GLOB_TO_TYPE_MAP);
|
|
717
|
+
const existingNames = {};
|
|
718
|
+
const entrypoints = [];
|
|
719
|
+
await Promise.all(
|
|
720
|
+
relativePaths.map(async (relativePath) => {
|
|
721
|
+
const path5 = resolve9(config.entrypointsDir, relativePath);
|
|
722
|
+
const matchingGlob = pathGlobs.find(
|
|
723
|
+
(glob3) => picomatch.isMatch(relativePath, glob3)
|
|
724
|
+
);
|
|
446
725
|
if (matchingGlob == null) {
|
|
447
726
|
return config.logger.warn(
|
|
448
727
|
`${relativePath} does not match any known entrypoint. Known entrypoints:
|
|
@@ -499,7 +778,7 @@ ${JSON.stringify(
|
|
|
499
778
|
}
|
|
500
779
|
async function getPopupEntrypoint(config, path5) {
|
|
501
780
|
const options = {};
|
|
502
|
-
const content = await
|
|
781
|
+
const content = await fs6.readFile(path5, "utf-8");
|
|
503
782
|
const { document } = parseHTML2(content);
|
|
504
783
|
const title = document.querySelector("title");
|
|
505
784
|
if (title != null)
|
|
@@ -529,7 +808,7 @@ async function getPopupEntrypoint(config, path5) {
|
|
|
529
808
|
}
|
|
530
809
|
async function getOptionsEntrypoint(config, path5) {
|
|
531
810
|
const options = {};
|
|
532
|
-
const content = await
|
|
811
|
+
const content = await fs6.readFile(path5, "utf-8");
|
|
533
812
|
const { document } = parseHTML2(content);
|
|
534
813
|
const openInTabContent = document.querySelector("meta[name='manifest.open_in_tab']")?.getAttribute("content");
|
|
535
814
|
if (openInTabContent) {
|
|
@@ -576,7 +855,7 @@ async function getContentScriptEntrypoint(config, name, path5) {
|
|
|
576
855
|
type: "content-script",
|
|
577
856
|
name: getEntrypointName(config.entrypointsDir, path5),
|
|
578
857
|
inputPath: path5,
|
|
579
|
-
outputDir:
|
|
858
|
+
outputDir: resolve9(config.outDir, "content-scripts"),
|
|
580
859
|
options
|
|
581
860
|
};
|
|
582
861
|
}
|
|
@@ -611,160 +890,112 @@ var PATH_GLOB_TO_TYPE_MAP = {
|
|
|
611
890
|
"*/*": "ignored"
|
|
612
891
|
};
|
|
613
892
|
|
|
614
|
-
// src/core/build/
|
|
615
|
-
import
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
function
|
|
619
|
-
|
|
620
|
-
const
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
let groupIndex = groupIndexMap[group];
|
|
627
|
-
if (groupIndex == null) {
|
|
628
|
-
groupIndex = groups.push([]) - 1;
|
|
629
|
-
groupIndexMap[group] = groupIndex;
|
|
630
|
-
}
|
|
631
|
-
groups[groupIndex].push(entry);
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
return groups;
|
|
635
|
-
}
|
|
636
|
-
var ENTRY_TYPE_TO_GROUP_MAP = {
|
|
637
|
-
sandbox: "sandbox-page",
|
|
638
|
-
popup: "extension-page",
|
|
639
|
-
newtab: "extension-page",
|
|
640
|
-
history: "extension-page",
|
|
641
|
-
options: "extension-page",
|
|
642
|
-
devtools: "extension-page",
|
|
643
|
-
bookmarks: "extension-page",
|
|
644
|
-
sidepanel: "extension-page",
|
|
645
|
-
"unlisted-page": "extension-page",
|
|
646
|
-
background: "no-group",
|
|
647
|
-
"content-script": "no-group",
|
|
648
|
-
"unlisted-script": "no-group"
|
|
649
|
-
};
|
|
650
|
-
|
|
651
|
-
// src/core/utils/removeEmptyDirs.ts
|
|
652
|
-
import fs5 from "fs-extra";
|
|
653
|
-
import path3 from "path";
|
|
654
|
-
async function removeEmptyDirs(dir) {
|
|
655
|
-
const files = await fs5.readdir(dir);
|
|
656
|
-
for (const file of files) {
|
|
657
|
-
const filePath = path3.join(dir, file);
|
|
658
|
-
const stats = await fs5.stat(filePath);
|
|
659
|
-
if (stats.isDirectory()) {
|
|
660
|
-
await removeEmptyDirs(filePath);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
try {
|
|
664
|
-
await fs5.rmdir(dir);
|
|
665
|
-
} catch {
|
|
666
|
-
}
|
|
893
|
+
// src/core/build/generateTypesDir.ts
|
|
894
|
+
import { createUnimport as createUnimport2 } from "unimport";
|
|
895
|
+
import fs7 from "fs-extra";
|
|
896
|
+
import { relative as relative4, resolve as resolve10 } from "path";
|
|
897
|
+
async function generateTypesDir(entrypoints, config) {
|
|
898
|
+
await fs7.ensureDir(config.typesDir);
|
|
899
|
+
const references = [];
|
|
900
|
+
references.push(await writeImportsDeclarationFile(config));
|
|
901
|
+
references.push(await writePathsDeclarationFile(entrypoints, config));
|
|
902
|
+
references.push(await writeGlobalsDeclarationFile(config));
|
|
903
|
+
const mainReference = await writeMainDeclarationFile(references, config);
|
|
904
|
+
await writeTsConfigFile(mainReference, config);
|
|
667
905
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
}
|
|
680
|
-
const publicOutput = await copyPublicDirectory(config);
|
|
681
|
-
outputs.push(publicOutput);
|
|
682
|
-
await removeEmptyDirs(config.outDir);
|
|
683
|
-
return outputs.flat();
|
|
906
|
+
async function writeImportsDeclarationFile(config) {
|
|
907
|
+
const filePath = resolve10(config.typesDir, "imports.d.ts");
|
|
908
|
+
const unimport2 = createUnimport2(getUnimportOptions(config));
|
|
909
|
+
await unimport2.scanImportsFromDir(void 0, { cwd: config.srcDir });
|
|
910
|
+
await fs7.writeFile(
|
|
911
|
+
filePath,
|
|
912
|
+
["// Generated by wxt", await unimport2.generateTypeDeclarations()].join(
|
|
913
|
+
"\n"
|
|
914
|
+
) + "\n"
|
|
915
|
+
);
|
|
916
|
+
return filePath;
|
|
684
917
|
}
|
|
685
|
-
async function
|
|
686
|
-
const
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
".js"
|
|
702
|
-
),
|
|
703
|
-
// Output content script CSS to assets/ with a hash to prevent conflicts. Defaults to
|
|
704
|
-
// "[name].[ext]" in lib mode, which usually results in "style.css". That means multiple
|
|
705
|
-
// content scripts with styles would overwrite each other if it weren't changed below.
|
|
706
|
-
assetFileNames: `assets/${entrypoint.name}-[hash].[ext]`
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
const entryConfig = vite2.mergeConfig(
|
|
712
|
-
libMode,
|
|
713
|
-
config.vite
|
|
918
|
+
async function writePathsDeclarationFile(entrypoints, config) {
|
|
919
|
+
const filePath = resolve10(config.typesDir, "paths.d.ts");
|
|
920
|
+
await fs7.writeFile(
|
|
921
|
+
filePath,
|
|
922
|
+
[
|
|
923
|
+
"// Generated by wxt",
|
|
924
|
+
"type EntrypointPath =",
|
|
925
|
+
...entrypoints.map((entry) => {
|
|
926
|
+
const path5 = getEntrypointBundlePath(
|
|
927
|
+
entry,
|
|
928
|
+
config.outDir,
|
|
929
|
+
entry.inputPath.endsWith(".html") ? ".html" : ".js"
|
|
930
|
+
);
|
|
931
|
+
return ` | "/${path5}"`;
|
|
932
|
+
}).sort()
|
|
933
|
+
].join("\n") + "\n"
|
|
714
934
|
);
|
|
715
|
-
|
|
716
|
-
return getBuildOutput(result);
|
|
935
|
+
return filePath;
|
|
717
936
|
}
|
|
718
|
-
async function
|
|
719
|
-
const
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
multiPage,
|
|
732
|
-
config.vite
|
|
937
|
+
async function writeGlobalsDeclarationFile(config) {
|
|
938
|
+
const filePath = resolve10(config.typesDir, "globals.d.ts");
|
|
939
|
+
const globals = getGlobals(config);
|
|
940
|
+
await fs7.writeFile(
|
|
941
|
+
filePath,
|
|
942
|
+
[
|
|
943
|
+
"// Generated by wxt",
|
|
944
|
+
"export {}",
|
|
945
|
+
"declare global {",
|
|
946
|
+
...globals.map((global) => ` const ${global.name}: ${global.type};`),
|
|
947
|
+
"}"
|
|
948
|
+
].join("\n") + "\n",
|
|
949
|
+
"utf-8"
|
|
733
950
|
);
|
|
734
|
-
|
|
735
|
-
return getBuildOutput(result);
|
|
951
|
+
return filePath;
|
|
736
952
|
}
|
|
737
|
-
function
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
953
|
+
async function writeMainDeclarationFile(references, config) {
|
|
954
|
+
const dir = config.wxtDir;
|
|
955
|
+
const filePath = resolve10(dir, "wxt.d.ts");
|
|
956
|
+
await fs7.writeFile(
|
|
957
|
+
filePath,
|
|
958
|
+
[
|
|
959
|
+
"// Generated by wxt",
|
|
960
|
+
...references.map(
|
|
961
|
+
(ref) => `/// <reference types="./${relative4(dir, ref)}" />`
|
|
962
|
+
)
|
|
963
|
+
].join("\n") + "\n"
|
|
964
|
+
);
|
|
965
|
+
return filePath;
|
|
743
966
|
}
|
|
744
|
-
async function
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
967
|
+
async function writeTsConfigFile(mainReference, config) {
|
|
968
|
+
const dir = config.wxtDir;
|
|
969
|
+
await fs7.writeFile(
|
|
970
|
+
resolve10(dir, "tsconfig.json"),
|
|
971
|
+
`{
|
|
972
|
+
"compilerOptions": {
|
|
973
|
+
"target": "ESNext",
|
|
974
|
+
"module": "ESNext",
|
|
975
|
+
"moduleResolution": "Bundler",
|
|
976
|
+
"noEmit": true,
|
|
977
|
+
"esModuleInterop": true,
|
|
978
|
+
"forceConsistentCasingInFileNames": true,
|
|
979
|
+
"resolveJsonModule": true,
|
|
980
|
+
|
|
981
|
+
/* Type Checking */
|
|
982
|
+
"strict": true,
|
|
983
|
+
|
|
984
|
+
/* Completeness */
|
|
985
|
+
"skipLibCheck": true
|
|
986
|
+
},
|
|
987
|
+
"include": [
|
|
988
|
+
"${relative4(dir, config.root)}/**/*",
|
|
989
|
+
"./${relative4(dir, mainReference)}"
|
|
990
|
+
],
|
|
991
|
+
"exclude": ["${relative4(dir, config.outBaseDir)}"]
|
|
992
|
+
}`
|
|
993
|
+
);
|
|
763
994
|
}
|
|
764
995
|
|
|
765
996
|
// src/core/utils/manifest.ts
|
|
766
|
-
import
|
|
767
|
-
import { resolve as
|
|
997
|
+
import fs8 from "fs-extra";
|
|
998
|
+
import { resolve as resolve11 } from "path";
|
|
768
999
|
|
|
769
1000
|
// src/core/utils/ContentSecurityPolicy.ts
|
|
770
1001
|
var ContentSecurityPolicy = class _ContentSecurityPolicy {
|
|
@@ -812,9 +1043,9 @@ var ContentSecurityPolicy = class _ContentSecurityPolicy {
|
|
|
812
1043
|
// src/core/utils/manifest.ts
|
|
813
1044
|
async function writeManifest(manifest, output, config) {
|
|
814
1045
|
const str = config.mode === "production" ? JSON.stringify(manifest) : JSON.stringify(manifest, null, 2);
|
|
815
|
-
await
|
|
816
|
-
await
|
|
817
|
-
output.unshift({
|
|
1046
|
+
await fs8.ensureDir(config.outDir);
|
|
1047
|
+
await fs8.writeFile(resolve11(config.outDir, "manifest.json"), str, "utf-8");
|
|
1048
|
+
output.publicAssets.unshift({
|
|
818
1049
|
type: "asset",
|
|
819
1050
|
fileName: "manifest.json",
|
|
820
1051
|
name: "manifest",
|
|
@@ -841,10 +1072,12 @@ async function generateMainfest(entrypoints, buildOutput, config) {
|
|
|
841
1072
|
addEntrypoints(manifest, entrypoints, buildOutput, config);
|
|
842
1073
|
if (config.command === "serve")
|
|
843
1074
|
addDevModeCsp(manifest, config);
|
|
1075
|
+
if (config.command === "serve")
|
|
1076
|
+
addDevModePermissions(manifest, config);
|
|
844
1077
|
return manifest;
|
|
845
1078
|
}
|
|
846
1079
|
async function getPackageJson(config) {
|
|
847
|
-
return await
|
|
1080
|
+
return await fs8.readJson(resolve11(config.root, "package.json"));
|
|
848
1081
|
}
|
|
849
1082
|
function simplifyVersion(versionName) {
|
|
850
1083
|
const version3 = /^((0|[1-9][0-9]{0,8})([.](0|[1-9][0-9]{0,8})){0,3}).*$/.exec(
|
|
@@ -997,23 +1230,23 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
|
|
|
997
1230
|
}
|
|
998
1231
|
}
|
|
999
1232
|
if (contentScripts?.length) {
|
|
1000
|
-
if (config.command === "serve") {
|
|
1001
|
-
const
|
|
1002
|
-
const hostPermissions = new Set(manifest[permissionsKey] ?? []);
|
|
1233
|
+
if (config.command === "serve" && config.manifestVersion === 3) {
|
|
1234
|
+
const hostPermissions = new Set(manifest.host_permissions ?? []);
|
|
1003
1235
|
contentScripts.forEach((script) => {
|
|
1004
1236
|
script.options.matches.forEach((matchPattern) => {
|
|
1005
1237
|
hostPermissions.add(matchPattern);
|
|
1006
1238
|
});
|
|
1007
1239
|
});
|
|
1008
|
-
|
|
1240
|
+
hostPermissions.forEach(
|
|
1241
|
+
(permission) => addHostPermission(manifest, permission)
|
|
1242
|
+
);
|
|
1009
1243
|
} else {
|
|
1010
1244
|
const hashToEntrypointsMap = contentScripts.reduce((map, script) => {
|
|
1011
1245
|
const hash = JSON.stringify(script.options);
|
|
1012
|
-
if (
|
|
1013
|
-
map.set(hash, [script]);
|
|
1014
|
-
} else {
|
|
1246
|
+
if (map.has(hash))
|
|
1015
1247
|
map.get(hash)?.push(script);
|
|
1016
|
-
|
|
1248
|
+
else
|
|
1249
|
+
map.set(hash, [script]);
|
|
1017
1250
|
return map;
|
|
1018
1251
|
}, /* @__PURE__ */ new Map());
|
|
1019
1252
|
manifest.content_scripts = Array.from(hashToEntrypointsMap.entries()).map(
|
|
@@ -1034,13 +1267,9 @@ function addDevModeCsp(manifest, config) {
|
|
|
1034
1267
|
const permission = `http://${config.server?.hostname ?? ""}/*`;
|
|
1035
1268
|
const allowedCsp = config.server?.origin ?? "http://localhost:*";
|
|
1036
1269
|
if (manifest.manifest_version === 3) {
|
|
1037
|
-
manifest
|
|
1038
|
-
if (!manifest.host_permissions.includes(permission))
|
|
1039
|
-
manifest.host_permissions.push(permission);
|
|
1270
|
+
addHostPermission(manifest, permission);
|
|
1040
1271
|
} else {
|
|
1041
|
-
manifest
|
|
1042
|
-
if (!manifest.permissions.includes(permission))
|
|
1043
|
-
manifest.permissions.push(permission);
|
|
1272
|
+
addPermission(manifest, permission);
|
|
1044
1273
|
}
|
|
1045
1274
|
const csp = new ContentSecurityPolicy(
|
|
1046
1275
|
manifest.manifest_version === 3 ? (
|
|
@@ -1058,12 +1287,17 @@ function addDevModeCsp(manifest, config) {
|
|
|
1058
1287
|
manifest.content_security_policy = csp.toString();
|
|
1059
1288
|
}
|
|
1060
1289
|
}
|
|
1290
|
+
function addDevModePermissions(manifest, config) {
|
|
1291
|
+
addPermission(manifest, "tabs");
|
|
1292
|
+
if (config.manifestVersion === 3)
|
|
1293
|
+
addPermission(manifest, "scripting");
|
|
1294
|
+
}
|
|
1061
1295
|
function getContentScriptCssFiles(contentScripts, buildOutput) {
|
|
1062
1296
|
const css = [];
|
|
1297
|
+
const allChunks = buildOutput.steps.flatMap((step) => step.chunks);
|
|
1063
1298
|
contentScripts.forEach((script) => {
|
|
1064
|
-
const
|
|
1065
|
-
|
|
1066
|
-
(chunk) => chunk.fileName.match(cssRegex)
|
|
1299
|
+
const relatedCss = allChunks.find(
|
|
1300
|
+
(chunk) => chunk.fileName === `assets/${script.name}.css`
|
|
1067
1301
|
);
|
|
1068
1302
|
if (relatedCss)
|
|
1069
1303
|
css.push(relatedCss.fileName);
|
|
@@ -1072,9 +1306,71 @@ function getContentScriptCssFiles(contentScripts, buildOutput) {
|
|
|
1072
1306
|
return css;
|
|
1073
1307
|
return void 0;
|
|
1074
1308
|
}
|
|
1309
|
+
function addPermission(manifest, permission) {
|
|
1310
|
+
manifest.permissions ??= [];
|
|
1311
|
+
if (manifest.permissions.includes(permission))
|
|
1312
|
+
return;
|
|
1313
|
+
manifest.permissions.push(permission);
|
|
1314
|
+
}
|
|
1315
|
+
function addHostPermission(manifest, hostPermission) {
|
|
1316
|
+
manifest.host_permissions ??= [];
|
|
1317
|
+
if (manifest.host_permissions.includes(hostPermission))
|
|
1318
|
+
return;
|
|
1319
|
+
manifest.host_permissions.push(hostPermission);
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
// src/core/build.ts
|
|
1323
|
+
import pc2 from "picocolors";
|
|
1324
|
+
import * as vite4 from "vite";
|
|
1325
|
+
import fs10 from "fs-extra";
|
|
1326
|
+
|
|
1327
|
+
// src/core/utils/groupEntrypoints.ts
|
|
1328
|
+
function groupEntrypoints(entrypoints) {
|
|
1329
|
+
const groupIndexMap = {};
|
|
1330
|
+
const groups = [];
|
|
1331
|
+
for (const entry of entrypoints) {
|
|
1332
|
+
const group = ENTRY_TYPE_TO_GROUP_MAP[entry.type];
|
|
1333
|
+
if (group === "no-group") {
|
|
1334
|
+
groups.push(entry);
|
|
1335
|
+
} else {
|
|
1336
|
+
let groupIndex = groupIndexMap[group];
|
|
1337
|
+
if (groupIndex == null) {
|
|
1338
|
+
groupIndex = groups.push([]) - 1;
|
|
1339
|
+
groupIndexMap[group] = groupIndex;
|
|
1340
|
+
}
|
|
1341
|
+
groups[groupIndex].push(entry);
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
return groups;
|
|
1345
|
+
}
|
|
1346
|
+
var ENTRY_TYPE_TO_GROUP_MAP = {
|
|
1347
|
+
sandbox: "sandbox-page",
|
|
1348
|
+
popup: "extension-page",
|
|
1349
|
+
newtab: "extension-page",
|
|
1350
|
+
history: "extension-page",
|
|
1351
|
+
options: "extension-page",
|
|
1352
|
+
devtools: "extension-page",
|
|
1353
|
+
bookmarks: "extension-page",
|
|
1354
|
+
sidepanel: "extension-page",
|
|
1355
|
+
"unlisted-page": "extension-page",
|
|
1356
|
+
background: "no-group",
|
|
1357
|
+
"content-script": "no-group",
|
|
1358
|
+
"unlisted-script": "no-group"
|
|
1359
|
+
};
|
|
1360
|
+
|
|
1361
|
+
// src/core/utils/formatDuration.ts
|
|
1362
|
+
function formatDuration(duration) {
|
|
1363
|
+
if (duration < 1e3)
|
|
1364
|
+
return `${duration} ms`;
|
|
1365
|
+
if (duration < 1e4)
|
|
1366
|
+
return `${(duration / 1e3).toFixed(3)} s`;
|
|
1367
|
+
if (duration < 6e4)
|
|
1368
|
+
return `${(duration / 1e3).toFixed(1)} s`;
|
|
1369
|
+
return `${(duration / 1e3).toFixed(0)} s`;
|
|
1370
|
+
}
|
|
1075
1371
|
|
|
1076
1372
|
// src/core/log/printBuildSummary.ts
|
|
1077
|
-
import path4, { extname as extname2, relative as
|
|
1373
|
+
import path4, { extname as extname2, relative as relative5, resolve as resolve12 } from "path";
|
|
1078
1374
|
|
|
1079
1375
|
// src/core/log/printTable.ts
|
|
1080
1376
|
function printTable(log, rows, gap = 2) {
|
|
@@ -1104,10 +1400,13 @@ function printTable(log, rows, gap = 2) {
|
|
|
1104
1400
|
|
|
1105
1401
|
// src/core/log/printBuildSummary.ts
|
|
1106
1402
|
import pc from "picocolors";
|
|
1107
|
-
import
|
|
1403
|
+
import fs9 from "fs-extra";
|
|
1108
1404
|
import { filesize } from "filesize";
|
|
1109
1405
|
async function printBuildSummary(output, config) {
|
|
1110
|
-
const chunks =
|
|
1406
|
+
const chunks = [
|
|
1407
|
+
...output.steps.flatMap((step) => step.chunks),
|
|
1408
|
+
...output.publicAssets
|
|
1409
|
+
].sort((l, r) => {
|
|
1111
1410
|
const lWeight = CHUNK_SORT_WEIGHTS[l.fileName] ?? CHUNK_SORT_WEIGHTS[extname2(l.fileName)] ?? DEFAULT_SORT_WEIGHT;
|
|
1112
1411
|
const rWeight = CHUNK_SORT_WEIGHTS[r.fileName] ?? CHUNK_SORT_WEIGHTS[extname2(r.fileName)] ?? DEFAULT_SORT_WEIGHT;
|
|
1113
1412
|
const diff = lWeight - rWeight;
|
|
@@ -1119,13 +1418,13 @@ async function printBuildSummary(output, config) {
|
|
|
1119
1418
|
const chunkRows = await Promise.all(
|
|
1120
1419
|
chunks.map(async (chunk, i) => {
|
|
1121
1420
|
const file = [
|
|
1122
|
-
|
|
1421
|
+
relative5(process.cwd(), config.outDir) + path4.sep,
|
|
1123
1422
|
chunk.fileName
|
|
1124
1423
|
];
|
|
1125
1424
|
const ext = extname2(chunk.fileName);
|
|
1126
1425
|
const prefix = i === chunks.length - 1 ? " \u2514\u2500" : " \u251C\u2500";
|
|
1127
1426
|
const color = CHUNK_COLORS[ext] ?? DEFAULT_COLOR;
|
|
1128
|
-
const stats = await
|
|
1427
|
+
const stats = await fs9.lstat(resolve12(config.outDir, chunk.fileName));
|
|
1129
1428
|
totalSize += stats.size;
|
|
1130
1429
|
const size = String(filesize(stats.size));
|
|
1131
1430
|
return [
|
|
@@ -1153,115 +1452,63 @@ var CHUNK_COLORS = {
|
|
|
1153
1452
|
".js": pc.cyan
|
|
1154
1453
|
};
|
|
1155
1454
|
|
|
1156
|
-
// src/
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
await fs9.ensureDir(config.typesDir);
|
|
1165
|
-
const references = [];
|
|
1166
|
-
references.push(await writeImportsDeclarationFile(config));
|
|
1167
|
-
references.push(await writePathsDeclarationFile(entrypoints, config));
|
|
1168
|
-
references.push(await writeGlobalsDeclarationFile(config));
|
|
1169
|
-
const mainReference = await writeMainDeclarationFile(references, config);
|
|
1170
|
-
await writeTsConfigFile(mainReference, config);
|
|
1171
|
-
}
|
|
1172
|
-
async function writeImportsDeclarationFile(config) {
|
|
1173
|
-
const filePath = resolve12(config.typesDir, "imports.d.ts");
|
|
1174
|
-
const unimport2 = createUnimport2(getUnimportOptions(config));
|
|
1175
|
-
await unimport2.scanImportsFromDir(void 0, { cwd: config.srcDir });
|
|
1176
|
-
await fs9.writeFile(
|
|
1177
|
-
filePath,
|
|
1178
|
-
["// Generated by wxt", await unimport2.generateTypeDeclarations()].join(
|
|
1179
|
-
"\n"
|
|
1180
|
-
) + "\n"
|
|
1181
|
-
);
|
|
1182
|
-
return filePath;
|
|
1183
|
-
}
|
|
1184
|
-
async function writePathsDeclarationFile(entrypoints, config) {
|
|
1185
|
-
const filePath = resolve12(config.typesDir, "paths.d.ts");
|
|
1186
|
-
await fs9.writeFile(
|
|
1187
|
-
filePath,
|
|
1188
|
-
[
|
|
1189
|
-
"// Generated by wxt",
|
|
1190
|
-
"type EntrypointPath =",
|
|
1191
|
-
...entrypoints.map((entry) => {
|
|
1192
|
-
const path5 = getEntrypointBundlePath(
|
|
1193
|
-
entry,
|
|
1194
|
-
config.outDir,
|
|
1195
|
-
entry.inputPath.endsWith(".html") ? ".html" : ".js"
|
|
1196
|
-
);
|
|
1197
|
-
return ` | "/${path5}"`;
|
|
1198
|
-
}).sort()
|
|
1199
|
-
].join("\n") + "\n"
|
|
1200
|
-
);
|
|
1201
|
-
return filePath;
|
|
1202
|
-
}
|
|
1203
|
-
async function writeGlobalsDeclarationFile(config) {
|
|
1204
|
-
const filePath = resolve12(config.typesDir, "globals.d.ts");
|
|
1205
|
-
const globals = getGlobals(config);
|
|
1206
|
-
await fs9.writeFile(
|
|
1207
|
-
filePath,
|
|
1208
|
-
[
|
|
1209
|
-
"// Generated by wxt",
|
|
1210
|
-
"export {}",
|
|
1211
|
-
"declare global {",
|
|
1212
|
-
...globals.map((global) => ` const ${global.name}: ${global.type};`),
|
|
1213
|
-
"}"
|
|
1214
|
-
].join("\n") + "\n",
|
|
1215
|
-
"utf-8"
|
|
1455
|
+
// src/core/build.ts
|
|
1456
|
+
async function buildInternal(config) {
|
|
1457
|
+
const verb = config.command === "serve" ? "Pre-rendering" : "Building";
|
|
1458
|
+
const target = `${config.browser}-mv${config.manifestVersion}`;
|
|
1459
|
+
config.logger.info(
|
|
1460
|
+
`${verb} ${pc2.cyan(target)} for ${pc2.cyan(config.mode)} with ${pc2.green(
|
|
1461
|
+
`Vite ${vite4.version}`
|
|
1462
|
+
)}`
|
|
1216
1463
|
);
|
|
1217
|
-
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
const
|
|
1221
|
-
const
|
|
1222
|
-
await
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
"// Generated by wxt",
|
|
1226
|
-
...references.map(
|
|
1227
|
-
(ref) => `/// <reference types="./${relative5(dir, ref)}" />`
|
|
1228
|
-
)
|
|
1229
|
-
].join("\n") + "\n"
|
|
1464
|
+
const startTime = Date.now();
|
|
1465
|
+
await fs10.rm(config.outDir, { recursive: true, force: true });
|
|
1466
|
+
await fs10.ensureDir(config.outDir);
|
|
1467
|
+
const entrypoints = await findEntrypoints(config);
|
|
1468
|
+
const groups = groupEntrypoints(entrypoints);
|
|
1469
|
+
const { output } = await rebuild(config, groups);
|
|
1470
|
+
config.logger.success(
|
|
1471
|
+
`Built extension in ${formatDuration(Date.now() - startTime)}`
|
|
1230
1472
|
);
|
|
1231
|
-
|
|
1473
|
+
await printBuildSummary(output, config);
|
|
1474
|
+
return output;
|
|
1232
1475
|
}
|
|
1233
|
-
async function
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
"strict": true,
|
|
1249
|
-
|
|
1250
|
-
/* Completeness */
|
|
1251
|
-
"skipLibCheck": true
|
|
1252
|
-
},
|
|
1253
|
-
"include": [
|
|
1254
|
-
"${relative5(dir, config.root)}/**/*",
|
|
1255
|
-
"./${relative5(dir, mainReference)}"
|
|
1256
|
-
],
|
|
1257
|
-
"exclude": ["${relative5(dir, config.outBaseDir)}"]
|
|
1258
|
-
}`
|
|
1476
|
+
async function rebuild(config, entrypointGroups, existingOutput = {
|
|
1477
|
+
steps: [],
|
|
1478
|
+
publicAssets: []
|
|
1479
|
+
}) {
|
|
1480
|
+
const allEntrypoints = await findEntrypoints(config);
|
|
1481
|
+
await generateTypesDir(allEntrypoints, config);
|
|
1482
|
+
const newOutput = await buildEntrypoints(entrypointGroups, config);
|
|
1483
|
+
const mergedOutput = {
|
|
1484
|
+
steps: [...existingOutput.steps, ...newOutput.steps],
|
|
1485
|
+
publicAssets: [...existingOutput.publicAssets, ...newOutput.publicAssets]
|
|
1486
|
+
};
|
|
1487
|
+
const newManifest = await generateMainfest(
|
|
1488
|
+
allEntrypoints,
|
|
1489
|
+
mergedOutput,
|
|
1490
|
+
config
|
|
1259
1491
|
);
|
|
1492
|
+
const finalOutput = {
|
|
1493
|
+
manifest: newManifest,
|
|
1494
|
+
...newOutput
|
|
1495
|
+
};
|
|
1496
|
+
await writeManifest(newManifest, finalOutput, config);
|
|
1497
|
+
return {
|
|
1498
|
+
output: {
|
|
1499
|
+
manifest: newManifest,
|
|
1500
|
+
steps: [...existingOutput.steps, ...finalOutput.steps],
|
|
1501
|
+
publicAssets: [
|
|
1502
|
+
...existingOutput.publicAssets,
|
|
1503
|
+
...finalOutput.publicAssets
|
|
1504
|
+
]
|
|
1505
|
+
},
|
|
1506
|
+
manifest: newManifest
|
|
1507
|
+
};
|
|
1260
1508
|
}
|
|
1261
1509
|
|
|
1262
|
-
// src/
|
|
1263
|
-
import
|
|
1264
|
-
import * as vite3 from "vite";
|
|
1510
|
+
// src/core/server.ts
|
|
1511
|
+
import * as vite5 from "vite";
|
|
1265
1512
|
|
|
1266
1513
|
// src/core/utils/findOpenPort.ts
|
|
1267
1514
|
import net from "node:net";
|
|
@@ -1286,17 +1533,6 @@ function findOpenPortRecursive(port, startPort, endPort) {
|
|
|
1286
1533
|
});
|
|
1287
1534
|
}
|
|
1288
1535
|
|
|
1289
|
-
// src/core/utils/formatDuration.ts
|
|
1290
|
-
function formatDuration(duration) {
|
|
1291
|
-
if (duration < 1e3)
|
|
1292
|
-
return `${duration} ms`;
|
|
1293
|
-
if (duration < 1e4)
|
|
1294
|
-
return `${(duration / 1e3).toFixed(3)} s`;
|
|
1295
|
-
if (duration < 6e4)
|
|
1296
|
-
return `${(duration / 1e3).toFixed(1)} s`;
|
|
1297
|
-
return `${(duration / 1e3).toFixed(0)} s`;
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
1536
|
// src/core/runners/createWebExtRunner.ts
|
|
1301
1537
|
function createWebExtRunner() {
|
|
1302
1538
|
let runner;
|
|
@@ -1354,8 +1590,93 @@ function createWebExtRunner() {
|
|
|
1354
1590
|
var WARN_LOG_LEVEL = 40;
|
|
1355
1591
|
var ERROR_LOG_LEVEL = 50;
|
|
1356
1592
|
|
|
1593
|
+
// src/core/server.ts
|
|
1594
|
+
async function getServerInfo() {
|
|
1595
|
+
const port = await findOpenPort(3e3, 3010);
|
|
1596
|
+
const hostname = "localhost";
|
|
1597
|
+
const origin = `http://${hostname}:${port}`;
|
|
1598
|
+
const serverConfig = {
|
|
1599
|
+
server: {
|
|
1600
|
+
origin
|
|
1601
|
+
}
|
|
1602
|
+
};
|
|
1603
|
+
return {
|
|
1604
|
+
port,
|
|
1605
|
+
hostname,
|
|
1606
|
+
origin,
|
|
1607
|
+
viteServerConfig: serverConfig
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
async function setupServer(serverInfo, config) {
|
|
1611
|
+
const runner = createWebExtRunner();
|
|
1612
|
+
const viteServer = await vite5.createServer(
|
|
1613
|
+
vite5.mergeConfig(serverInfo, config.vite)
|
|
1614
|
+
);
|
|
1615
|
+
const start = async () => {
|
|
1616
|
+
await viteServer.listen(server.port);
|
|
1617
|
+
config.logger.success(`Started dev server @ ${serverInfo.origin}`);
|
|
1618
|
+
server.currentOutput = await buildInternal(config);
|
|
1619
|
+
config.logger.info("Opening browser...");
|
|
1620
|
+
await runner.openBrowser(config);
|
|
1621
|
+
config.logger.success("Opened!");
|
|
1622
|
+
};
|
|
1623
|
+
const reloadExtension = () => {
|
|
1624
|
+
viteServer.ws.send("wxt:reload-extension");
|
|
1625
|
+
};
|
|
1626
|
+
const reloadPage = (path5) => {
|
|
1627
|
+
viteServer.ws.send("wxt:reload-page", path5);
|
|
1628
|
+
};
|
|
1629
|
+
const reloadContentScript = (contentScript) => {
|
|
1630
|
+
viteServer.ws.send("wxt:reload-content-script", contentScript);
|
|
1631
|
+
};
|
|
1632
|
+
const server = {
|
|
1633
|
+
...viteServer,
|
|
1634
|
+
start,
|
|
1635
|
+
currentOutput: {
|
|
1636
|
+
manifest: {
|
|
1637
|
+
manifest_version: 3,
|
|
1638
|
+
name: "",
|
|
1639
|
+
version: ""
|
|
1640
|
+
},
|
|
1641
|
+
publicAssets: [],
|
|
1642
|
+
steps: []
|
|
1643
|
+
},
|
|
1644
|
+
port: serverInfo.port,
|
|
1645
|
+
hostname: serverInfo.hostname,
|
|
1646
|
+
origin: serverInfo.origin,
|
|
1647
|
+
reloadExtension,
|
|
1648
|
+
reloadPage,
|
|
1649
|
+
reloadContentScript
|
|
1650
|
+
};
|
|
1651
|
+
return server;
|
|
1652
|
+
}
|
|
1653
|
+
function reloadContentScripts(steps, config, server) {
|
|
1654
|
+
if (config.manifestVersion === 3) {
|
|
1655
|
+
steps.forEach((step) => {
|
|
1656
|
+
const entry = step.entrypoints;
|
|
1657
|
+
if (Array.isArray(entry) || entry.type !== "content-script")
|
|
1658
|
+
return;
|
|
1659
|
+
const js = [getEntrypointBundlePath(entry, config.outDir, ".js")];
|
|
1660
|
+
const css = getContentScriptCssFiles([entry], server.currentOutput);
|
|
1661
|
+
server.reloadContentScript({
|
|
1662
|
+
js,
|
|
1663
|
+
css,
|
|
1664
|
+
...entry.options
|
|
1665
|
+
});
|
|
1666
|
+
});
|
|
1667
|
+
} else {
|
|
1668
|
+
server.reloadExtension();
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
function reloadHtmlPages(groups, server, config) {
|
|
1672
|
+
groups.flat().forEach((entry) => {
|
|
1673
|
+
const path5 = getEntrypointBundlePath(entry, config.outDir, ".html");
|
|
1674
|
+
server.reloadPage(path5);
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1357
1678
|
// package.json
|
|
1358
|
-
var
|
|
1679
|
+
var version2 = "0.1.0";
|
|
1359
1680
|
|
|
1360
1681
|
// src/core/utils/defineConfig.ts
|
|
1361
1682
|
function defineConfig(config) {
|
|
@@ -1373,69 +1694,69 @@ async function build2(config) {
|
|
|
1373
1694
|
return await buildInternal(internalConfig);
|
|
1374
1695
|
}
|
|
1375
1696
|
async function createServer2(config) {
|
|
1376
|
-
const
|
|
1377
|
-
const
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
}
|
|
1383
|
-
};
|
|
1384
|
-
const internalConfig = await getInternalConfig(
|
|
1385
|
-
vite3.mergeConfig(serverConfig, config ?? {}),
|
|
1386
|
-
"serve"
|
|
1387
|
-
);
|
|
1388
|
-
const runner = createWebExtRunner();
|
|
1389
|
-
const viteServer = await vite3.createServer(internalConfig.vite);
|
|
1390
|
-
const server = {
|
|
1391
|
-
...viteServer,
|
|
1392
|
-
async listen(port2, isRestart) {
|
|
1393
|
-
const res = await viteServer.listen(port2, isRestart);
|
|
1394
|
-
if (!isRestart) {
|
|
1395
|
-
internalConfig.logger.success(`Started dev server @ ${origin}`);
|
|
1396
|
-
internalConfig.logger.info("Opening browser...");
|
|
1397
|
-
await runner.openBrowser(internalConfig);
|
|
1398
|
-
internalConfig.logger.success("Opened!");
|
|
1399
|
-
}
|
|
1400
|
-
return res;
|
|
1401
|
-
},
|
|
1402
|
-
logger: internalConfig.logger,
|
|
1403
|
-
port,
|
|
1404
|
-
hostname,
|
|
1405
|
-
origin
|
|
1697
|
+
const serverInfo = await getServerInfo();
|
|
1698
|
+
const getLatestInternalConfig = () => {
|
|
1699
|
+
const viteConfig = vite6.mergeConfig(
|
|
1700
|
+
serverInfo.viteServerConfig,
|
|
1701
|
+
config?.vite ?? {}
|
|
1702
|
+
);
|
|
1703
|
+
return getInternalConfig({ ...config, vite: viteConfig }, "serve");
|
|
1406
1704
|
};
|
|
1407
|
-
internalConfig
|
|
1705
|
+
let internalConfig = await getLatestInternalConfig();
|
|
1706
|
+
const server = await setupServer(serverInfo, internalConfig);
|
|
1408
1707
|
internalConfig.server = server;
|
|
1409
|
-
|
|
1708
|
+
const fileChangedMutex = new Mutex();
|
|
1709
|
+
const changeQueue = [];
|
|
1710
|
+
server.ws.on("wxt:background-initialized", () => {
|
|
1711
|
+
reloadContentScripts(server.currentOutput.steps, internalConfig, server);
|
|
1712
|
+
});
|
|
1713
|
+
server.watcher.on("all", async (event, path5, _stats) => {
|
|
1714
|
+
if (path5.startsWith(internalConfig.outBaseDir))
|
|
1715
|
+
return;
|
|
1716
|
+
changeQueue.push([event, path5]);
|
|
1717
|
+
await fileChangedMutex.runExclusive(async () => {
|
|
1718
|
+
const fileChanges = changeQueue.splice(0, changeQueue.length);
|
|
1719
|
+
const changes = detectDevChanges(fileChanges, server.currentOutput);
|
|
1720
|
+
if (changes.type === "no-change")
|
|
1721
|
+
return;
|
|
1722
|
+
consola3.info(
|
|
1723
|
+
`Changed: ${Array.from(new Set(fileChanges.map((change) => change[1]))).map((file) => pc3.dim(relative6(internalConfig.root, file))).join(", ")}`
|
|
1724
|
+
);
|
|
1725
|
+
const rebuiltNames = changes.rebuildGroups.flat().map((entry) => {
|
|
1726
|
+
return pc3.cyan(
|
|
1727
|
+
relative6(internalConfig.outDir, getEntrypointOutputFile(entry, ""))
|
|
1728
|
+
);
|
|
1729
|
+
}).join(pc3.dim(", "));
|
|
1730
|
+
internalConfig = await getLatestInternalConfig();
|
|
1731
|
+
internalConfig.server = server;
|
|
1732
|
+
const { output: newOutput } = await rebuild(
|
|
1733
|
+
internalConfig,
|
|
1734
|
+
// TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
|
|
1735
|
+
changes.rebuildGroups,
|
|
1736
|
+
changes.cachedOutput
|
|
1737
|
+
);
|
|
1738
|
+
server.currentOutput = newOutput;
|
|
1739
|
+
switch (changes.type) {
|
|
1740
|
+
case "extension-reload":
|
|
1741
|
+
server.reloadExtension();
|
|
1742
|
+
break;
|
|
1743
|
+
case "html-reload":
|
|
1744
|
+
reloadHtmlPages(changes.rebuildGroups, server, internalConfig);
|
|
1745
|
+
break;
|
|
1746
|
+
case "content-script-reload":
|
|
1747
|
+
reloadContentScripts(changes.changedSteps, internalConfig, server);
|
|
1748
|
+
break;
|
|
1749
|
+
}
|
|
1750
|
+
consola3.success(`Reloaded: ${rebuiltNames}`);
|
|
1751
|
+
});
|
|
1752
|
+
});
|
|
1410
1753
|
return server;
|
|
1411
1754
|
}
|
|
1412
|
-
async function buildInternal(config) {
|
|
1413
|
-
const verb = config.command === "serve" ? "Pre-rendering" : "Building";
|
|
1414
|
-
const target = `${config.browser}-mv${config.manifestVersion}`;
|
|
1415
|
-
config.logger.info(
|
|
1416
|
-
`${verb} ${pc2.cyan(target)} for ${pc2.cyan(config.mode)} with ${pc2.green(
|
|
1417
|
-
`Vite ${vite3.version}`
|
|
1418
|
-
)}`
|
|
1419
|
-
);
|
|
1420
|
-
const startTime = Date.now();
|
|
1421
|
-
await fs10.rm(config.outDir, { recursive: true, force: true });
|
|
1422
|
-
await fs10.ensureDir(config.outDir);
|
|
1423
|
-
const entrypoints = await findEntrypoints(config);
|
|
1424
|
-
await generateTypesDir(entrypoints, config);
|
|
1425
|
-
const output = await buildEntrypoints(entrypoints, config);
|
|
1426
|
-
const manifest = await generateMainfest(entrypoints, output, config);
|
|
1427
|
-
await writeManifest(manifest, output, config);
|
|
1428
|
-
config.logger.success(
|
|
1429
|
-
`Built extension in ${formatDuration(Date.now() - startTime)}`
|
|
1430
|
-
);
|
|
1431
|
-
await printBuildSummary(output, config);
|
|
1432
|
-
return output;
|
|
1433
|
-
}
|
|
1434
1755
|
export {
|
|
1435
1756
|
build2 as build,
|
|
1436
1757
|
createServer2 as createServer,
|
|
1437
1758
|
defineConfig,
|
|
1438
1759
|
defineRunnerConfig,
|
|
1439
|
-
version
|
|
1760
|
+
version2 as version
|
|
1440
1761
|
};
|
|
1441
1762
|
//# sourceMappingURL=index.js.map
|