wxt 0.0.2 → 0.1.1-alpha1
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 +3 -4
- package/dist/cli.cjs +603 -499
- package/dist/index.cjs +600 -500
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +17 -38
- package/dist/index.js +596 -495
- package/dist/index.js.map +1 -1
- package/dist/virtual-modules/background-entrypoint.js +52 -4
- package/dist/virtual-modules/background-entrypoint.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -8,25 +8,27 @@ import { consola } from "consola";
|
|
|
8
8
|
import createJITI from "jiti";
|
|
9
9
|
import transform from "jiti/dist/babel";
|
|
10
10
|
import { resolve } from "path";
|
|
11
|
-
import {
|
|
11
|
+
import { createUnimport } from "unimport";
|
|
12
|
+
import fs from "fs-extra";
|
|
12
13
|
async function importTsFile(root, path5) {
|
|
13
|
-
const
|
|
14
|
+
const unimport2 = createUnimport({});
|
|
15
|
+
await unimport2.scanImportsFromFile(
|
|
14
16
|
resolve(root, "node_modules/wxt/dist/client.js")
|
|
15
17
|
);
|
|
18
|
+
const text = await fs.readFile(path5, "utf-8");
|
|
19
|
+
const res = await unimport2.injectImports(text, path5);
|
|
20
|
+
const transformedText = res.code;
|
|
16
21
|
const jiti = createJITI(__filename, {
|
|
17
22
|
cache: false,
|
|
18
23
|
esmResolve: true,
|
|
19
24
|
interopDefault: true,
|
|
25
|
+
alias: {
|
|
26
|
+
"webextension-polyfill": "wxt"
|
|
27
|
+
},
|
|
20
28
|
transform(opts) {
|
|
29
|
+
if (opts.filename === path5)
|
|
30
|
+
opts.source = transformedText;
|
|
21
31
|
opts.source = opts.source.replace(/^import ['"].*\.css['"];?$/gm, "");
|
|
22
|
-
opts.source = opts.source.replace(
|
|
23
|
-
/^import\s+.*\s+from ['"]webextension-polyfill['"];?$/gm,
|
|
24
|
-
""
|
|
25
|
-
);
|
|
26
|
-
if (opts.filename === path5) {
|
|
27
|
-
const imports = clientImports.map((i) => `import { ${i.name} } from "${i.from}";`).join("\n") + "\n";
|
|
28
|
-
opts.source = imports + opts.source;
|
|
29
|
-
}
|
|
30
32
|
return transform(opts);
|
|
31
33
|
}
|
|
32
34
|
});
|
|
@@ -209,7 +211,7 @@ function download(config) {
|
|
|
209
211
|
|
|
210
212
|
// src/core/vite-plugins/multipageMove.ts
|
|
211
213
|
import { dirname as dirname2, extname, resolve as resolve4 } from "node:path";
|
|
212
|
-
import
|
|
214
|
+
import fs2, { ensureDir } from "fs-extra";
|
|
213
215
|
function multipageMove(entrypoints, config) {
|
|
214
216
|
return {
|
|
215
217
|
name: "wxt:multipage-move",
|
|
@@ -237,7 +239,7 @@ function multipageMove(entrypoints, config) {
|
|
|
237
239
|
const oldAbsPath = resolve4(config.outDir, oldBundlePath);
|
|
238
240
|
const newAbsPath = resolve4(config.outDir, newBundlePath);
|
|
239
241
|
await ensureDir(dirname2(newAbsPath));
|
|
240
|
-
await
|
|
242
|
+
await fs2.move(oldAbsPath, newAbsPath, { overwrite: true });
|
|
241
243
|
const renamedChunk = {
|
|
242
244
|
...bundle[oldBundlePath],
|
|
243
245
|
fileName: newBundlePath
|
|
@@ -250,7 +252,7 @@ function multipageMove(entrypoints, config) {
|
|
|
250
252
|
}
|
|
251
253
|
|
|
252
254
|
// src/core/vite-plugins/unimport.ts
|
|
253
|
-
import { createUnimport } from "unimport";
|
|
255
|
+
import { createUnimport as createUnimport2 } from "unimport";
|
|
254
256
|
|
|
255
257
|
// src/core/utils/auto-imports.ts
|
|
256
258
|
import { mergeConfig as mergeConfig2 } from "vite";
|
|
@@ -274,7 +276,7 @@ function getUnimportOptions(config) {
|
|
|
274
276
|
// src/core/vite-plugins/unimport.ts
|
|
275
277
|
function unimport(config) {
|
|
276
278
|
const options = getUnimportOptions(config);
|
|
277
|
-
const unimport2 =
|
|
279
|
+
const unimport2 = createUnimport2(options);
|
|
278
280
|
return {
|
|
279
281
|
name: "wxt:unimport",
|
|
280
282
|
async config() {
|
|
@@ -287,7 +289,7 @@ function unimport(config) {
|
|
|
287
289
|
}
|
|
288
290
|
|
|
289
291
|
// src/core/vite-plugins/virtualEntrypoint.ts
|
|
290
|
-
import
|
|
292
|
+
import fs3 from "fs-extra";
|
|
291
293
|
import { resolve as resolve5 } from "path";
|
|
292
294
|
function virtualEntrypoin(type, config) {
|
|
293
295
|
const virtualId = `virtual:wxt-${type}?`;
|
|
@@ -305,7 +307,7 @@ function virtualEntrypoin(type, config) {
|
|
|
305
307
|
if (!id.startsWith(resolvedVirtualId))
|
|
306
308
|
return;
|
|
307
309
|
const inputPath = id.replace(resolvedVirtualId, "");
|
|
308
|
-
const template = await
|
|
310
|
+
const template = await fs3.readFile(
|
|
309
311
|
resolve5(
|
|
310
312
|
config.root,
|
|
311
313
|
`node_modules/wxt/dist/virtual-modules/${type}-entrypoint.js`
|
|
@@ -318,7 +320,7 @@ function virtualEntrypoin(type, config) {
|
|
|
318
320
|
}
|
|
319
321
|
|
|
320
322
|
// src/core/utils/createFsCache.ts
|
|
321
|
-
import
|
|
323
|
+
import fs4, { ensureDir as ensureDir2 } from "fs-extra";
|
|
322
324
|
import { dirname as dirname3, resolve as resolve6 } from "path";
|
|
323
325
|
function createFsCache(wxtDir) {
|
|
324
326
|
const getPath = (key) => resolve6(wxtDir, "cache", encodeURIComponent(key));
|
|
@@ -326,12 +328,12 @@ function createFsCache(wxtDir) {
|
|
|
326
328
|
async set(key, value) {
|
|
327
329
|
const path5 = getPath(key);
|
|
328
330
|
await ensureDir2(dirname3(path5));
|
|
329
|
-
await
|
|
331
|
+
await fs4.writeFile(path5, value, "utf-8");
|
|
330
332
|
},
|
|
331
333
|
async get(key) {
|
|
332
334
|
const path5 = getPath(key);
|
|
333
335
|
try {
|
|
334
|
-
return await
|
|
336
|
+
return await fs4.readFile(path5, "utf-8");
|
|
335
337
|
} catch {
|
|
336
338
|
return void 0;
|
|
337
339
|
}
|
|
@@ -470,15 +472,246 @@ async function getInternalConfig(config, command) {
|
|
|
470
472
|
return finalConfig;
|
|
471
473
|
}
|
|
472
474
|
|
|
475
|
+
// src/index.ts
|
|
476
|
+
import pc3 from "picocolors";
|
|
477
|
+
import * as vite6 from "vite";
|
|
478
|
+
|
|
479
|
+
// src/core/utils/arrays.ts
|
|
480
|
+
function every(array, predicate) {
|
|
481
|
+
for (let i = 0; i < array.length; i++)
|
|
482
|
+
if (!predicate(array[i], i))
|
|
483
|
+
return false;
|
|
484
|
+
return true;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// src/core/utils/detectDevChanges.ts
|
|
488
|
+
function detectDevChanges(changedFiles, currentOutput) {
|
|
489
|
+
if (currentOutput == null)
|
|
490
|
+
return { type: "no-change" };
|
|
491
|
+
const changedSteps = new Set(
|
|
492
|
+
changedFiles.flatMap(
|
|
493
|
+
(changedFile) => findEffectedSteps(changedFile, currentOutput)
|
|
494
|
+
)
|
|
495
|
+
);
|
|
496
|
+
if (changedSteps.size === 0)
|
|
497
|
+
return { type: "no-change" };
|
|
498
|
+
const unchangedOutput = {
|
|
499
|
+
manifest: currentOutput.manifest,
|
|
500
|
+
steps: [],
|
|
501
|
+
publicAssets: []
|
|
502
|
+
};
|
|
503
|
+
const changedOutput = {
|
|
504
|
+
manifest: currentOutput.manifest,
|
|
505
|
+
steps: [],
|
|
506
|
+
publicAssets: []
|
|
507
|
+
};
|
|
508
|
+
for (const step of currentOutput.steps) {
|
|
509
|
+
if (changedSteps.has(step)) {
|
|
510
|
+
changedOutput.steps.push(step);
|
|
511
|
+
} else {
|
|
512
|
+
unchangedOutput.steps.push(step);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
for (const asset of currentOutput.publicAssets) {
|
|
516
|
+
if (changedSteps.has(asset)) {
|
|
517
|
+
changedOutput.publicAssets.push(asset);
|
|
518
|
+
} else {
|
|
519
|
+
unchangedOutput.publicAssets.push(asset);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
const isOnlyHtmlChanges = changedFiles.length > 0 && every(changedFiles, ([_, file]) => file.endsWith(".html"));
|
|
523
|
+
if (isOnlyHtmlChanges) {
|
|
524
|
+
return {
|
|
525
|
+
type: "html-reload",
|
|
526
|
+
cachedOutput: unchangedOutput,
|
|
527
|
+
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
const isOnlyContentScripts = changedOutput.steps.length > 0 && every(
|
|
531
|
+
changedOutput.steps.flatMap((step) => step.entrypoints),
|
|
532
|
+
(entry) => entry.type === "content-script"
|
|
533
|
+
);
|
|
534
|
+
if (isOnlyContentScripts) {
|
|
535
|
+
return {
|
|
536
|
+
type: "content-script-reload",
|
|
537
|
+
cachedOutput: unchangedOutput,
|
|
538
|
+
changedSteps: changedOutput.steps,
|
|
539
|
+
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
type: "extension-reload",
|
|
544
|
+
cachedOutput: unchangedOutput,
|
|
545
|
+
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function findEffectedSteps(changedFile, currentOutput) {
|
|
549
|
+
const changes = [];
|
|
550
|
+
const changedPath = changedFile[1];
|
|
551
|
+
const isChunkEffected = (chunk) => (
|
|
552
|
+
// If it's an HTML file with the same path, is is effected because HTML files need to be pre-rendered
|
|
553
|
+
// TODO: use bundle path to support `<name>/index.html`?
|
|
554
|
+
chunk.type === "asset" && changedPath.endsWith(chunk.fileName) || // If it's a chunk that depends on the changed file, it is effected
|
|
555
|
+
chunk.type === "chunk" && chunk.moduleIds.includes(changedPath)
|
|
556
|
+
);
|
|
557
|
+
for (const step of currentOutput.steps) {
|
|
558
|
+
const effectedChunk = step.chunks.find((chunk) => isChunkEffected(chunk));
|
|
559
|
+
if (effectedChunk)
|
|
560
|
+
changes.push(step);
|
|
561
|
+
}
|
|
562
|
+
const effectedAsset = currentOutput.publicAssets.find(
|
|
563
|
+
(chunk) => isChunkEffected(chunk)
|
|
564
|
+
);
|
|
565
|
+
if (effectedAsset)
|
|
566
|
+
changes.push(effectedAsset);
|
|
567
|
+
return changes;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// src/index.ts
|
|
571
|
+
import { Mutex } from "async-mutex";
|
|
572
|
+
import { consola as consola3 } from "consola";
|
|
573
|
+
import { relative as relative6 } from "node:path";
|
|
574
|
+
|
|
575
|
+
// src/core/build/buildEntrypoints.ts
|
|
576
|
+
import * as vite3 from "vite";
|
|
577
|
+
|
|
578
|
+
// src/core/utils/removeEmptyDirs.ts
|
|
579
|
+
import fs5 from "fs-extra";
|
|
580
|
+
import path3 from "path";
|
|
581
|
+
async function removeEmptyDirs(dir) {
|
|
582
|
+
const files = await fs5.readdir(dir);
|
|
583
|
+
for (const file of files) {
|
|
584
|
+
const filePath = path3.join(dir, file);
|
|
585
|
+
const stats = await fs5.stat(filePath);
|
|
586
|
+
if (stats.isDirectory()) {
|
|
587
|
+
await removeEmptyDirs(filePath);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
try {
|
|
591
|
+
await fs5.rmdir(dir);
|
|
592
|
+
} catch {
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// src/core/build/buildEntrypoints.ts
|
|
597
|
+
import glob from "fast-glob";
|
|
598
|
+
import fs6 from "fs-extra";
|
|
599
|
+
import { dirname as dirname4, resolve as resolve8 } from "path";
|
|
600
|
+
async function buildEntrypoints(groups, config) {
|
|
601
|
+
const steps = [];
|
|
602
|
+
for (const group of groups) {
|
|
603
|
+
const step = Array.isArray(group) ? await buildMultipleEntrypoints(group, config) : await buildSingleEntrypoint(group, config);
|
|
604
|
+
steps.push(step);
|
|
605
|
+
}
|
|
606
|
+
const publicAssets = await copyPublicDirectory(config);
|
|
607
|
+
await removeEmptyDirs(config.outDir);
|
|
608
|
+
return { publicAssets, steps };
|
|
609
|
+
}
|
|
610
|
+
async function buildSingleEntrypoint(entrypoint, config) {
|
|
611
|
+
const isVirtual = ["background", "content-script"].includes(entrypoint.type);
|
|
612
|
+
const entry = isVirtual ? `virtual:wxt-${entrypoint.type}?${entrypoint.inputPath}` : entrypoint.inputPath;
|
|
613
|
+
const libMode = {
|
|
614
|
+
build: {
|
|
615
|
+
lib: {
|
|
616
|
+
entry,
|
|
617
|
+
formats: ["iife"],
|
|
618
|
+
name: entrypoint.name,
|
|
619
|
+
fileName: entrypoint.name
|
|
620
|
+
},
|
|
621
|
+
rollupOptions: {
|
|
622
|
+
output: {
|
|
623
|
+
// There's only a single output for this build, so we use the desired bundle path for the
|
|
624
|
+
// entry output (like "content-scripts/overlay.js")
|
|
625
|
+
entryFileNames: getEntrypointBundlePath(
|
|
626
|
+
entrypoint,
|
|
627
|
+
config.outDir,
|
|
628
|
+
".js"
|
|
629
|
+
),
|
|
630
|
+
// Output content script CSS to assets/ with a hash to prevent conflicts. Defaults to
|
|
631
|
+
// "[name].[ext]" in lib mode, which usually results in "style.css". That means multiple
|
|
632
|
+
// content scripts with styles would overwrite each other if it weren't changed below.
|
|
633
|
+
assetFileNames: `assets/${entrypoint.name}.[ext]`
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
const entryConfig = vite3.mergeConfig(
|
|
639
|
+
libMode,
|
|
640
|
+
config.vite
|
|
641
|
+
);
|
|
642
|
+
const result = await vite3.build(entryConfig);
|
|
643
|
+
return {
|
|
644
|
+
entrypoints: entrypoint,
|
|
645
|
+
chunks: getBuildOutputChunks(result)
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
async function buildMultipleEntrypoints(entrypoints, config) {
|
|
649
|
+
const multiPage = {
|
|
650
|
+
plugins: [multipageMove(entrypoints, config)],
|
|
651
|
+
build: {
|
|
652
|
+
rollupOptions: {
|
|
653
|
+
input: entrypoints.reduce((input, entry) => {
|
|
654
|
+
input[entry.name] = entry.inputPath;
|
|
655
|
+
return input;
|
|
656
|
+
}, {}),
|
|
657
|
+
output: {
|
|
658
|
+
// Include a hash to prevent conflicts
|
|
659
|
+
chunkFileNames: "chunks/[name]-[hash].js",
|
|
660
|
+
// Include a hash to prevent conflicts
|
|
661
|
+
entryFileNames: "chunks/[name]-[hash].js",
|
|
662
|
+
// We can't control the "name", so we need a hash to prevent conflicts
|
|
663
|
+
assetFileNames: "assets/[name]-[hash].[ext]"
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
const entryConfig = vite3.mergeConfig(
|
|
669
|
+
multiPage,
|
|
670
|
+
config.vite
|
|
671
|
+
);
|
|
672
|
+
const result = await vite3.build(entryConfig);
|
|
673
|
+
return {
|
|
674
|
+
entrypoints,
|
|
675
|
+
chunks: getBuildOutputChunks(result)
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
function getBuildOutputChunks(result) {
|
|
679
|
+
if ("on" in result)
|
|
680
|
+
throw Error("wxt does not support vite watch mode.");
|
|
681
|
+
if (Array.isArray(result))
|
|
682
|
+
return result.flatMap(({ output }) => output);
|
|
683
|
+
return result.output;
|
|
684
|
+
}
|
|
685
|
+
async function copyPublicDirectory(config) {
|
|
686
|
+
const publicAssets = [];
|
|
687
|
+
if (!await fs6.exists(config.publicDir))
|
|
688
|
+
return publicAssets;
|
|
689
|
+
const files = await glob("**/*", { cwd: config.publicDir });
|
|
690
|
+
for (const file of files) {
|
|
691
|
+
const srcPath = resolve8(config.publicDir, file);
|
|
692
|
+
const outPath = resolve8(config.outDir, file);
|
|
693
|
+
await fs6.ensureDir(dirname4(outPath));
|
|
694
|
+
await fs6.copyFile(srcPath, outPath);
|
|
695
|
+
publicAssets.push({
|
|
696
|
+
type: "asset",
|
|
697
|
+
fileName: file,
|
|
698
|
+
name: file,
|
|
699
|
+
needsCodeReference: false,
|
|
700
|
+
source: await fs6.readFile(srcPath)
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
return publicAssets;
|
|
704
|
+
}
|
|
705
|
+
|
|
473
706
|
// src/core/build/findEntrypoints.ts
|
|
474
|
-
import { relative as relative3, resolve as
|
|
475
|
-
import
|
|
707
|
+
import { relative as relative3, resolve as resolve9 } from "path";
|
|
708
|
+
import fs7 from "fs-extra";
|
|
476
709
|
import picomatch from "picomatch";
|
|
477
710
|
import { parseHTML as parseHTML2 } from "linkedom";
|
|
478
711
|
import JSON5 from "json5";
|
|
479
|
-
import
|
|
712
|
+
import glob2 from "fast-glob";
|
|
480
713
|
async function findEntrypoints(config) {
|
|
481
|
-
const relativePaths = await
|
|
714
|
+
const relativePaths = await glob2("**/*", {
|
|
482
715
|
cwd: config.entrypointsDir
|
|
483
716
|
});
|
|
484
717
|
relativePaths.sort();
|
|
@@ -487,7 +720,7 @@ async function findEntrypoints(config) {
|
|
|
487
720
|
const entrypoints = [];
|
|
488
721
|
await Promise.all(
|
|
489
722
|
relativePaths.map(async (relativePath) => {
|
|
490
|
-
const path5 =
|
|
723
|
+
const path5 = resolve9(config.entrypointsDir, relativePath);
|
|
491
724
|
const matchingGlob = pathGlobs.find(
|
|
492
725
|
(glob3) => picomatch.isMatch(relativePath, glob3)
|
|
493
726
|
);
|
|
@@ -547,7 +780,7 @@ ${JSON.stringify(
|
|
|
547
780
|
}
|
|
548
781
|
async function getPopupEntrypoint(config, path5) {
|
|
549
782
|
const options = {};
|
|
550
|
-
const content = await
|
|
783
|
+
const content = await fs7.readFile(path5, "utf-8");
|
|
551
784
|
const { document } = parseHTML2(content);
|
|
552
785
|
const title = document.querySelector("title");
|
|
553
786
|
if (title != null)
|
|
@@ -577,7 +810,7 @@ async function getPopupEntrypoint(config, path5) {
|
|
|
577
810
|
}
|
|
578
811
|
async function getOptionsEntrypoint(config, path5) {
|
|
579
812
|
const options = {};
|
|
580
|
-
const content = await
|
|
813
|
+
const content = await fs7.readFile(path5, "utf-8");
|
|
581
814
|
const { document } = parseHTML2(content);
|
|
582
815
|
const openInTabContent = document.querySelector("meta[name='manifest.open_in_tab']")?.getAttribute("content");
|
|
583
816
|
if (openInTabContent) {
|
|
@@ -624,7 +857,7 @@ async function getContentScriptEntrypoint(config, name, path5) {
|
|
|
624
857
|
type: "content-script",
|
|
625
858
|
name: getEntrypointName(config.entrypointsDir, path5),
|
|
626
859
|
inputPath: path5,
|
|
627
|
-
outputDir:
|
|
860
|
+
outputDir: resolve9(config.outDir, "content-scripts"),
|
|
628
861
|
options
|
|
629
862
|
};
|
|
630
863
|
}
|
|
@@ -659,140 +892,112 @@ var PATH_GLOB_TO_TYPE_MAP = {
|
|
|
659
892
|
"*/*": "ignored"
|
|
660
893
|
};
|
|
661
894
|
|
|
662
|
-
// src/core/build/
|
|
663
|
-
import
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
await removeEmptyDirs(filePath);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
try {
|
|
678
|
-
await fs5.rmdir(dir);
|
|
679
|
-
} catch {
|
|
680
|
-
}
|
|
895
|
+
// src/core/build/generateTypesDir.ts
|
|
896
|
+
import { createUnimport as createUnimport3 } from "unimport";
|
|
897
|
+
import fs8 from "fs-extra";
|
|
898
|
+
import { relative as relative4, resolve as resolve10 } from "path";
|
|
899
|
+
async function generateTypesDir(entrypoints, config) {
|
|
900
|
+
await fs8.ensureDir(config.typesDir);
|
|
901
|
+
const references = [];
|
|
902
|
+
references.push(await writeImportsDeclarationFile(config));
|
|
903
|
+
references.push(await writePathsDeclarationFile(entrypoints, config));
|
|
904
|
+
references.push(await writeGlobalsDeclarationFile(config));
|
|
905
|
+
const mainReference = await writeMainDeclarationFile(references, config);
|
|
906
|
+
await writeTsConfigFile(mainReference, config);
|
|
681
907
|
}
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
const publicAssets = await copyPublicDirectory(config);
|
|
694
|
-
await removeEmptyDirs(config.outDir);
|
|
695
|
-
return { publicAssets, steps };
|
|
908
|
+
async function writeImportsDeclarationFile(config) {
|
|
909
|
+
const filePath = resolve10(config.typesDir, "imports.d.ts");
|
|
910
|
+
const unimport2 = createUnimport3(getUnimportOptions(config));
|
|
911
|
+
await unimport2.scanImportsFromDir(void 0, { cwd: config.srcDir });
|
|
912
|
+
await fs8.writeFile(
|
|
913
|
+
filePath,
|
|
914
|
+
["// Generated by wxt", await unimport2.generateTypeDeclarations()].join(
|
|
915
|
+
"\n"
|
|
916
|
+
) + "\n"
|
|
917
|
+
);
|
|
918
|
+
return filePath;
|
|
696
919
|
}
|
|
697
|
-
async function
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
entrypoint,
|
|
714
|
-
config.outDir,
|
|
715
|
-
".js"
|
|
716
|
-
),
|
|
717
|
-
// Output content script CSS to assets/ with a hash to prevent conflicts. Defaults to
|
|
718
|
-
// "[name].[ext]" in lib mode, which usually results in "style.css". That means multiple
|
|
719
|
-
// content scripts with styles would overwrite each other if it weren't changed below.
|
|
720
|
-
assetFileNames: `assets/${entrypoint.name}.[ext]`
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
};
|
|
725
|
-
const entryConfig = vite3.mergeConfig(
|
|
726
|
-
libMode,
|
|
727
|
-
config.vite
|
|
920
|
+
async function writePathsDeclarationFile(entrypoints, config) {
|
|
921
|
+
const filePath = resolve10(config.typesDir, "paths.d.ts");
|
|
922
|
+
await fs8.writeFile(
|
|
923
|
+
filePath,
|
|
924
|
+
[
|
|
925
|
+
"// Generated by wxt",
|
|
926
|
+
"type EntrypointPath =",
|
|
927
|
+
...entrypoints.map((entry) => {
|
|
928
|
+
const path5 = getEntrypointBundlePath(
|
|
929
|
+
entry,
|
|
930
|
+
config.outDir,
|
|
931
|
+
entry.inputPath.endsWith(".html") ? ".html" : ".js"
|
|
932
|
+
);
|
|
933
|
+
return ` | "/${path5}"`;
|
|
934
|
+
}).sort()
|
|
935
|
+
].join("\n") + "\n"
|
|
728
936
|
);
|
|
729
|
-
|
|
730
|
-
return {
|
|
731
|
-
entrypoints: entrypoint,
|
|
732
|
-
chunks: getBuildOutputChunks(result)
|
|
733
|
-
};
|
|
937
|
+
return filePath;
|
|
734
938
|
}
|
|
735
|
-
async function
|
|
736
|
-
const
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
entryFileNames: "chunks/[name]-[hash].js",
|
|
749
|
-
// We can't control the "name", so we need a hash to prevent conflicts
|
|
750
|
-
assetFileNames: "assets/[name]-[hash].[ext]"
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
};
|
|
755
|
-
const entryConfig = vite3.mergeConfig(
|
|
756
|
-
multiPage,
|
|
757
|
-
config.vite
|
|
939
|
+
async function writeGlobalsDeclarationFile(config) {
|
|
940
|
+
const filePath = resolve10(config.typesDir, "globals.d.ts");
|
|
941
|
+
const globals = getGlobals(config);
|
|
942
|
+
await fs8.writeFile(
|
|
943
|
+
filePath,
|
|
944
|
+
[
|
|
945
|
+
"// Generated by wxt",
|
|
946
|
+
"export {}",
|
|
947
|
+
"declare global {",
|
|
948
|
+
...globals.map((global) => ` const ${global.name}: ${global.type};`),
|
|
949
|
+
"}"
|
|
950
|
+
].join("\n") + "\n",
|
|
951
|
+
"utf-8"
|
|
758
952
|
);
|
|
759
|
-
|
|
760
|
-
return {
|
|
761
|
-
entrypoints,
|
|
762
|
-
chunks: getBuildOutputChunks(result)
|
|
763
|
-
};
|
|
953
|
+
return filePath;
|
|
764
954
|
}
|
|
765
|
-
function
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
955
|
+
async function writeMainDeclarationFile(references, config) {
|
|
956
|
+
const dir = config.wxtDir;
|
|
957
|
+
const filePath = resolve10(dir, "wxt.d.ts");
|
|
958
|
+
await fs8.writeFile(
|
|
959
|
+
filePath,
|
|
960
|
+
[
|
|
961
|
+
"// Generated by wxt",
|
|
962
|
+
...references.map(
|
|
963
|
+
(ref) => `/// <reference types="./${relative4(dir, ref)}" />`
|
|
964
|
+
)
|
|
965
|
+
].join("\n") + "\n"
|
|
966
|
+
);
|
|
967
|
+
return filePath;
|
|
771
968
|
}
|
|
772
|
-
async function
|
|
773
|
-
const
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
969
|
+
async function writeTsConfigFile(mainReference, config) {
|
|
970
|
+
const dir = config.wxtDir;
|
|
971
|
+
await fs8.writeFile(
|
|
972
|
+
resolve10(dir, "tsconfig.json"),
|
|
973
|
+
`{
|
|
974
|
+
"compilerOptions": {
|
|
975
|
+
"target": "ESNext",
|
|
976
|
+
"module": "ESNext",
|
|
977
|
+
"moduleResolution": "Bundler",
|
|
978
|
+
"noEmit": true,
|
|
979
|
+
"esModuleInterop": true,
|
|
980
|
+
"forceConsistentCasingInFileNames": true,
|
|
981
|
+
"resolveJsonModule": true,
|
|
982
|
+
|
|
983
|
+
/* Type Checking */
|
|
984
|
+
"strict": true,
|
|
985
|
+
|
|
986
|
+
/* Completeness */
|
|
987
|
+
"skipLibCheck": true
|
|
988
|
+
},
|
|
989
|
+
"include": [
|
|
990
|
+
"${relative4(dir, config.root)}/**/*",
|
|
991
|
+
"./${relative4(dir, mainReference)}"
|
|
992
|
+
],
|
|
993
|
+
"exclude": ["${relative4(dir, config.outBaseDir)}"]
|
|
994
|
+
}`
|
|
995
|
+
);
|
|
791
996
|
}
|
|
792
997
|
|
|
793
998
|
// src/core/utils/manifest.ts
|
|
794
|
-
import
|
|
795
|
-
import { resolve as
|
|
999
|
+
import fs9 from "fs-extra";
|
|
1000
|
+
import { resolve as resolve11 } from "path";
|
|
796
1001
|
|
|
797
1002
|
// src/core/utils/ContentSecurityPolicy.ts
|
|
798
1003
|
var ContentSecurityPolicy = class _ContentSecurityPolicy {
|
|
@@ -840,8 +1045,8 @@ var ContentSecurityPolicy = class _ContentSecurityPolicy {
|
|
|
840
1045
|
// src/core/utils/manifest.ts
|
|
841
1046
|
async function writeManifest(manifest, output, config) {
|
|
842
1047
|
const str = config.mode === "production" ? JSON.stringify(manifest) : JSON.stringify(manifest, null, 2);
|
|
843
|
-
await
|
|
844
|
-
await
|
|
1048
|
+
await fs9.ensureDir(config.outDir);
|
|
1049
|
+
await fs9.writeFile(resolve11(config.outDir, "manifest.json"), str, "utf-8");
|
|
845
1050
|
output.publicAssets.unshift({
|
|
846
1051
|
type: "asset",
|
|
847
1052
|
fileName: "manifest.json",
|
|
@@ -869,10 +1074,12 @@ async function generateMainfest(entrypoints, buildOutput, config) {
|
|
|
869
1074
|
addEntrypoints(manifest, entrypoints, buildOutput, config);
|
|
870
1075
|
if (config.command === "serve")
|
|
871
1076
|
addDevModeCsp(manifest, config);
|
|
1077
|
+
if (config.command === "serve")
|
|
1078
|
+
addDevModePermissions(manifest, config);
|
|
872
1079
|
return manifest;
|
|
873
1080
|
}
|
|
874
1081
|
async function getPackageJson(config) {
|
|
875
|
-
return await
|
|
1082
|
+
return await fs9.readJson(resolve11(config.root, "package.json"));
|
|
876
1083
|
}
|
|
877
1084
|
function simplifyVersion(versionName) {
|
|
878
1085
|
const version3 = /^((0|[1-9][0-9]{0,8})([.](0|[1-9][0-9]{0,8})){0,3}).*$/.exec(
|
|
@@ -1025,23 +1232,23 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
|
|
|
1025
1232
|
}
|
|
1026
1233
|
}
|
|
1027
1234
|
if (contentScripts?.length) {
|
|
1028
|
-
if (config.command === "serve") {
|
|
1029
|
-
const
|
|
1030
|
-
const hostPermissions = new Set(manifest[permissionsKey] ?? []);
|
|
1235
|
+
if (config.command === "serve" && config.manifestVersion === 3) {
|
|
1236
|
+
const hostPermissions = new Set(manifest.host_permissions ?? []);
|
|
1031
1237
|
contentScripts.forEach((script) => {
|
|
1032
1238
|
script.options.matches.forEach((matchPattern) => {
|
|
1033
1239
|
hostPermissions.add(matchPattern);
|
|
1034
1240
|
});
|
|
1035
1241
|
});
|
|
1036
|
-
|
|
1242
|
+
hostPermissions.forEach(
|
|
1243
|
+
(permission) => addHostPermission(manifest, permission)
|
|
1244
|
+
);
|
|
1037
1245
|
} else {
|
|
1038
1246
|
const hashToEntrypointsMap = contentScripts.reduce((map, script) => {
|
|
1039
1247
|
const hash = JSON.stringify(script.options);
|
|
1040
|
-
if (
|
|
1041
|
-
map.set(hash, [script]);
|
|
1042
|
-
} else {
|
|
1248
|
+
if (map.has(hash))
|
|
1043
1249
|
map.get(hash)?.push(script);
|
|
1044
|
-
|
|
1250
|
+
else
|
|
1251
|
+
map.set(hash, [script]);
|
|
1045
1252
|
return map;
|
|
1046
1253
|
}, /* @__PURE__ */ new Map());
|
|
1047
1254
|
manifest.content_scripts = Array.from(hashToEntrypointsMap.entries()).map(
|
|
@@ -1062,13 +1269,9 @@ function addDevModeCsp(manifest, config) {
|
|
|
1062
1269
|
const permission = `http://${config.server?.hostname ?? ""}/*`;
|
|
1063
1270
|
const allowedCsp = config.server?.origin ?? "http://localhost:*";
|
|
1064
1271
|
if (manifest.manifest_version === 3) {
|
|
1065
|
-
manifest
|
|
1066
|
-
if (!manifest.host_permissions.includes(permission))
|
|
1067
|
-
manifest.host_permissions.push(permission);
|
|
1272
|
+
addHostPermission(manifest, permission);
|
|
1068
1273
|
} else {
|
|
1069
|
-
manifest
|
|
1070
|
-
if (!manifest.permissions.includes(permission))
|
|
1071
|
-
manifest.permissions.push(permission);
|
|
1274
|
+
addPermission(manifest, permission);
|
|
1072
1275
|
}
|
|
1073
1276
|
const csp = new ContentSecurityPolicy(
|
|
1074
1277
|
manifest.manifest_version === 3 ? (
|
|
@@ -1086,6 +1289,11 @@ function addDevModeCsp(manifest, config) {
|
|
|
1086
1289
|
manifest.content_security_policy = csp.toString();
|
|
1087
1290
|
}
|
|
1088
1291
|
}
|
|
1292
|
+
function addDevModePermissions(manifest, config) {
|
|
1293
|
+
addPermission(manifest, "tabs");
|
|
1294
|
+
if (config.manifestVersion === 3)
|
|
1295
|
+
addPermission(manifest, "scripting");
|
|
1296
|
+
}
|
|
1089
1297
|
function getContentScriptCssFiles(contentScripts, buildOutput) {
|
|
1090
1298
|
const css = [];
|
|
1091
1299
|
const allChunks = buildOutput.steps.flatMap((step) => step.chunks);
|
|
@@ -1100,9 +1308,71 @@ function getContentScriptCssFiles(contentScripts, buildOutput) {
|
|
|
1100
1308
|
return css;
|
|
1101
1309
|
return void 0;
|
|
1102
1310
|
}
|
|
1311
|
+
function addPermission(manifest, permission) {
|
|
1312
|
+
manifest.permissions ??= [];
|
|
1313
|
+
if (manifest.permissions.includes(permission))
|
|
1314
|
+
return;
|
|
1315
|
+
manifest.permissions.push(permission);
|
|
1316
|
+
}
|
|
1317
|
+
function addHostPermission(manifest, hostPermission) {
|
|
1318
|
+
manifest.host_permissions ??= [];
|
|
1319
|
+
if (manifest.host_permissions.includes(hostPermission))
|
|
1320
|
+
return;
|
|
1321
|
+
manifest.host_permissions.push(hostPermission);
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
// src/core/build.ts
|
|
1325
|
+
import pc2 from "picocolors";
|
|
1326
|
+
import * as vite4 from "vite";
|
|
1327
|
+
import fs11 from "fs-extra";
|
|
1328
|
+
|
|
1329
|
+
// src/core/utils/groupEntrypoints.ts
|
|
1330
|
+
function groupEntrypoints(entrypoints) {
|
|
1331
|
+
const groupIndexMap = {};
|
|
1332
|
+
const groups = [];
|
|
1333
|
+
for (const entry of entrypoints) {
|
|
1334
|
+
const group = ENTRY_TYPE_TO_GROUP_MAP[entry.type];
|
|
1335
|
+
if (group === "no-group") {
|
|
1336
|
+
groups.push(entry);
|
|
1337
|
+
} else {
|
|
1338
|
+
let groupIndex = groupIndexMap[group];
|
|
1339
|
+
if (groupIndex == null) {
|
|
1340
|
+
groupIndex = groups.push([]) - 1;
|
|
1341
|
+
groupIndexMap[group] = groupIndex;
|
|
1342
|
+
}
|
|
1343
|
+
groups[groupIndex].push(entry);
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
return groups;
|
|
1347
|
+
}
|
|
1348
|
+
var ENTRY_TYPE_TO_GROUP_MAP = {
|
|
1349
|
+
sandbox: "sandbox-page",
|
|
1350
|
+
popup: "extension-page",
|
|
1351
|
+
newtab: "extension-page",
|
|
1352
|
+
history: "extension-page",
|
|
1353
|
+
options: "extension-page",
|
|
1354
|
+
devtools: "extension-page",
|
|
1355
|
+
bookmarks: "extension-page",
|
|
1356
|
+
sidepanel: "extension-page",
|
|
1357
|
+
"unlisted-page": "extension-page",
|
|
1358
|
+
background: "no-group",
|
|
1359
|
+
"content-script": "no-group",
|
|
1360
|
+
"unlisted-script": "no-group"
|
|
1361
|
+
};
|
|
1362
|
+
|
|
1363
|
+
// src/core/utils/formatDuration.ts
|
|
1364
|
+
function formatDuration(duration) {
|
|
1365
|
+
if (duration < 1e3)
|
|
1366
|
+
return `${duration} ms`;
|
|
1367
|
+
if (duration < 1e4)
|
|
1368
|
+
return `${(duration / 1e3).toFixed(3)} s`;
|
|
1369
|
+
if (duration < 6e4)
|
|
1370
|
+
return `${(duration / 1e3).toFixed(1)} s`;
|
|
1371
|
+
return `${(duration / 1e3).toFixed(0)} s`;
|
|
1372
|
+
}
|
|
1103
1373
|
|
|
1104
1374
|
// src/core/log/printBuildSummary.ts
|
|
1105
|
-
import path4, { extname as extname2, relative as
|
|
1375
|
+
import path4, { extname as extname2, relative as relative5, resolve as resolve12 } from "path";
|
|
1106
1376
|
|
|
1107
1377
|
// src/core/log/printTable.ts
|
|
1108
1378
|
function printTable(log, rows, gap = 2) {
|
|
@@ -1132,7 +1402,7 @@ function printTable(log, rows, gap = 2) {
|
|
|
1132
1402
|
|
|
1133
1403
|
// src/core/log/printBuildSummary.ts
|
|
1134
1404
|
import pc from "picocolors";
|
|
1135
|
-
import
|
|
1405
|
+
import fs10 from "fs-extra";
|
|
1136
1406
|
import { filesize } from "filesize";
|
|
1137
1407
|
async function printBuildSummary(output, config) {
|
|
1138
1408
|
const chunks = [
|
|
@@ -1150,13 +1420,13 @@ async function printBuildSummary(output, config) {
|
|
|
1150
1420
|
const chunkRows = await Promise.all(
|
|
1151
1421
|
chunks.map(async (chunk, i) => {
|
|
1152
1422
|
const file = [
|
|
1153
|
-
|
|
1423
|
+
relative5(process.cwd(), config.outDir) + path4.sep,
|
|
1154
1424
|
chunk.fileName
|
|
1155
1425
|
];
|
|
1156
1426
|
const ext = extname2(chunk.fileName);
|
|
1157
1427
|
const prefix = i === chunks.length - 1 ? " \u2514\u2500" : " \u251C\u2500";
|
|
1158
1428
|
const color = CHUNK_COLORS[ext] ?? DEFAULT_COLOR;
|
|
1159
|
-
const stats = await
|
|
1429
|
+
const stats = await fs10.lstat(resolve12(config.outDir, chunk.fileName));
|
|
1160
1430
|
totalSize += stats.size;
|
|
1161
1431
|
const size = String(filesize(stats.size));
|
|
1162
1432
|
return [
|
|
@@ -1184,115 +1454,63 @@ var CHUNK_COLORS = {
|
|
|
1184
1454
|
".js": pc.cyan
|
|
1185
1455
|
};
|
|
1186
1456
|
|
|
1187
|
-
// src/
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
await fs9.ensureDir(config.typesDir);
|
|
1196
|
-
const references = [];
|
|
1197
|
-
references.push(await writeImportsDeclarationFile(config));
|
|
1198
|
-
references.push(await writePathsDeclarationFile(entrypoints, config));
|
|
1199
|
-
references.push(await writeGlobalsDeclarationFile(config));
|
|
1200
|
-
const mainReference = await writeMainDeclarationFile(references, config);
|
|
1201
|
-
await writeTsConfigFile(mainReference, config);
|
|
1202
|
-
}
|
|
1203
|
-
async function writeImportsDeclarationFile(config) {
|
|
1204
|
-
const filePath = resolve12(config.typesDir, "imports.d.ts");
|
|
1205
|
-
const unimport2 = createUnimport2(getUnimportOptions(config));
|
|
1206
|
-
await unimport2.scanImportsFromDir(void 0, { cwd: config.srcDir });
|
|
1207
|
-
await fs9.writeFile(
|
|
1208
|
-
filePath,
|
|
1209
|
-
["// Generated by wxt", await unimport2.generateTypeDeclarations()].join(
|
|
1210
|
-
"\n"
|
|
1211
|
-
) + "\n"
|
|
1457
|
+
// src/core/build.ts
|
|
1458
|
+
async function buildInternal(config) {
|
|
1459
|
+
const verb = config.command === "serve" ? "Pre-rendering" : "Building";
|
|
1460
|
+
const target = `${config.browser}-mv${config.manifestVersion}`;
|
|
1461
|
+
config.logger.info(
|
|
1462
|
+
`${verb} ${pc2.cyan(target)} for ${pc2.cyan(config.mode)} with ${pc2.green(
|
|
1463
|
+
`Vite ${vite4.version}`
|
|
1464
|
+
)}`
|
|
1212
1465
|
);
|
|
1213
|
-
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
const
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
"type EntrypointPath =",
|
|
1222
|
-
...entrypoints.map((entry) => {
|
|
1223
|
-
const path5 = getEntrypointBundlePath(
|
|
1224
|
-
entry,
|
|
1225
|
-
config.outDir,
|
|
1226
|
-
entry.inputPath.endsWith(".html") ? ".html" : ".js"
|
|
1227
|
-
);
|
|
1228
|
-
return ` | "/${path5}"`;
|
|
1229
|
-
}).sort()
|
|
1230
|
-
].join("\n") + "\n"
|
|
1231
|
-
);
|
|
1232
|
-
return filePath;
|
|
1233
|
-
}
|
|
1234
|
-
async function writeGlobalsDeclarationFile(config) {
|
|
1235
|
-
const filePath = resolve12(config.typesDir, "globals.d.ts");
|
|
1236
|
-
const globals = getGlobals(config);
|
|
1237
|
-
await fs9.writeFile(
|
|
1238
|
-
filePath,
|
|
1239
|
-
[
|
|
1240
|
-
"// Generated by wxt",
|
|
1241
|
-
"export {}",
|
|
1242
|
-
"declare global {",
|
|
1243
|
-
...globals.map((global) => ` const ${global.name}: ${global.type};`),
|
|
1244
|
-
"}"
|
|
1245
|
-
].join("\n") + "\n",
|
|
1246
|
-
"utf-8"
|
|
1247
|
-
);
|
|
1248
|
-
return filePath;
|
|
1249
|
-
}
|
|
1250
|
-
async function writeMainDeclarationFile(references, config) {
|
|
1251
|
-
const dir = config.wxtDir;
|
|
1252
|
-
const filePath = resolve12(dir, "wxt.d.ts");
|
|
1253
|
-
await fs9.writeFile(
|
|
1254
|
-
filePath,
|
|
1255
|
-
[
|
|
1256
|
-
"// Generated by wxt",
|
|
1257
|
-
...references.map(
|
|
1258
|
-
(ref) => `/// <reference types="./${relative5(dir, ref)}" />`
|
|
1259
|
-
)
|
|
1260
|
-
].join("\n") + "\n"
|
|
1466
|
+
const startTime = Date.now();
|
|
1467
|
+
await fs11.rm(config.outDir, { recursive: true, force: true });
|
|
1468
|
+
await fs11.ensureDir(config.outDir);
|
|
1469
|
+
const entrypoints = await findEntrypoints(config);
|
|
1470
|
+
const groups = groupEntrypoints(entrypoints);
|
|
1471
|
+
const { output } = await rebuild(config, groups);
|
|
1472
|
+
config.logger.success(
|
|
1473
|
+
`Built extension in ${formatDuration(Date.now() - startTime)}`
|
|
1261
1474
|
);
|
|
1262
|
-
|
|
1475
|
+
await printBuildSummary(output, config);
|
|
1476
|
+
return output;
|
|
1263
1477
|
}
|
|
1264
|
-
async function
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
"strict": true,
|
|
1280
|
-
|
|
1281
|
-
/* Completeness */
|
|
1282
|
-
"skipLibCheck": true
|
|
1283
|
-
},
|
|
1284
|
-
"include": [
|
|
1285
|
-
"${relative5(dir, config.root)}/**/*",
|
|
1286
|
-
"./${relative5(dir, mainReference)}"
|
|
1287
|
-
],
|
|
1288
|
-
"exclude": ["${relative5(dir, config.outBaseDir)}"]
|
|
1289
|
-
}`
|
|
1478
|
+
async function rebuild(config, entrypointGroups, existingOutput = {
|
|
1479
|
+
steps: [],
|
|
1480
|
+
publicAssets: []
|
|
1481
|
+
}) {
|
|
1482
|
+
const allEntrypoints = await findEntrypoints(config);
|
|
1483
|
+
await generateTypesDir(allEntrypoints, config);
|
|
1484
|
+
const newOutput = await buildEntrypoints(entrypointGroups, config);
|
|
1485
|
+
const mergedOutput = {
|
|
1486
|
+
steps: [...existingOutput.steps, ...newOutput.steps],
|
|
1487
|
+
publicAssets: [...existingOutput.publicAssets, ...newOutput.publicAssets]
|
|
1488
|
+
};
|
|
1489
|
+
const newManifest = await generateMainfest(
|
|
1490
|
+
allEntrypoints,
|
|
1491
|
+
mergedOutput,
|
|
1492
|
+
config
|
|
1290
1493
|
);
|
|
1494
|
+
const finalOutput = {
|
|
1495
|
+
manifest: newManifest,
|
|
1496
|
+
...newOutput
|
|
1497
|
+
};
|
|
1498
|
+
await writeManifest(newManifest, finalOutput, config);
|
|
1499
|
+
return {
|
|
1500
|
+
output: {
|
|
1501
|
+
manifest: newManifest,
|
|
1502
|
+
steps: [...existingOutput.steps, ...finalOutput.steps],
|
|
1503
|
+
publicAssets: [
|
|
1504
|
+
...existingOutput.publicAssets,
|
|
1505
|
+
...finalOutput.publicAssets
|
|
1506
|
+
]
|
|
1507
|
+
},
|
|
1508
|
+
manifest: newManifest
|
|
1509
|
+
};
|
|
1291
1510
|
}
|
|
1292
1511
|
|
|
1293
|
-
// src/
|
|
1294
|
-
import
|
|
1295
|
-
import * as vite4 from "vite";
|
|
1512
|
+
// src/core/server.ts
|
|
1513
|
+
import * as vite5 from "vite";
|
|
1296
1514
|
|
|
1297
1515
|
// src/core/utils/findOpenPort.ts
|
|
1298
1516
|
import net from "node:net";
|
|
@@ -1317,17 +1535,6 @@ function findOpenPortRecursive(port, startPort, endPort) {
|
|
|
1317
1535
|
});
|
|
1318
1536
|
}
|
|
1319
1537
|
|
|
1320
|
-
// src/core/utils/formatDuration.ts
|
|
1321
|
-
function formatDuration(duration) {
|
|
1322
|
-
if (duration < 1e3)
|
|
1323
|
-
return `${duration} ms`;
|
|
1324
|
-
if (duration < 1e4)
|
|
1325
|
-
return `${(duration / 1e3).toFixed(3)} s`;
|
|
1326
|
-
if (duration < 6e4)
|
|
1327
|
-
return `${(duration / 1e3).toFixed(1)} s`;
|
|
1328
|
-
return `${(duration / 1e3).toFixed(0)} s`;
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
1538
|
// src/core/runners/createWebExtRunner.ts
|
|
1332
1539
|
function createWebExtRunner() {
|
|
1333
1540
|
let runner;
|
|
@@ -1385,120 +1592,93 @@ function createWebExtRunner() {
|
|
|
1385
1592
|
var WARN_LOG_LEVEL = 40;
|
|
1386
1593
|
var ERROR_LOG_LEVEL = 50;
|
|
1387
1594
|
|
|
1388
|
-
// src/core/
|
|
1389
|
-
function
|
|
1390
|
-
const
|
|
1391
|
-
const
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
} else {
|
|
1397
|
-
let groupIndex = groupIndexMap[group];
|
|
1398
|
-
if (groupIndex == null) {
|
|
1399
|
-
groupIndex = groups.push([]) - 1;
|
|
1400
|
-
groupIndexMap[group] = groupIndex;
|
|
1401
|
-
}
|
|
1402
|
-
groups[groupIndex].push(entry);
|
|
1595
|
+
// src/core/server.ts
|
|
1596
|
+
async function getServerInfo() {
|
|
1597
|
+
const port = await findOpenPort(3e3, 3010);
|
|
1598
|
+
const hostname = "localhost";
|
|
1599
|
+
const origin = `http://${hostname}:${port}`;
|
|
1600
|
+
const serverConfig = {
|
|
1601
|
+
server: {
|
|
1602
|
+
origin
|
|
1403
1603
|
}
|
|
1404
|
-
}
|
|
1405
|
-
return
|
|
1604
|
+
};
|
|
1605
|
+
return {
|
|
1606
|
+
port,
|
|
1607
|
+
hostname,
|
|
1608
|
+
origin,
|
|
1609
|
+
viteServerConfig: serverConfig
|
|
1610
|
+
};
|
|
1406
1611
|
}
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
history: "extension-page",
|
|
1412
|
-
options: "extension-page",
|
|
1413
|
-
devtools: "extension-page",
|
|
1414
|
-
bookmarks: "extension-page",
|
|
1415
|
-
sidepanel: "extension-page",
|
|
1416
|
-
"unlisted-page": "extension-page",
|
|
1417
|
-
background: "no-group",
|
|
1418
|
-
"content-script": "no-group",
|
|
1419
|
-
"unlisted-script": "no-group"
|
|
1420
|
-
};
|
|
1421
|
-
|
|
1422
|
-
// src/core/utils/detectDevChanges.ts
|
|
1423
|
-
function detectDevChanges(changedFiles, currentOutput) {
|
|
1424
|
-
if (currentOutput == null)
|
|
1425
|
-
return { type: "no-change" };
|
|
1426
|
-
const changedSteps = new Set(
|
|
1427
|
-
changedFiles.flatMap(
|
|
1428
|
-
(changedFile) => findEffectedSteps(changedFile, currentOutput)
|
|
1429
|
-
)
|
|
1612
|
+
async function setupServer(serverInfo, config) {
|
|
1613
|
+
const runner = createWebExtRunner();
|
|
1614
|
+
const viteServer = await vite5.createServer(
|
|
1615
|
+
vite5.mergeConfig(serverInfo, config.vite)
|
|
1430
1616
|
);
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1617
|
+
const start = async () => {
|
|
1618
|
+
await viteServer.listen(server.port);
|
|
1619
|
+
config.logger.success(`Started dev server @ ${serverInfo.origin}`);
|
|
1620
|
+
server.currentOutput = await buildInternal(config);
|
|
1621
|
+
config.logger.info("Opening browser...");
|
|
1622
|
+
await runner.openBrowser(config);
|
|
1623
|
+
config.logger.success("Opened!");
|
|
1437
1624
|
};
|
|
1438
|
-
const
|
|
1439
|
-
|
|
1440
|
-
steps: [],
|
|
1441
|
-
publicAssets: []
|
|
1625
|
+
const reloadExtension = () => {
|
|
1626
|
+
viteServer.ws.send("wxt:reload-extension");
|
|
1442
1627
|
};
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
changedOutput.steps.push(step);
|
|
1446
|
-
} else {
|
|
1447
|
-
unchangedOutput.steps.push(step);
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
for (const asset of currentOutput.publicAssets) {
|
|
1451
|
-
if (changedSteps.has(asset)) {
|
|
1452
|
-
changedOutput.publicAssets.push(asset);
|
|
1453
|
-
} else {
|
|
1454
|
-
unchangedOutput.publicAssets.push(asset);
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
const isOnlyHtmlChanges = !changedFiles.find(
|
|
1458
|
-
([_, file]) => !file.endsWith(".html")
|
|
1459
|
-
);
|
|
1460
|
-
if (isOnlyHtmlChanges) {
|
|
1461
|
-
return {
|
|
1462
|
-
type: "html-reload",
|
|
1463
|
-
cachedOutput: unchangedOutput,
|
|
1464
|
-
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
1465
|
-
};
|
|
1466
|
-
}
|
|
1467
|
-
return {
|
|
1468
|
-
type: "extension-reload",
|
|
1469
|
-
cachedOutput: unchangedOutput,
|
|
1470
|
-
rebuildGroups: changedOutput.steps.map((step) => step.entrypoints)
|
|
1628
|
+
const reloadPage = (path5) => {
|
|
1629
|
+
viteServer.ws.send("wxt:reload-page", path5);
|
|
1471
1630
|
};
|
|
1631
|
+
const reloadContentScript = (contentScript) => {
|
|
1632
|
+
viteServer.ws.send("wxt:reload-content-script", contentScript);
|
|
1633
|
+
};
|
|
1634
|
+
const server = {
|
|
1635
|
+
...viteServer,
|
|
1636
|
+
start,
|
|
1637
|
+
currentOutput: {
|
|
1638
|
+
manifest: {
|
|
1639
|
+
manifest_version: 3,
|
|
1640
|
+
name: "",
|
|
1641
|
+
version: ""
|
|
1642
|
+
},
|
|
1643
|
+
publicAssets: [],
|
|
1644
|
+
steps: []
|
|
1645
|
+
},
|
|
1646
|
+
port: serverInfo.port,
|
|
1647
|
+
hostname: serverInfo.hostname,
|
|
1648
|
+
origin: serverInfo.origin,
|
|
1649
|
+
reloadExtension,
|
|
1650
|
+
reloadPage,
|
|
1651
|
+
reloadContentScript
|
|
1652
|
+
};
|
|
1653
|
+
return server;
|
|
1472
1654
|
}
|
|
1473
|
-
function
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1655
|
+
function reloadContentScripts(steps, config, server) {
|
|
1656
|
+
if (config.manifestVersion === 3) {
|
|
1657
|
+
steps.forEach((step) => {
|
|
1658
|
+
const entry = step.entrypoints;
|
|
1659
|
+
if (Array.isArray(entry) || entry.type !== "content-script")
|
|
1660
|
+
return;
|
|
1661
|
+
const js = [getEntrypointBundlePath(entry, config.outDir, ".js")];
|
|
1662
|
+
const css = getContentScriptCssFiles([entry], server.currentOutput);
|
|
1663
|
+
server.reloadContentScript({
|
|
1664
|
+
js,
|
|
1665
|
+
css,
|
|
1666
|
+
...entry.options
|
|
1667
|
+
});
|
|
1668
|
+
});
|
|
1669
|
+
} else {
|
|
1670
|
+
server.reloadExtension();
|
|
1486
1671
|
}
|
|
1487
|
-
const effectedAsset = currentOutput.publicAssets.find(
|
|
1488
|
-
(chunk) => isChunkEffected(chunk)
|
|
1489
|
-
);
|
|
1490
|
-
if (effectedAsset)
|
|
1491
|
-
changes.push(effectedAsset);
|
|
1492
|
-
return changes;
|
|
1493
1672
|
}
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1673
|
+
function reloadHtmlPages(groups, server, config) {
|
|
1674
|
+
groups.flat().forEach((entry) => {
|
|
1675
|
+
const path5 = getEntrypointBundlePath(entry, config.outDir, ".html");
|
|
1676
|
+
server.reloadPage(path5);
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1499
1679
|
|
|
1500
1680
|
// package.json
|
|
1501
|
-
var
|
|
1681
|
+
var version2 = "0.1.1-alpha1";
|
|
1502
1682
|
|
|
1503
1683
|
// src/core/utils/defineConfig.ts
|
|
1504
1684
|
function defineConfig(config) {
|
|
@@ -1516,45 +1696,40 @@ async function build2(config) {
|
|
|
1516
1696
|
return await buildInternal(internalConfig);
|
|
1517
1697
|
}
|
|
1518
1698
|
async function createServer2(config) {
|
|
1519
|
-
const
|
|
1520
|
-
const
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
}
|
|
1699
|
+
const serverInfo = await getServerInfo();
|
|
1700
|
+
const getLatestInternalConfig = () => {
|
|
1701
|
+
const viteConfig = vite6.mergeConfig(
|
|
1702
|
+
serverInfo.viteServerConfig,
|
|
1703
|
+
config?.vite ?? {}
|
|
1704
|
+
);
|
|
1705
|
+
return getInternalConfig({ ...config, vite: viteConfig }, "serve");
|
|
1526
1706
|
};
|
|
1527
|
-
let internalConfig = await
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
);
|
|
1531
|
-
const runner = createWebExtRunner();
|
|
1532
|
-
let hasBuiltOnce = false;
|
|
1533
|
-
let currentOutput;
|
|
1707
|
+
let internalConfig = await getLatestInternalConfig();
|
|
1708
|
+
const server = await setupServer(serverInfo, internalConfig);
|
|
1709
|
+
internalConfig.server = server;
|
|
1534
1710
|
const fileChangedMutex = new Mutex();
|
|
1535
1711
|
const changeQueue = [];
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1712
|
+
server.ws.on("wxt:background-initialized", () => {
|
|
1713
|
+
reloadContentScripts(server.currentOutput.steps, internalConfig, server);
|
|
1714
|
+
});
|
|
1715
|
+
server.watcher.on("all", async (event, path5, _stats) => {
|
|
1716
|
+
if (path5.startsWith(internalConfig.outBaseDir))
|
|
1539
1717
|
return;
|
|
1540
1718
|
changeQueue.push([event, path5]);
|
|
1541
1719
|
await fileChangedMutex.runExclusive(async () => {
|
|
1542
1720
|
const fileChanges = changeQueue.splice(0, changeQueue.length);
|
|
1543
|
-
const changes = detectDevChanges(fileChanges, currentOutput);
|
|
1721
|
+
const changes = detectDevChanges(fileChanges, server.currentOutput);
|
|
1544
1722
|
if (changes.type === "no-change")
|
|
1545
1723
|
return;
|
|
1546
1724
|
consola3.info(
|
|
1547
|
-
`Changed: ${Array.from(new Set(fileChanges.map((change) => change[1]))).map((file) =>
|
|
1725
|
+
`Changed: ${Array.from(new Set(fileChanges.map((change) => change[1]))).map((file) => pc3.dim(relative6(internalConfig.root, file))).join(", ")}`
|
|
1548
1726
|
);
|
|
1549
1727
|
const rebuiltNames = changes.rebuildGroups.flat().map((entry) => {
|
|
1550
|
-
return
|
|
1728
|
+
return pc3.cyan(
|
|
1551
1729
|
relative6(internalConfig.outDir, getEntrypointOutputFile(entry, ""))
|
|
1552
1730
|
);
|
|
1553
|
-
}).join(
|
|
1554
|
-
internalConfig = await
|
|
1555
|
-
vite4.mergeConfig(serverConfig, config ?? {}),
|
|
1556
|
-
"serve"
|
|
1557
|
-
);
|
|
1731
|
+
}).join(pc3.dim(", "));
|
|
1732
|
+
internalConfig = await getLatestInternalConfig();
|
|
1558
1733
|
internalConfig.server = server;
|
|
1559
1734
|
const { output: newOutput } = await rebuild(
|
|
1560
1735
|
internalConfig,
|
|
@@ -1562,102 +1737,28 @@ async function createServer2(config) {
|
|
|
1562
1737
|
changes.rebuildGroups,
|
|
1563
1738
|
changes.cachedOutput
|
|
1564
1739
|
);
|
|
1565
|
-
currentOutput = newOutput;
|
|
1740
|
+
server.currentOutput = newOutput;
|
|
1566
1741
|
switch (changes.type) {
|
|
1567
1742
|
case "extension-reload":
|
|
1568
1743
|
server.reloadExtension();
|
|
1569
|
-
consola3.success(`Reloaded extension: ${rebuiltNames}`);
|
|
1570
1744
|
break;
|
|
1571
1745
|
case "html-reload":
|
|
1572
|
-
changes.rebuildGroups
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
".html"
|
|
1577
|
-
);
|
|
1578
|
-
server.reloadPage(path6);
|
|
1579
|
-
});
|
|
1580
|
-
consola3.success(`Reloaded pages: ${rebuiltNames}`);
|
|
1746
|
+
reloadHtmlPages(changes.rebuildGroups, server, internalConfig);
|
|
1747
|
+
break;
|
|
1748
|
+
case "content-script-reload":
|
|
1749
|
+
reloadContentScripts(changes.changedSteps, internalConfig, server);
|
|
1581
1750
|
break;
|
|
1582
1751
|
}
|
|
1752
|
+
consola3.success(`Reloaded: ${rebuiltNames}`);
|
|
1583
1753
|
});
|
|
1584
1754
|
});
|
|
1585
|
-
const server = {
|
|
1586
|
-
...viteServer,
|
|
1587
|
-
async listen(port2, isRestart) {
|
|
1588
|
-
const res = await viteServer.listen(port2, isRestart);
|
|
1589
|
-
if (!isRestart) {
|
|
1590
|
-
internalConfig.logger.success(`Started dev server @ ${origin}`);
|
|
1591
|
-
internalConfig.logger.info("Opening browser...");
|
|
1592
|
-
await runner.openBrowser(internalConfig);
|
|
1593
|
-
internalConfig.logger.success("Opened!");
|
|
1594
|
-
}
|
|
1595
|
-
return res;
|
|
1596
|
-
},
|
|
1597
|
-
port,
|
|
1598
|
-
hostname,
|
|
1599
|
-
origin,
|
|
1600
|
-
reloadExtension: () => {
|
|
1601
|
-
server.ws.send("wxt:reload-extension");
|
|
1602
|
-
},
|
|
1603
|
-
reloadPage: (path5) => {
|
|
1604
|
-
server.ws.send("wxt:reload-page", path5);
|
|
1605
|
-
}
|
|
1606
|
-
};
|
|
1607
|
-
internalConfig.logger.info("Created dev server");
|
|
1608
|
-
internalConfig.server = server;
|
|
1609
|
-
currentOutput = await buildInternal(internalConfig);
|
|
1610
|
-
hasBuiltOnce = true;
|
|
1611
1755
|
return server;
|
|
1612
1756
|
}
|
|
1613
|
-
async function buildInternal(config) {
|
|
1614
|
-
const verb = config.command === "serve" ? "Pre-rendering" : "Building";
|
|
1615
|
-
const target = `${config.browser}-mv${config.manifestVersion}`;
|
|
1616
|
-
config.logger.info(
|
|
1617
|
-
`${verb} ${pc2.cyan(target)} for ${pc2.cyan(config.mode)} with ${pc2.green(
|
|
1618
|
-
`Vite ${vite4.version}`
|
|
1619
|
-
)}`
|
|
1620
|
-
);
|
|
1621
|
-
const startTime = Date.now();
|
|
1622
|
-
await fs10.rm(config.outDir, { recursive: true, force: true });
|
|
1623
|
-
await fs10.ensureDir(config.outDir);
|
|
1624
|
-
const entrypoints = await findEntrypoints(config);
|
|
1625
|
-
const groups = groupEntrypoints(entrypoints);
|
|
1626
|
-
const { output } = await rebuild(config, groups);
|
|
1627
|
-
config.logger.success(
|
|
1628
|
-
`Built extension in ${formatDuration(Date.now() - startTime)}`
|
|
1629
|
-
);
|
|
1630
|
-
await printBuildSummary(output, config);
|
|
1631
|
-
return output;
|
|
1632
|
-
}
|
|
1633
|
-
async function rebuild(config, entrypointGroups, existingOutput = {
|
|
1634
|
-
steps: [],
|
|
1635
|
-
publicAssets: []
|
|
1636
|
-
}) {
|
|
1637
|
-
const allEntrypoints = await findEntrypoints(config);
|
|
1638
|
-
await generateTypesDir(allEntrypoints, config);
|
|
1639
|
-
const buildOutput = await buildEntrypoints(entrypointGroups, config);
|
|
1640
|
-
const manifest = await generateMainfest(allEntrypoints, buildOutput, config);
|
|
1641
|
-
const output = {
|
|
1642
|
-
manifest,
|
|
1643
|
-
...buildOutput
|
|
1644
|
-
};
|
|
1645
|
-
await writeManifest(manifest, output, config);
|
|
1646
|
-
return {
|
|
1647
|
-
output: {
|
|
1648
|
-
manifest,
|
|
1649
|
-
steps: [...existingOutput.steps, ...output.steps],
|
|
1650
|
-
publicAssets: [...existingOutput.publicAssets, ...output.publicAssets]
|
|
1651
|
-
},
|
|
1652
|
-
manifest
|
|
1653
|
-
};
|
|
1654
|
-
}
|
|
1655
1757
|
export {
|
|
1656
1758
|
build2 as build,
|
|
1657
1759
|
createServer2 as createServer,
|
|
1658
1760
|
defineConfig,
|
|
1659
1761
|
defineRunnerConfig,
|
|
1660
|
-
|
|
1661
|
-
version
|
|
1762
|
+
version2 as version
|
|
1662
1763
|
};
|
|
1663
1764
|
//# sourceMappingURL=index.js.map
|