wxt 0.16.2 → 0.16.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,74 @@
1
1
  // package.json
2
- var version = "0.16.2";
2
+ var version = "0.16.4";
3
+
4
+ // src/core/utils/fs.ts
5
+ import fs from "fs-extra";
6
+ import glob from "fast-glob";
7
+
8
+ // src/core/utils/paths.ts
9
+ import systemPath from "node:path";
10
+ import normalize from "normalize-path";
11
+ function normalizePath(path7) {
12
+ return normalize(path7);
13
+ }
14
+ function unnormalizePath(path7) {
15
+ return systemPath.normalize(path7);
16
+ }
17
+ var CSS_EXTENSIONS = ["css", "scss", "sass", "less", "styl", "stylus"];
18
+ var CSS_EXTENSIONS_PATTERN = `+(${CSS_EXTENSIONS.join("|")})`;
19
+
20
+ // src/core/utils/fs.ts
21
+ async function writeFileIfDifferent(file, newContents) {
22
+ const existingContents = await fs.readFile(file, "utf-8").catch(() => void 0);
23
+ if (existingContents !== newContents) {
24
+ await fs.writeFile(file, newContents);
25
+ }
26
+ }
27
+ async function getPublicFiles() {
28
+ if (!await fs.exists(wxt.config.publicDir))
29
+ return [];
30
+ const files = await glob("**/*", { cwd: wxt.config.publicDir });
31
+ return files.map(unnormalizePath);
32
+ }
33
+
34
+ // src/core/utils/building/build-entrypoints.ts
35
+ import fs2 from "fs-extra";
36
+ import { dirname, resolve } from "path";
37
+ import pc from "picocolors";
38
+ async function buildEntrypoints(groups, spinner) {
39
+ const steps = [];
40
+ for (let i = 0; i < groups.length; i++) {
41
+ const group = groups[i];
42
+ const groupNames = [group].flat().map((e) => e.name);
43
+ const groupNameColored = groupNames.join(pc.dim(", "));
44
+ spinner.text = pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNameColored}`;
45
+ try {
46
+ steps.push(await wxt.config.builder.build(group));
47
+ } catch (err) {
48
+ wxt.logger.error(err);
49
+ throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
50
+ }
51
+ }
52
+ const publicAssets = await copyPublicDirectory();
53
+ return { publicAssets, steps };
54
+ }
55
+ async function copyPublicDirectory() {
56
+ const files = await getPublicFiles();
57
+ if (files.length === 0)
58
+ return [];
59
+ const publicAssets = [];
60
+ for (const file of files) {
61
+ const srcPath = resolve(wxt.config.publicDir, file);
62
+ const outPath = resolve(wxt.config.outDir, file);
63
+ await fs2.ensureDir(dirname(outPath));
64
+ await fs2.copyFile(srcPath, outPath);
65
+ publicAssets.push({
66
+ type: "asset",
67
+ fileName: file
68
+ });
69
+ }
70
+ return publicAssets;
71
+ }
3
72
 
4
73
  // src/core/utils/arrays.ts
5
74
  function every(array, predicate) {
@@ -15,29 +84,17 @@ function some(array, predicate) {
15
84
  return false;
16
85
  }
17
86
 
18
- // src/core/utils/paths.ts
19
- import systemPath from "node:path";
20
- import normalize from "normalize-path";
21
- function normalizePath(path6) {
22
- return normalize(path6);
23
- }
24
- function unnormalizePath(path6) {
25
- return systemPath.normalize(path6);
26
- }
27
- var CSS_EXTENSIONS = ["css", "scss", "sass", "less", "styl", "stylus"];
28
- var CSS_EXTENSIONS_PATTERN = `+(${CSS_EXTENSIONS.join("|")})`;
29
-
30
87
  // src/core/utils/building/detect-dev-changes.ts
31
- function detectDevChanges(config, changedFiles, currentOutput) {
88
+ function detectDevChanges(changedFiles, currentOutput) {
32
89
  const isConfigChange = some(
33
90
  changedFiles,
34
- (file) => file === config.userConfigMetadata.configFile
91
+ (file) => file === wxt.config.userConfigMetadata.configFile
35
92
  );
36
93
  if (isConfigChange)
37
94
  return { type: "full-restart" };
38
95
  const isRunnerChange = some(
39
96
  changedFiles,
40
- (file) => file === config.runnerConfig.configFile
97
+ (file) => file === wxt.config.runnerConfig.configFile
41
98
  );
42
99
  if (isRunnerChange)
43
100
  return { type: "browser-restart" };
@@ -121,15 +178,23 @@ function findEffectedSteps(changedFile, currentOutput) {
121
178
  return changes;
122
179
  }
123
180
 
181
+ // src/core/utils/building/find-entrypoints.ts
182
+ import { relative as relative2, resolve as resolve3 } from "path";
183
+ import fs3 from "fs-extra";
184
+ import { minimatch } from "minimatch";
185
+ import { parseHTML } from "linkedom";
186
+ import JSON5 from "json5";
187
+ import glob2 from "fast-glob";
188
+
124
189
  // src/core/utils/entrypoints.ts
125
- import path, { relative, resolve } from "node:path";
190
+ import path, { relative, resolve as resolve2 } from "node:path";
126
191
  function getEntrypointName(entrypointsDir, inputPath) {
127
192
  const relativePath = path.relative(entrypointsDir, inputPath);
128
193
  const name = relativePath.split(/[\.\/\\]/, 2)[0];
129
194
  return name;
130
195
  }
131
196
  function getEntrypointOutputFile(entrypoint, ext) {
132
- return resolve(entrypoint.outputDir, `${entrypoint.name}${ext}`);
197
+ return resolve2(entrypoint.outputDir, `${entrypoint.name}${ext}`);
133
198
  }
134
199
  function getEntrypointBundlePath(entrypoint, outDir, ext) {
135
200
  return normalizePath(
@@ -142,71 +207,371 @@ function resolvePerBrowserOption(option, browser) {
142
207
  return option;
143
208
  }
144
209
 
210
+ // src/core/utils/constants.ts
211
+ var VIRTUAL_NOOP_BACKGROUND_MODULE_ID = "virtual:user-background";
212
+
145
213
  // src/core/utils/building/find-entrypoints.ts
146
- import { relative as relative6, resolve as resolve13 } from "path";
147
- import fs12 from "fs-extra";
148
- import { minimatch } from "minimatch";
149
- import { parseHTML as parseHTML2 } from "linkedom";
150
- import JSON5 from "json5";
214
+ import pc2 from "picocolors";
215
+ async function findEntrypoints() {
216
+ const relativePaths = await glob2(Object.keys(PATH_GLOB_TO_TYPE_MAP), {
217
+ cwd: wxt.config.entrypointsDir
218
+ });
219
+ relativePaths.sort();
220
+ const pathGlobs = Object.keys(PATH_GLOB_TO_TYPE_MAP);
221
+ const entrypointInfos = relativePaths.reduce((results, relativePath) => {
222
+ const inputPath = resolve3(wxt.config.entrypointsDir, relativePath);
223
+ const name = getEntrypointName(wxt.config.entrypointsDir, inputPath);
224
+ const matchingGlob = pathGlobs.find(
225
+ (glob4) => minimatch(relativePath, glob4)
226
+ );
227
+ if (matchingGlob) {
228
+ const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
229
+ results.push({
230
+ name,
231
+ inputPath,
232
+ type,
233
+ skipped: wxt.config.filterEntrypoints != null && !wxt.config.filterEntrypoints.has(name)
234
+ });
235
+ }
236
+ return results;
237
+ }, []);
238
+ preventNoEntrypoints(entrypointInfos);
239
+ preventDuplicateEntrypointNames(entrypointInfos);
240
+ let hasBackground = false;
241
+ const entrypoints = await Promise.all(
242
+ entrypointInfos.map(async (info) => {
243
+ const { type } = info;
244
+ switch (type) {
245
+ case "popup":
246
+ return await getPopupEntrypoint(info);
247
+ case "options":
248
+ return await getOptionsEntrypoint(info);
249
+ case "background":
250
+ hasBackground = true;
251
+ return await getBackgroundEntrypoint(info);
252
+ case "content-script":
253
+ return await getContentScriptEntrypoint(info);
254
+ case "unlisted-page":
255
+ return await getUnlistedPageEntrypoint(info);
256
+ case "unlisted-script":
257
+ return await getUnlistedScriptEntrypoint(info);
258
+ case "content-script-style":
259
+ return {
260
+ ...info,
261
+ type,
262
+ outputDir: resolve3(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
263
+ options: {
264
+ include: void 0,
265
+ exclude: void 0
266
+ }
267
+ };
268
+ default:
269
+ return {
270
+ ...info,
271
+ type,
272
+ outputDir: wxt.config.outDir,
273
+ options: {
274
+ include: void 0,
275
+ exclude: void 0
276
+ }
277
+ };
278
+ }
279
+ })
280
+ );
281
+ if (wxt.config.command === "serve" && !hasBackground) {
282
+ entrypoints.push(
283
+ await getBackgroundEntrypoint({
284
+ inputPath: VIRTUAL_NOOP_BACKGROUND_MODULE_ID,
285
+ name: "background",
286
+ type: "background",
287
+ skipped: false
288
+ })
289
+ );
290
+ }
291
+ wxt.logger.debug("All entrypoints:", entrypoints);
292
+ const skippedEntrypointNames = entrypointInfos.filter((item) => item.skipped).map((item) => item.name);
293
+ if (skippedEntrypointNames.length) {
294
+ wxt.logger.warn(
295
+ `Filter excluded the following entrypoints:
296
+ ${skippedEntrypointNames.map((item) => `${pc2.dim("-")} ${pc2.cyan(item)}`).join("\n")}`
297
+ );
298
+ }
299
+ const targetEntrypoints = entrypoints.filter((entry) => {
300
+ const { include, exclude } = entry.options;
301
+ if (include?.length && exclude?.length) {
302
+ wxt.logger.warn(
303
+ `The ${entry.name} entrypoint lists both include and exclude, but only one can be used per entrypoint. Entrypoint ignored.`
304
+ );
305
+ return false;
306
+ }
307
+ if (exclude?.length && !include?.length) {
308
+ return !exclude.includes(wxt.config.browser);
309
+ }
310
+ if (include?.length && !exclude?.length) {
311
+ return include.includes(wxt.config.browser);
312
+ }
313
+ if (skippedEntrypointNames.includes(entry.name)) {
314
+ return false;
315
+ }
316
+ return true;
317
+ });
318
+ wxt.logger.debug(`${wxt.config.browser} entrypoints:`, targetEntrypoints);
319
+ await wxt.hooks.callHook("entrypoints:resolved", wxt, targetEntrypoints);
320
+ return targetEntrypoints;
321
+ }
322
+ function preventDuplicateEntrypointNames(files) {
323
+ const namesToPaths = files.reduce(
324
+ (map, { name, inputPath }) => {
325
+ map[name] ??= [];
326
+ map[name].push(inputPath);
327
+ return map;
328
+ },
329
+ {}
330
+ );
331
+ const errorLines = Object.entries(namesToPaths).reduce(
332
+ (lines, [name, absolutePaths]) => {
333
+ if (absolutePaths.length > 1) {
334
+ lines.push(`- ${name}`);
335
+ absolutePaths.forEach((absolutePath) => {
336
+ lines.push(` - ${relative2(wxt.config.root, absolutePath)}`);
337
+ });
338
+ }
339
+ return lines;
340
+ },
341
+ []
342
+ );
343
+ if (errorLines.length > 0) {
344
+ const errorContent = errorLines.join("\n");
345
+ throw Error(
346
+ `Multiple entrypoints with the same name detected, only one entrypoint for each name is allowed.
151
347
 
152
- // src/core/utils/fs.ts
153
- import fs from "fs-extra";
154
- import glob from "fast-glob";
155
- async function writeFileIfDifferent(file, newContents) {
156
- const existingContents = await fs.readFile(file, "utf-8").catch(() => void 0);
157
- if (existingContents !== newContents) {
158
- await fs.writeFile(file, newContents);
348
+ ${errorContent}`
349
+ );
159
350
  }
160
351
  }
161
- async function getPublicFiles(config) {
162
- if (!await fs.exists(config.publicDir))
163
- return [];
164
- const files = await glob("**/*", { cwd: config.publicDir });
165
- return files.map(unnormalizePath);
352
+ function preventNoEntrypoints(files) {
353
+ if (files.length === 0) {
354
+ throw Error(`No entrypoints found in ${wxt.config.entrypointsDir}`);
355
+ }
166
356
  }
167
-
168
- // src/core/utils/building/build-entrypoints.ts
169
- import fs2 from "fs-extra";
170
- import { dirname, resolve as resolve2 } from "path";
171
- import pc from "picocolors";
172
- async function buildEntrypoints(groups, config, spinner) {
173
- const steps = [];
174
- for (let i = 0; i < groups.length; i++) {
175
- const group = groups[i];
176
- const groupNames = [group].flat().map((e) => e.name);
177
- const groupNameColored = groupNames.join(pc.dim(", "));
178
- spinner.text = pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNameColored}`;
357
+ function getHtmlBaseOptions(document) {
358
+ const options = {};
359
+ const includeContent = document.querySelector("meta[name='manifest.include']")?.getAttribute("content");
360
+ if (includeContent) {
361
+ options.include = JSON5.parse(includeContent);
362
+ }
363
+ const excludeContent = document.querySelector("meta[name='manifest.exclude']")?.getAttribute("content");
364
+ if (excludeContent) {
365
+ options.exclude = JSON5.parse(excludeContent);
366
+ }
367
+ return options;
368
+ }
369
+ async function getPopupEntrypoint({
370
+ inputPath,
371
+ name,
372
+ skipped
373
+ }) {
374
+ const content = await fs3.readFile(inputPath, "utf-8");
375
+ const { document } = parseHTML(content);
376
+ const options = getHtmlBaseOptions(document);
377
+ const title = document.querySelector("title");
378
+ if (title != null)
379
+ options.defaultTitle = title.textContent ?? void 0;
380
+ const defaultIconContent = document.querySelector("meta[name='manifest.default_icon']")?.getAttribute("content");
381
+ if (defaultIconContent) {
179
382
  try {
180
- steps.push(await config.builder.build(group));
383
+ options.defaultIcon = JSON5.parse(defaultIconContent);
181
384
  } catch (err) {
182
- throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
385
+ wxt.logger.fatal(
386
+ `Failed to parse default_icon meta tag content as JSON5. content=${defaultIconContent}`,
387
+ err
388
+ );
183
389
  }
184
390
  }
185
- const publicAssets = await copyPublicDirectory(config);
186
- return { publicAssets, steps };
187
- }
188
- async function copyPublicDirectory(config) {
189
- const files = await getPublicFiles(config);
190
- if (files.length === 0)
191
- return [];
192
- const publicAssets = [];
193
- for (const file of files) {
194
- const srcPath = resolve2(config.publicDir, file);
195
- const outPath = resolve2(config.outDir, file);
196
- await fs2.ensureDir(dirname(outPath));
197
- await fs2.copyFile(srcPath, outPath);
198
- publicAssets.push({
199
- type: "asset",
200
- fileName: file
201
- });
391
+ const mv2TypeContent = document.querySelector("meta[name='manifest.type']")?.getAttribute("content");
392
+ if (mv2TypeContent) {
393
+ options.mv2Key = mv2TypeContent === "page_action" ? "page_action" : "browser_action";
202
394
  }
203
- return publicAssets;
395
+ const browserStyleContent = document.querySelector("meta[name='manifest.browser_style']")?.getAttribute("content");
396
+ if (browserStyleContent) {
397
+ options.browserStyle = browserStyleContent === "true";
398
+ }
399
+ return {
400
+ type: "popup",
401
+ name: "popup",
402
+ options,
403
+ inputPath,
404
+ outputDir: wxt.config.outDir,
405
+ skipped
406
+ };
204
407
  }
205
-
408
+ async function getOptionsEntrypoint({
409
+ inputPath,
410
+ name,
411
+ skipped
412
+ }) {
413
+ const content = await fs3.readFile(inputPath, "utf-8");
414
+ const { document } = parseHTML(content);
415
+ const options = getHtmlBaseOptions(document);
416
+ const openInTabContent = document.querySelector("meta[name='manifest.open_in_tab']")?.getAttribute("content");
417
+ if (openInTabContent) {
418
+ options.openInTab = openInTabContent === "true";
419
+ }
420
+ const chromeStyleContent = document.querySelector("meta[name='manifest.chrome_style']")?.getAttribute("content");
421
+ if (chromeStyleContent) {
422
+ options.chromeStyle = chromeStyleContent === "true";
423
+ }
424
+ const browserStyleContent = document.querySelector("meta[name='manifest.browser_style']")?.getAttribute("content");
425
+ if (browserStyleContent) {
426
+ options.browserStyle = browserStyleContent === "true";
427
+ }
428
+ return {
429
+ type: "options",
430
+ name: "options",
431
+ options,
432
+ inputPath,
433
+ outputDir: wxt.config.outDir,
434
+ skipped
435
+ };
436
+ }
437
+ async function getUnlistedPageEntrypoint({
438
+ inputPath,
439
+ name,
440
+ skipped
441
+ }) {
442
+ const content = await fs3.readFile(inputPath, "utf-8");
443
+ const { document } = parseHTML(content);
444
+ return {
445
+ type: "unlisted-page",
446
+ name: getEntrypointName(wxt.config.entrypointsDir, inputPath),
447
+ inputPath,
448
+ outputDir: wxt.config.outDir,
449
+ options: getHtmlBaseOptions(document),
450
+ skipped
451
+ };
452
+ }
453
+ async function getUnlistedScriptEntrypoint({
454
+ inputPath,
455
+ name,
456
+ skipped
457
+ }) {
458
+ const defaultExport = await importEntrypointFile(inputPath);
459
+ if (defaultExport == null) {
460
+ throw Error(
461
+ `${name}: Default export not found, did you forget to call "export default defineUnlistedScript(...)"?`
462
+ );
463
+ }
464
+ const { main: _, ...moduleOptions } = defaultExport;
465
+ const options = moduleOptions;
466
+ return {
467
+ type: "unlisted-script",
468
+ name,
469
+ inputPath,
470
+ outputDir: wxt.config.outDir,
471
+ options,
472
+ skipped
473
+ };
474
+ }
475
+ async function getBackgroundEntrypoint({
476
+ inputPath,
477
+ name,
478
+ skipped
479
+ }) {
480
+ let options = {};
481
+ if (inputPath !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
482
+ const defaultExport = await importEntrypointFile(inputPath);
483
+ if (defaultExport == null) {
484
+ throw Error(
485
+ `${name}: Default export not found, did you forget to call "export default defineBackground(...)"?`
486
+ );
487
+ }
488
+ const { main: _, ...moduleOptions } = defaultExport;
489
+ options = moduleOptions;
490
+ }
491
+ if (wxt.config.manifestVersion !== 3) {
492
+ delete options.type;
493
+ }
494
+ return {
495
+ type: "background",
496
+ name,
497
+ inputPath,
498
+ outputDir: wxt.config.outDir,
499
+ options: {
500
+ ...options,
501
+ type: resolvePerBrowserOption(options.type, wxt.config.browser),
502
+ persistent: resolvePerBrowserOption(
503
+ options.persistent,
504
+ wxt.config.browser
505
+ )
506
+ },
507
+ skipped
508
+ };
509
+ }
510
+ async function getContentScriptEntrypoint({
511
+ inputPath,
512
+ name,
513
+ skipped
514
+ }) {
515
+ const { main: _, ...options } = await importEntrypointFile(inputPath);
516
+ if (options == null) {
517
+ throw Error(
518
+ `${name}: Default export not found, did you forget to call "export default defineContentScript(...)"?`
519
+ );
520
+ }
521
+ return {
522
+ type: "content-script",
523
+ name,
524
+ inputPath,
525
+ outputDir: resolve3(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
526
+ options,
527
+ skipped
528
+ };
529
+ }
530
+ var PATH_GLOB_TO_TYPE_MAP = {
531
+ "sandbox.html": "sandbox",
532
+ "sandbox/index.html": "sandbox",
533
+ "*.sandbox.html": "sandbox",
534
+ "*.sandbox/index.html": "sandbox",
535
+ "bookmarks.html": "bookmarks",
536
+ "bookmarks/index.html": "bookmarks",
537
+ "history.html": "history",
538
+ "history/index.html": "history",
539
+ "newtab.html": "newtab",
540
+ "newtab/index.html": "newtab",
541
+ "sidepanel.html": "sidepanel",
542
+ "sidepanel/index.html": "sidepanel",
543
+ "*.sidepanel.html": "sidepanel",
544
+ "*.sidepanel/index.html": "sidepanel",
545
+ "devtools.html": "devtools",
546
+ "devtools/index.html": "devtools",
547
+ "background.[jt]s": "background",
548
+ "background/index.[jt]s": "background",
549
+ [VIRTUAL_NOOP_BACKGROUND_MODULE_ID]: "background",
550
+ "content.[jt]s?(x)": "content-script",
551
+ "content/index.[jt]s?(x)": "content-script",
552
+ "*.content.[jt]s?(x)": "content-script",
553
+ "*.content/index.[jt]s?(x)": "content-script",
554
+ [`content.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
555
+ [`*.content.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
556
+ [`content/index.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
557
+ [`*.content/index.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
558
+ "popup.html": "popup",
559
+ "popup/index.html": "popup",
560
+ "options.html": "options",
561
+ "options/index.html": "options",
562
+ "*.html": "unlisted-page",
563
+ "*/index.html": "unlisted-page",
564
+ "*.[jt]s?(x)": "unlisted-script",
565
+ "*/index.[jt]s?(x)": "unlisted-script",
566
+ [`*.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style",
567
+ [`*/index.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style"
568
+ };
569
+ var CONTENT_SCRIPT_OUT_DIR = "content-scripts";
570
+
206
571
  // src/core/utils/building/generate-wxt-dir.ts
207
572
  import { createUnimport } from "unimport";
208
- import fs3 from "fs-extra";
209
- import { relative as relative2, resolve as resolve3 } from "path";
573
+ import fs4 from "fs-extra";
574
+ import { relative as relative3, resolve as resolve4 } from "path";
210
575
 
211
576
  // src/core/utils/unimport.ts
212
577
  import { defu } from "defu";
@@ -327,23 +692,23 @@ function parseI18nMessages(messagesJson) {
327
692
  }
328
693
 
329
694
  // src/core/utils/building/generate-wxt-dir.ts
330
- async function generateTypesDir(entrypoints, config) {
331
- await fs3.ensureDir(config.typesDir);
695
+ async function generateTypesDir(entrypoints) {
696
+ await fs4.ensureDir(wxt.config.typesDir);
332
697
  const references = [];
333
- const imports = getUnimportOptions(config);
698
+ const imports = getUnimportOptions(wxt.config);
334
699
  if (imports !== false) {
335
- references.push(await writeImportsDeclarationFile(config, imports));
700
+ references.push(await writeImportsDeclarationFile(imports));
336
701
  }
337
- references.push(await writePathsDeclarationFile(entrypoints, config));
338
- references.push(await writeI18nDeclarationFile(config));
339
- references.push(await writeGlobalsDeclarationFile(config));
340
- const mainReference = await writeMainDeclarationFile(references, config);
341
- await writeTsConfigFile(mainReference, config);
702
+ references.push(await writePathsDeclarationFile(entrypoints));
703
+ references.push(await writeI18nDeclarationFile());
704
+ references.push(await writeGlobalsDeclarationFile());
705
+ const mainReference = await writeMainDeclarationFile(references);
706
+ await writeTsConfigFile(mainReference);
342
707
  }
343
- async function writeImportsDeclarationFile(config, unimportOptions) {
344
- const filePath = resolve3(config.typesDir, "imports.d.ts");
708
+ async function writeImportsDeclarationFile(unimportOptions) {
709
+ const filePath = resolve4(wxt.config.typesDir, "imports.d.ts");
345
710
  const unimport2 = createUnimport(unimportOptions);
346
- await unimport2.scanImportsFromDir(void 0, { cwd: config.srcDir });
711
+ await unimport2.scanImportsFromDir(void 0, { cwd: wxt.config.srcDir });
347
712
  await writeFileIfDifferent(
348
713
  filePath,
349
714
  ["// Generated by wxt", await unimport2.generateTypeDeclarations()].join(
@@ -352,15 +717,15 @@ async function writeImportsDeclarationFile(config, unimportOptions) {
352
717
  );
353
718
  return filePath;
354
719
  }
355
- async function writePathsDeclarationFile(entrypoints, config) {
356
- const filePath = resolve3(config.typesDir, "paths.d.ts");
720
+ async function writePathsDeclarationFile(entrypoints) {
721
+ const filePath = resolve4(wxt.config.typesDir, "paths.d.ts");
357
722
  const unions = entrypoints.map(
358
723
  (entry) => getEntrypointBundlePath(
359
724
  entry,
360
- config.outDir,
725
+ wxt.config.outDir,
361
726
  entry.inputPath.endsWith(".html") ? ".html" : ".js"
362
727
  )
363
- ).concat(await getPublicFiles(config)).map(normalizePath).map((path6) => ` | "/${path6}"`).sort().join("\n");
728
+ ).concat(await getPublicFiles()).map(normalizePath).map((path7) => ` | "/${path7}"`).sort().join("\n");
364
729
  const template = `// Generated by wxt
365
730
  import "wxt/browser";
366
731
 
@@ -380,9 +745,9 @@ declare module "wxt/browser" {
380
745
  );
381
746
  return filePath;
382
747
  }
383
- async function writeI18nDeclarationFile(config) {
384
- const filePath = resolve3(config.typesDir, "i18n.d.ts");
385
- const defaultLocale = config.manifest.default_locale;
748
+ async function writeI18nDeclarationFile() {
749
+ const filePath = resolve4(wxt.config.typesDir, "i18n.d.ts");
750
+ const defaultLocale = wxt.config.manifest.default_locale;
386
751
  const template = `// Generated by wxt
387
752
  import "wxt/browser";
388
753
 
@@ -405,12 +770,12 @@ declare module "wxt/browser" {
405
770
  let messages;
406
771
  if (defaultLocale) {
407
772
  const defaultLocalePath = path2.resolve(
408
- config.publicDir,
773
+ wxt.config.publicDir,
409
774
  "_locales",
410
775
  defaultLocale,
411
776
  "messages.json"
412
777
  );
413
- const content = JSON.parse(await fs3.readFile(defaultLocalePath, "utf-8"));
778
+ const content = JSON.parse(await fs4.readFile(defaultLocalePath, "utf-8"));
414
779
  messages = parseI18nMessages(content);
415
780
  } else {
416
781
  messages = parseI18nMessages({});
@@ -433,9 +798,9 @@ declare module "wxt/browser" {
433
798
  );
434
799
  return filePath;
435
800
  }
436
- async function writeGlobalsDeclarationFile(config) {
437
- const filePath = resolve3(config.typesDir, "globals.d.ts");
438
- const globals2 = [...getGlobals(config), ...getEntrypointGlobals("")];
801
+ async function writeGlobalsDeclarationFile() {
802
+ const filePath = resolve4(wxt.config.typesDir, "globals.d.ts");
803
+ const globals2 = [...getGlobals(wxt.config), ...getEntrypointGlobals("")];
439
804
  await writeFileIfDifferent(
440
805
  filePath,
441
806
  [
@@ -451,25 +816,25 @@ async function writeGlobalsDeclarationFile(config) {
451
816
  );
452
817
  return filePath;
453
818
  }
454
- async function writeMainDeclarationFile(references, config) {
455
- const dir = config.wxtDir;
456
- const filePath = resolve3(dir, "wxt.d.ts");
819
+ async function writeMainDeclarationFile(references) {
820
+ const dir = wxt.config.wxtDir;
821
+ const filePath = resolve4(dir, "wxt.d.ts");
457
822
  await writeFileIfDifferent(
458
823
  filePath,
459
824
  [
460
825
  "// Generated by wxt",
461
826
  `/// <reference types="wxt/vite-builder-env" />`,
462
827
  ...references.map(
463
- (ref) => `/// <reference types="./${normalizePath(relative2(dir, ref))}" />`
828
+ (ref) => `/// <reference types="./${normalizePath(relative3(dir, ref))}" />`
464
829
  )
465
830
  ].join("\n") + "\n"
466
831
  );
467
832
  return filePath;
468
833
  }
469
- async function writeTsConfigFile(mainReference, config) {
470
- const dir = config.wxtDir;
471
- const getTsconfigPath = (path6) => normalizePath(relative2(dir, path6));
472
- const paths = Object.entries(config.alias).flatMap(([alias, absolutePath]) => {
834
+ async function writeTsConfigFile(mainReference) {
835
+ const dir = wxt.config.wxtDir;
836
+ const getTsconfigPath = (path7) => normalizePath(relative3(dir, path7));
837
+ const paths = Object.entries(wxt.config.alias).flatMap(([alias, absolutePath]) => {
473
838
  const aliasPath = getTsconfigPath(absolutePath);
474
839
  return [
475
840
  ` "${alias}": ["${aliasPath}"]`,
@@ -477,7 +842,7 @@ async function writeTsConfigFile(mainReference, config) {
477
842
  ];
478
843
  }).join(",\n");
479
844
  await writeFileIfDifferent(
480
- resolve3(dir, "tsconfig.json"),
845
+ resolve4(dir, "tsconfig.json"),
481
846
  `{
482
847
  "compilerOptions": {
483
848
  "target": "ESNext",
@@ -494,33 +859,33 @@ ${paths}
494
859
  }
495
860
  },
496
861
  "include": [
497
- "${getTsconfigPath(config.root)}/**/*",
862
+ "${getTsconfigPath(wxt.config.root)}/**/*",
498
863
  "./${getTsconfigPath(mainReference)}"
499
864
  ],
500
- "exclude": ["${getTsconfigPath(config.outBaseDir)}"]
865
+ "exclude": ["${getTsconfigPath(wxt.config.outBaseDir)}"]
501
866
  }`
502
867
  );
503
868
  }
504
869
 
505
- // src/core/utils/building/get-internal-config.ts
870
+ // src/core/utils/building/resolve-config.ts
506
871
  import { loadConfig } from "c12";
507
- import path4 from "node:path";
872
+ import path5 from "node:path";
508
873
 
509
874
  // src/core/utils/cache.ts
510
- import fs4, { ensureDir } from "fs-extra";
511
- import { dirname as dirname2, resolve as resolve4 } from "path";
875
+ import fs5, { ensureDir } from "fs-extra";
876
+ import { dirname as dirname2, resolve as resolve5 } from "path";
512
877
  function createFsCache(wxtDir) {
513
- const getPath = (key) => resolve4(wxtDir, "cache", encodeURIComponent(key));
878
+ const getPath = (key) => resolve5(wxtDir, "cache", encodeURIComponent(key));
514
879
  return {
515
880
  async set(key, value) {
516
- const path6 = getPath(key);
517
- await ensureDir(dirname2(path6));
518
- await writeFileIfDifferent(path6, value);
881
+ const path7 = getPath(key);
882
+ await ensureDir(dirname2(path7));
883
+ await writeFileIfDifferent(path7, value);
519
884
  },
520
885
  async get(key) {
521
- const path6 = getPath(key);
886
+ const path7 = getPath(key);
522
887
  try {
523
- return await fs4.readFile(path6, "utf-8");
888
+ return await fs5.readFile(path7, "utf-8");
524
889
  } catch {
525
890
  return void 0;
526
891
  }
@@ -528,16 +893,16 @@ function createFsCache(wxtDir) {
528
893
  };
529
894
  }
530
895
 
531
- // src/core/utils/building/get-internal-config.ts
896
+ // src/core/utils/building/resolve-config.ts
532
897
  import consola, { LogLevels } from "consola";
533
898
 
534
899
  // src/core/builders/vite/plugins/devHtmlPrerender.ts
535
- import { parseHTML } from "linkedom";
536
- import { dirname as dirname3, relative as relative3, resolve as resolve5 } from "node:path";
900
+ import { parseHTML as parseHTML2 } from "linkedom";
901
+ import { dirname as dirname3, relative as relative4, resolve as resolve6 } from "node:path";
537
902
  var reactRefreshPreamble = "";
538
903
  function devHtmlPrerender(config) {
539
904
  const htmlReloadId = "@wxt/reload-html";
540
- const resolvedHtmlReloadId = resolve5(
905
+ const resolvedHtmlReloadId = resolve6(
541
906
  config.root,
542
907
  "node_modules/wxt/dist/virtual/reload-html.js"
543
908
  );
@@ -562,7 +927,7 @@ function devHtmlPrerender(config) {
562
927
  const server = config.server;
563
928
  if (config.command !== "serve" || server == null || !id.endsWith(".html"))
564
929
  return;
565
- const { document } = parseHTML(code);
930
+ const { document } = parseHTML2(code);
566
931
  const _pointToDevServer = (querySelector, attr) => pointToDevServer(config, server, id, document, querySelector, attr);
567
932
  _pointToDevServer("script[type=module]", "src");
568
933
  _pointToDevServer("link[rel=stylesheet]", "href");
@@ -585,7 +950,7 @@ function devHtmlPrerender(config) {
585
950
  const name = getEntrypointName(config.entrypointsDir, ctx.filename);
586
951
  const url = `${server.origin}/${name}.html`;
587
952
  const serverHtml = await server.transformHtml(url, html, originalUrl);
588
- const { document } = parseHTML(serverHtml);
953
+ const { document } = parseHTML2(serverHtml);
589
954
  const reactRefreshScript = Array.from(
590
955
  document.querySelectorAll("script[type=module]")
591
956
  ).find((script) => script.innerHTML.includes("@react-refresh"));
@@ -642,22 +1007,22 @@ function pointToDevServer(config, server, id, document, querySelector, attr) {
642
1007
  );
643
1008
  if (matchingAlias) {
644
1009
  const [alias, replacement] = matchingAlias;
645
- resolvedAbsolutePath = resolve5(
1010
+ resolvedAbsolutePath = resolve6(
646
1011
  config.root,
647
1012
  src.replace(alias, replacement)
648
1013
  );
649
1014
  } else {
650
- resolvedAbsolutePath = resolve5(dirname3(id), src);
1015
+ resolvedAbsolutePath = resolve6(dirname3(id), src);
651
1016
  }
652
1017
  if (resolvedAbsolutePath) {
653
1018
  const relativePath = normalizePath(
654
- relative3(config.root, resolvedAbsolutePath)
1019
+ relative4(config.root, resolvedAbsolutePath)
655
1020
  );
656
1021
  if (relativePath.startsWith(".")) {
657
- let path6 = normalizePath(resolvedAbsolutePath);
658
- if (!path6.startsWith("/"))
659
- path6 = "/" + path6;
660
- element.setAttribute(attr, `${server.origin}/@fs${path6}`);
1022
+ let path7 = normalizePath(resolvedAbsolutePath);
1023
+ if (!path7.startsWith("/"))
1024
+ path7 = "/" + path7;
1025
+ element.setAttribute(attr, `${server.origin}/@fs${path7}`);
661
1026
  } else {
662
1027
  const url = new URL(relativePath, server.origin);
663
1028
  element.setAttribute(attr, url.href);
@@ -771,8 +1136,8 @@ function download(config) {
771
1136
  }
772
1137
 
773
1138
  // src/core/builders/vite/plugins/multipageMove.ts
774
- import { dirname as dirname4, extname, resolve as resolve6, join } from "node:path";
775
- import fs5, { ensureDir as ensureDir2 } from "fs-extra";
1139
+ import { dirname as dirname4, extname, resolve as resolve7, join } from "node:path";
1140
+ import fs6, { ensureDir as ensureDir2 } from "fs-extra";
776
1141
  function multipageMove(entrypoints, config) {
777
1142
  return {
778
1143
  name: "wxt:multipage-move",
@@ -799,10 +1164,10 @@ function multipageMove(entrypoints, config) {
799
1164
  );
800
1165
  continue;
801
1166
  }
802
- const oldAbsPath = resolve6(config.outDir, oldBundlePath);
803
- const newAbsPath = resolve6(config.outDir, newBundlePath);
1167
+ const oldAbsPath = resolve7(config.outDir, oldBundlePath);
1168
+ const newAbsPath = resolve7(config.outDir, newBundlePath);
804
1169
  await ensureDir2(dirname4(newAbsPath));
805
- await fs5.move(oldAbsPath, newAbsPath, { overwrite: true });
1170
+ await fs6.move(oldAbsPath, newAbsPath, { overwrite: true });
806
1171
  const renamedChunk = {
807
1172
  ...bundle[oldBundlePath],
808
1173
  fileName: newBundlePath
@@ -815,16 +1180,16 @@ function multipageMove(entrypoints, config) {
815
1180
  };
816
1181
  }
817
1182
  async function removeEmptyDirs(dir) {
818
- const files = await fs5.readdir(dir);
1183
+ const files = await fs6.readdir(dir);
819
1184
  for (const file of files) {
820
1185
  const filePath = join(dir, file);
821
- const stats = await fs5.stat(filePath);
1186
+ const stats = await fs6.stat(filePath);
822
1187
  if (stats.isDirectory()) {
823
1188
  await removeEmptyDirs(filePath);
824
1189
  }
825
1190
  }
826
1191
  try {
827
- await fs5.rmdir(dir);
1192
+ await fs6.rmdir(dir);
828
1193
  } catch {
829
1194
  }
830
1195
  }
@@ -865,8 +1230,8 @@ function unimport(config) {
865
1230
  }
866
1231
 
867
1232
  // src/core/builders/vite/plugins/virtualEntrypoint.ts
868
- import fs6 from "fs-extra";
869
- import { resolve as resolve7 } from "path";
1233
+ import fs7 from "fs-extra";
1234
+ import { resolve as resolve8 } from "path";
870
1235
  function virtualEntrypoint(type, config) {
871
1236
  const virtualId = `virtual:wxt-${type}?`;
872
1237
  const resolvedVirtualId = `\0${virtualId}`;
@@ -883,8 +1248,8 @@ function virtualEntrypoint(type, config) {
883
1248
  if (!id.startsWith(resolvedVirtualId))
884
1249
  return;
885
1250
  const inputPath = id.replace(resolvedVirtualId, "");
886
- const template = await fs6.readFile(
887
- resolve7(
1251
+ const template = await fs7.readFile(
1252
+ resolve8(
888
1253
  config.root,
889
1254
  `node_modules/wxt/dist/virtual/${type}-entrypoint.js`
890
1255
  ),
@@ -909,9 +1274,6 @@ function tsconfigPaths(config) {
909
1274
  };
910
1275
  }
911
1276
 
912
- // src/core/utils/constants.ts
913
- var VIRTUAL_NOOP_BACKGROUND_MODULE_ID = "virtual:user-background";
914
-
915
1277
  // src/core/builders/vite/plugins/noopBackground.ts
916
1278
  function noopBackground() {
917
1279
  const virtualModuleId = VIRTUAL_NOOP_BACKGROUND_MODULE_ID;
@@ -957,12 +1319,12 @@ function cssEntrypoints(entrypoint, config) {
957
1319
 
958
1320
  // src/core/builders/vite/plugins/bundleAnalysis.ts
959
1321
  import { visualizer } from "rollup-plugin-visualizer";
1322
+ import path3 from "node:path";
960
1323
  var increment = 0;
961
- function bundleAnalysis() {
1324
+ function bundleAnalysis(config) {
962
1325
  return visualizer({
963
- emitFile: true,
964
1326
  template: "raw-data",
965
- filename: `stats-${increment++}.json`
1327
+ filename: path3.resolve(config.outDir, `stats-${increment++}.json`)
966
1328
  });
967
1329
  }
968
1330
 
@@ -983,7 +1345,7 @@ function globals(config) {
983
1345
  }
984
1346
 
985
1347
  // src/core/builders/vite/plugins/webextensionPolyfillMock.ts
986
- import path3 from "node:path";
1348
+ import path4 from "node:path";
987
1349
  function webextensionPolyfillMock(config) {
988
1350
  return {
989
1351
  name: "wxt:testing-inline-deps",
@@ -992,7 +1354,7 @@ function webextensionPolyfillMock(config) {
992
1354
  resolve: {
993
1355
  alias: {
994
1356
  // Alias to use a mocked version of the polyfill
995
- "webextension-polyfill": path3.resolve(
1357
+ "webextension-polyfill": path4.resolve(
996
1358
  config.root,
997
1359
  "node_modules/wxt/dist/virtual/mock-browser"
998
1360
  )
@@ -1103,7 +1465,7 @@ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
1103
1465
  defineImportMeta()
1104
1466
  );
1105
1467
  if (wxtConfig.analysis.enabled) {
1106
- config.plugins.push(bundleAnalysis());
1468
+ config.plugins.push(bundleAnalysis(wxtConfig));
1107
1469
  }
1108
1470
  return config;
1109
1471
  };
@@ -1278,9 +1640,9 @@ function getRollupEntry(entrypoint) {
1278
1640
  return virtualEntrypointType ? `virtual:wxt-${virtualEntrypointType}?${entrypoint.inputPath}` : entrypoint.inputPath;
1279
1641
  }
1280
1642
 
1281
- // src/core/utils/building/get-internal-config.ts
1643
+ // src/core/utils/building/resolve-config.ts
1282
1644
  import defu2 from "defu";
1283
- async function getInternalConfig(inlineConfig, command, server) {
1645
+ async function resolveConfig(inlineConfig, command, server) {
1284
1646
  let userConfig = {};
1285
1647
  let userConfigMetadata;
1286
1648
  if (inlineConfig.configFile !== false) {
@@ -1304,20 +1666,20 @@ async function getInternalConfig(inlineConfig, command, server) {
1304
1666
  const manifestVersion = mergedConfig.manifestVersion ?? (browser === "firefox" || browser === "safari" ? 2 : 3);
1305
1667
  const mode = mergedConfig.mode ?? (command === "build" ? "production" : "development");
1306
1668
  const env = { browser, command, manifestVersion, mode };
1307
- const root = path4.resolve(
1669
+ const root = path5.resolve(
1308
1670
  inlineConfig.root ?? userConfig.root ?? process.cwd()
1309
1671
  );
1310
- const wxtDir = path4.resolve(root, ".wxt");
1311
- const srcDir = path4.resolve(root, mergedConfig.srcDir ?? root);
1312
- const entrypointsDir = path4.resolve(
1672
+ const wxtDir = path5.resolve(root, ".wxt");
1673
+ const srcDir = path5.resolve(root, mergedConfig.srcDir ?? root);
1674
+ const entrypointsDir = path5.resolve(
1313
1675
  srcDir,
1314
1676
  mergedConfig.entrypointsDir ?? "entrypoints"
1315
1677
  );
1316
1678
  const filterEntrypoints = !!mergedConfig.filterEntrypoints?.length ? new Set(mergedConfig.filterEntrypoints) : void 0;
1317
- const publicDir = path4.resolve(srcDir, mergedConfig.publicDir ?? "public");
1318
- const typesDir = path4.resolve(wxtDir, "types");
1319
- const outBaseDir = path4.resolve(root, mergedConfig.outDir ?? ".output");
1320
- const outDir = path4.resolve(outBaseDir, `${browser}-mv${manifestVersion}`);
1679
+ const publicDir = path5.resolve(srcDir, mergedConfig.publicDir ?? "public");
1680
+ const typesDir = path5.resolve(wxtDir, "types");
1681
+ const outBaseDir = path5.resolve(root, mergedConfig.outDir ?? ".output");
1682
+ const outDir = path5.resolve(outBaseDir, `${browser}-mv${manifestVersion}`);
1321
1683
  const reloadCommand = mergedConfig.dev?.reloadCommand ?? "Alt+R";
1322
1684
  const runnerConfig = await loadConfig({
1323
1685
  name: "web-ext",
@@ -1334,7 +1696,7 @@ async function getInternalConfig(inlineConfig, command, server) {
1334
1696
  "~": srcDir,
1335
1697
  "@@": root,
1336
1698
  "~~": root
1337
- }).map(([key, value]) => [key, path4.resolve(root, value)])
1699
+ }).map(([key, value]) => [key, path5.resolve(root, value)])
1338
1700
  );
1339
1701
  const finalConfig = {
1340
1702
  browser,
@@ -1364,7 +1726,11 @@ async function getInternalConfig(inlineConfig, command, server) {
1364
1726
  },
1365
1727
  analysis: {
1366
1728
  enabled: mergedConfig.analysis?.enabled ?? false,
1367
- template: mergedConfig.analysis?.template ?? "treemap"
1729
+ template: mergedConfig.analysis?.template ?? "treemap",
1730
+ outputFile: path5.resolve(
1731
+ root,
1732
+ mergedConfig.analysis?.outputFile ?? "stats.html"
1733
+ )
1368
1734
  },
1369
1735
  userConfigMetadata: userConfigMetadata ?? {},
1370
1736
  alias,
@@ -1374,7 +1740,8 @@ async function getInternalConfig(inlineConfig, command, server) {
1374
1740
  server,
1375
1741
  dev: {
1376
1742
  reloadCommand
1377
- }
1743
+ },
1744
+ hooks: mergedConfig.hooks ?? {}
1378
1745
  };
1379
1746
  const builder = await createViteBuilder(
1380
1747
  inlineConfig,
@@ -1411,6 +1778,10 @@ function mergeInlineConfig(inlineConfig, userConfig) {
1411
1778
  inlineConfig.zip ?? {},
1412
1779
  userConfig.zip ?? {}
1413
1780
  );
1781
+ const hooks = defu2(
1782
+ inlineConfig.hooks ?? {},
1783
+ userConfig.hooks ?? {}
1784
+ );
1414
1785
  return {
1415
1786
  root: inlineConfig.root ?? userConfig.root,
1416
1787
  browser: inlineConfig.browser ?? userConfig.browser,
@@ -1429,8 +1800,8 @@ function mergeInlineConfig(inlineConfig, userConfig) {
1429
1800
  outDir: inlineConfig.outDir ?? userConfig.outDir,
1430
1801
  zip,
1431
1802
  analysis: {
1432
- enabled: inlineConfig.analysis?.enabled ?? userConfig.analysis?.enabled,
1433
- template: inlineConfig.analysis?.template ?? userConfig.analysis?.template
1803
+ ...userConfig.analysis,
1804
+ ...inlineConfig.analysis
1434
1805
  },
1435
1806
  alias: {
1436
1807
  ...userConfig.alias,
@@ -1445,7 +1816,8 @@ function mergeInlineConfig(inlineConfig, userConfig) {
1445
1816
  dev: {
1446
1817
  ...userConfig.dev,
1447
1818
  ...inlineConfig.dev
1448
- }
1819
+ },
1820
+ hooks
1449
1821
  };
1450
1822
  }
1451
1823
  function resolveInternalZipConfig(root, mergedConfig) {
@@ -1513,8 +1885,8 @@ var ENTRY_TYPE_TO_GROUP_MAP = {
1513
1885
  // src/core/utils/building/import-entrypoint.ts
1514
1886
  import createJITI from "jiti";
1515
1887
  import { createUnimport as createUnimport3 } from "unimport";
1516
- import fs7 from "fs-extra";
1517
- import { relative as relative4, resolve as resolve8 } from "node:path";
1888
+ import fs8 from "fs-extra";
1889
+ import { relative as relative5, resolve as resolve9 } from "node:path";
1518
1890
 
1519
1891
  // src/core/utils/strings.ts
1520
1892
  function kebabCaseAlphanumeric(str) {
@@ -1536,30 +1908,30 @@ ${noImports}`;
1536
1908
  // src/core/utils/building/import-entrypoint.ts
1537
1909
  import { transformSync } from "esbuild";
1538
1910
  import { fileURLToPath } from "node:url";
1539
- async function importEntrypointFile(path6, config) {
1540
- config.logger.debug("Loading file metadata:", path6);
1541
- const normalPath = normalizePath(path6);
1911
+ async function importEntrypointFile(path7) {
1912
+ wxt.logger.debug("Loading file metadata:", path7);
1913
+ const normalPath = normalizePath(path7);
1542
1914
  const unimport2 = createUnimport3({
1543
- ...getUnimportOptions(config),
1915
+ ...getUnimportOptions(wxt.config),
1544
1916
  // Only allow specific imports, not all from the project
1545
1917
  dirs: []
1546
1918
  });
1547
1919
  await unimport2.init();
1548
- const text = await fs7.readFile(path6, "utf-8");
1920
+ const text = await fs8.readFile(path7, "utf-8");
1549
1921
  const textNoImports = removeProjectImportStatements(text);
1550
1922
  const { code } = await unimport2.injectImports(textNoImports);
1551
- config.logger.debug(
1923
+ wxt.logger.debug(
1552
1924
  ["Text:", text, "No imports:", textNoImports, "Code:", code].join("\n")
1553
1925
  );
1554
1926
  const jiti = createJITI(
1555
1927
  typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url),
1556
1928
  {
1557
1929
  cache: false,
1558
- debug: config.debug,
1930
+ debug: wxt.config.debug,
1559
1931
  esmResolve: true,
1560
1932
  alias: {
1561
- "webextension-polyfill": resolve8(
1562
- config.root,
1933
+ "webextension-polyfill": resolve9(
1934
+ wxt.config.root,
1563
1935
  "node_modules/wxt/dist/virtual/mock-browser.js"
1564
1936
  )
1565
1937
  },
@@ -1588,10 +1960,10 @@ async function importEntrypointFile(path6, config) {
1588
1960
  }
1589
1961
  );
1590
1962
  try {
1591
- const res = await jiti(path6);
1963
+ const res = await jiti(path7);
1592
1964
  return res.default;
1593
1965
  } catch (err) {
1594
- const filePath = relative4(config.root, path6);
1966
+ const filePath = relative5(wxt.config.root, path7);
1595
1967
  if (err instanceof ReferenceError) {
1596
1968
  const variableName = err.message.replace(" is not defined", "");
1597
1969
  throw Error(
@@ -1599,7 +1971,7 @@ async function importEntrypointFile(path6, config) {
1599
1971
  { cause: err }
1600
1972
  );
1601
1973
  } else {
1602
- config.logger.error(err);
1974
+ wxt.logger.error(err);
1603
1975
  throw Error(`Failed to load entrypoint: ${filePath}`, { cause: err });
1604
1976
  }
1605
1977
  }
@@ -1614,16 +1986,16 @@ function getEsbuildOptions(opts) {
1614
1986
  }
1615
1987
 
1616
1988
  // src/core/utils/building/internal-build.ts
1617
- import pc4 from "picocolors";
1618
- import fs11 from "fs-extra";
1989
+ import pc5 from "picocolors";
1990
+ import fs12 from "fs-extra";
1619
1991
 
1620
1992
  // src/core/utils/log/printBuildSummary.ts
1621
- import { resolve as resolve9 } from "path";
1993
+ import { resolve as resolve10 } from "path";
1622
1994
 
1623
1995
  // src/core/utils/log/printFileList.ts
1624
- import path5 from "node:path";
1625
- import pc2 from "picocolors";
1626
- import fs8 from "fs-extra";
1996
+ import path6 from "node:path";
1997
+ import pc3 from "picocolors";
1998
+ import fs9 from "fs-extra";
1627
1999
  import { filesize } from "filesize";
1628
2000
 
1629
2001
  // src/core/utils/log/printTable.ts
@@ -1659,41 +2031,41 @@ async function printFileList(log, header, baseDir, files) {
1659
2031
  const fileRows = await Promise.all(
1660
2032
  files.map(async (file, i) => {
1661
2033
  const parts = [
1662
- path5.relative(process.cwd(), baseDir) + path5.sep,
1663
- path5.relative(baseDir, file)
2034
+ path6.relative(process.cwd(), baseDir) + path6.sep,
2035
+ path6.relative(baseDir, file)
1664
2036
  ];
1665
2037
  const prefix = i === files.length - 1 ? " \u2514\u2500" : " \u251C\u2500";
1666
2038
  const color = getChunkColor(file);
1667
- const stats = await fs8.lstat(file);
2039
+ const stats = await fs9.lstat(file);
1668
2040
  totalSize += stats.size;
1669
2041
  const size = String(filesize(stats.size));
1670
2042
  return [
1671
- `${pc2.gray(prefix)} ${pc2.dim(parts[0])}${color(parts[1])}`,
1672
- pc2.dim(size)
2043
+ `${pc3.gray(prefix)} ${pc3.dim(parts[0])}${color(parts[1])}`,
2044
+ pc3.dim(size)
1673
2045
  ];
1674
2046
  })
1675
2047
  );
1676
- fileRows.push([`${pc2.cyan("\u03A3 Total size:")} ${String(filesize(totalSize))}`]);
2048
+ fileRows.push([`${pc3.cyan("\u03A3 Total size:")} ${String(filesize(totalSize))}`]);
1677
2049
  printTable(log, header, fileRows);
1678
2050
  }
1679
- var DEFAULT_COLOR = pc2.blue;
2051
+ var DEFAULT_COLOR = pc3.blue;
1680
2052
  var CHUNK_COLORS = {
1681
- ".js.map": pc2.gray,
1682
- ".cjs.map": pc2.gray,
1683
- ".mjs.map": pc2.gray,
1684
- ".html": pc2.green,
1685
- ".css": pc2.magenta,
1686
- ".js": pc2.cyan,
1687
- ".cjs": pc2.cyan,
1688
- ".mjs": pc2.cyan,
1689
- ".zip": pc2.yellow
2053
+ ".js.map": pc3.gray,
2054
+ ".cjs.map": pc3.gray,
2055
+ ".mjs.map": pc3.gray,
2056
+ ".html": pc3.green,
2057
+ ".css": pc3.magenta,
2058
+ ".js": pc3.cyan,
2059
+ ".cjs": pc3.cyan,
2060
+ ".mjs": pc3.cyan,
2061
+ ".zip": pc3.yellow
1690
2062
  };
1691
2063
  function getChunkColor(filename) {
1692
2064
  return Object.entries(CHUNK_COLORS).find(([key]) => filename.endsWith(key))?.[1] ?? DEFAULT_COLOR;
1693
2065
  }
1694
2066
 
1695
2067
  // src/core/utils/log/printBuildSummary.ts
1696
- async function printBuildSummary(log, header, output, config) {
2068
+ async function printBuildSummary(log, header, output) {
1697
2069
  const chunks = [
1698
2070
  ...output.steps.flatMap((step) => step.chunks),
1699
2071
  ...output.publicAssets
@@ -1705,8 +2077,10 @@ async function printBuildSummary(log, header, output, config) {
1705
2077
  return diff;
1706
2078
  return l.fileName.localeCompare(r.fileName);
1707
2079
  });
1708
- const files = chunks.map((chunk) => resolve9(config.outDir, chunk.fileName));
1709
- await printFileList(log, header, config.outDir, files);
2080
+ const files = chunks.map(
2081
+ (chunk) => resolve10(wxt.config.outDir, chunk.fileName)
2082
+ );
2083
+ await printFileList(log, header, wxt.config.outDir, files);
1710
2084
  }
1711
2085
  var DEFAULT_SORT_WEIGHT = 100;
1712
2086
  var CHUNK_SORT_WEIGHTS = {
@@ -1723,15 +2097,15 @@ function getChunkSortWeight(filename) {
1723
2097
  }
1724
2098
 
1725
2099
  // src/core/utils/log/printHeader.ts
1726
- import pc3 from "picocolors";
2100
+ import pc4 from "picocolors";
1727
2101
  import { consola as consola2 } from "consola";
1728
2102
 
1729
2103
  // src/core/utils/building/internal-build.ts
1730
- import glob2 from "fast-glob";
2104
+ import glob3 from "fast-glob";
1731
2105
 
1732
2106
  // src/core/utils/manifest.ts
1733
- import fs10 from "fs-extra";
1734
- import { resolve as resolve11 } from "path";
2107
+ import fs11 from "fs-extra";
2108
+ import { resolve as resolve12 } from "path";
1735
2109
 
1736
2110
  // src/core/utils/content-security-policy.ts
1737
2111
  var ContentSecurityPolicy = class _ContentSecurityPolicy {
@@ -1777,8 +2151,8 @@ var ContentSecurityPolicy = class _ContentSecurityPolicy {
1777
2151
  };
1778
2152
 
1779
2153
  // src/core/utils/content-scripts.ts
1780
- function hashContentScriptOptions(options, config) {
1781
- const simplifiedOptions = mapWxtOptionsToContentScript(options, config);
2154
+ function hashContentScriptOptions(options) {
2155
+ const simplifiedOptions = mapWxtOptionsToContentScript(options);
1782
2156
  Object.keys(simplifiedOptions).forEach((key) => {
1783
2157
  if (simplifiedOptions[key] == null)
1784
2158
  delete simplifiedOptions[key];
@@ -1804,45 +2178,45 @@ function hashContentScriptOptions(options, config) {
1804
2178
  }).sort((l, r) => l[0].localeCompare(r[0]))
1805
2179
  );
1806
2180
  }
1807
- function mapWxtOptionsToContentScript(options, config) {
2181
+ function mapWxtOptionsToContentScript(options) {
1808
2182
  return {
1809
- matches: resolvePerBrowserOption(options.matches, config.browser),
1810
- all_frames: resolvePerBrowserOption(options.allFrames, config.browser),
2183
+ matches: resolvePerBrowserOption(options.matches, wxt.config.browser),
2184
+ all_frames: resolvePerBrowserOption(options.allFrames, wxt.config.browser),
1811
2185
  match_about_blank: resolvePerBrowserOption(
1812
2186
  options.matchAboutBlank,
1813
- config.browser
2187
+ wxt.config.browser
1814
2188
  ),
1815
2189
  exclude_globs: resolvePerBrowserOption(
1816
2190
  options.excludeGlobs,
1817
- config.browser
2191
+ wxt.config.browser
1818
2192
  ),
1819
2193
  exclude_matches: resolvePerBrowserOption(
1820
2194
  options.excludeMatches,
1821
- config.browser
2195
+ wxt.config.browser
1822
2196
  ),
1823
2197
  include_globs: resolvePerBrowserOption(
1824
2198
  options.includeGlobs,
1825
- config.browser
2199
+ wxt.config.browser
1826
2200
  ),
1827
- run_at: resolvePerBrowserOption(options.runAt, config.browser),
2201
+ run_at: resolvePerBrowserOption(options.runAt, wxt.config.browser),
1828
2202
  // @ts-expect-error: untyped chrome options
1829
2203
  match_origin_as_fallback: resolvePerBrowserOption(
1830
2204
  options.matchOriginAsFallback,
1831
- config.browser
2205
+ wxt.config.browser
1832
2206
  ),
1833
2207
  world: options.world
1834
2208
  };
1835
2209
  }
1836
2210
 
1837
2211
  // src/core/utils/package.ts
1838
- import { resolve as resolve10 } from "node:path";
1839
- import fs9 from "fs-extra";
1840
- async function getPackageJson(config) {
1841
- const file = resolve10(config.root, "package.json");
2212
+ import { resolve as resolve11 } from "node:path";
2213
+ import fs10 from "fs-extra";
2214
+ async function getPackageJson() {
2215
+ const file = resolve11(wxt.config.root, "package.json");
1842
2216
  try {
1843
- return await fs9.readJson(file);
2217
+ return await fs10.readJson(file);
1844
2218
  } catch (err) {
1845
- config.logger.debug(
2219
+ wxt.logger.debug(
1846
2220
  `Failed to read package.json at: ${file}. Returning undefined.`
1847
2221
  );
1848
2222
  return {};
@@ -1850,42 +2224,41 @@ async function getPackageJson(config) {
1850
2224
  }
1851
2225
 
1852
2226
  // src/core/utils/manifest.ts
1853
- import { produce } from "immer";
1854
2227
  import defu3 from "defu";
1855
- async function writeManifest(manifest, output, config) {
1856
- const str = config.mode === "production" ? JSON.stringify(manifest) : JSON.stringify(manifest, null, 2);
1857
- await fs10.ensureDir(config.outDir);
1858
- await writeFileIfDifferent(resolve11(config.outDir, "manifest.json"), str);
2228
+ async function writeManifest(manifest, output) {
2229
+ const str = wxt.config.mode === "production" ? JSON.stringify(manifest) : JSON.stringify(manifest, null, 2);
2230
+ await fs11.ensureDir(wxt.config.outDir);
2231
+ await writeFileIfDifferent(resolve12(wxt.config.outDir, "manifest.json"), str);
1859
2232
  output.publicAssets.unshift({
1860
2233
  type: "asset",
1861
2234
  fileName: "manifest.json"
1862
2235
  });
1863
2236
  }
1864
- async function generateManifest(entrypoints, buildOutput, config) {
2237
+ async function generateManifest(entrypoints, buildOutput) {
1865
2238
  const warnings = [];
1866
- const pkg = await getPackageJson(config);
1867
- let versionName = config.manifest.version_name ?? config.manifest.version ?? pkg?.version;
2239
+ const pkg = await getPackageJson();
2240
+ let versionName = wxt.config.manifest.version_name ?? wxt.config.manifest.version ?? pkg?.version;
1868
2241
  if (versionName == null) {
1869
2242
  versionName = "0.0.0";
1870
- config.logger.warn(
2243
+ wxt.logger.warn(
1871
2244
  'Extension version not found, defaulting to "0.0.0". Add a version to your `package.json` or `wxt.config.ts` file. For more details, see: https://wxt.dev/guide/manifest.html#version-and-version-name'
1872
2245
  );
1873
2246
  }
1874
- const version2 = config.manifest.version ?? simplifyVersion(versionName);
2247
+ const version2 = wxt.config.manifest.version ?? simplifyVersion(versionName);
1875
2248
  const baseManifest = {
1876
- manifest_version: config.manifestVersion,
2249
+ manifest_version: wxt.config.manifestVersion,
1877
2250
  name: pkg?.name,
1878
2251
  description: pkg?.description,
1879
2252
  version: version2,
1880
2253
  short_name: pkg?.shortName,
1881
2254
  icons: discoverIcons(buildOutput)
1882
2255
  };
1883
- const userManifest = config.manifest;
1884
- const manifest = defu3(
2256
+ const userManifest = wxt.config.manifest;
2257
+ let manifest = defu3(
1885
2258
  userManifest,
1886
2259
  baseManifest
1887
2260
  );
1888
- if (config.command === "serve" && config.dev.reloadCommand) {
2261
+ if (wxt.config.command === "serve" && wxt.config.dev.reloadCommand) {
1889
2262
  if (manifest.commands && Object.keys(manifest.commands).length >= 4) {
1890
2263
  warnings.push([
1891
2264
  "Extension already has 4 registered commands, WXT's reload command is disabled"
@@ -1895,31 +2268,37 @@ async function generateManifest(entrypoints, buildOutput, config) {
1895
2268
  manifest.commands["wxt:reload-extension"] = {
1896
2269
  description: "Reload the extension during development",
1897
2270
  suggested_key: {
1898
- default: config.dev.reloadCommand
2271
+ default: wxt.config.dev.reloadCommand
1899
2272
  }
1900
2273
  };
1901
2274
  }
1902
2275
  }
1903
2276
  manifest.version = version2;
1904
2277
  manifest.version_name = // Firefox doesn't support version_name
1905
- config.browser === "firefox" || versionName === version2 ? void 0 : versionName;
1906
- addEntrypoints(manifest, entrypoints, buildOutput, config);
1907
- if (config.command === "serve")
1908
- addDevModeCsp(manifest, config);
1909
- if (config.command === "serve")
1910
- addDevModePermissions(manifest, config);
1911
- const finalManifest = produce(manifest, config.transformManifest);
1912
- if (finalManifest.name == null)
2278
+ wxt.config.browser === "firefox" || versionName === version2 ? void 0 : versionName;
2279
+ addEntrypoints(manifest, entrypoints, buildOutput);
2280
+ if (wxt.config.command === "serve")
2281
+ addDevModeCsp(manifest);
2282
+ if (wxt.config.command === "serve")
2283
+ addDevModePermissions(manifest);
2284
+ wxt.config.transformManifest(manifest);
2285
+ await wxt.hooks.callHook("build:manifestGenerated", wxt, manifest);
2286
+ if (wxt.config.manifestVersion === 2)
2287
+ convertWebAccessibleResourcesToMv2(manifest);
2288
+ if (wxt.config.manifestVersion === 3) {
2289
+ validateMv3WebAccessbileResources(manifest);
2290
+ }
2291
+ if (manifest.name == null)
1913
2292
  throw Error(
1914
2293
  "Manifest 'name' is missing. Either:\n1. Set the name in your <rootDir>/package.json\n2. Set a name via the manifest option in your wxt.config.ts"
1915
2294
  );
1916
- if (finalManifest.version == null) {
2295
+ if (manifest.version == null) {
1917
2296
  throw Error(
1918
2297
  "Manifest 'version' is missing. Either:\n1. Add a version in your <rootDir>/package.json\n2. Pass the version via the manifest option in your wxt.config.ts"
1919
2298
  );
1920
2299
  }
1921
2300
  return {
1922
- manifest: finalManifest,
2301
+ manifest,
1923
2302
  warnings
1924
2303
  };
1925
2304
  }
@@ -1933,7 +2312,7 @@ function simplifyVersion(versionName) {
1933
2312
  );
1934
2313
  return version2;
1935
2314
  }
1936
- function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2315
+ function addEntrypoints(manifest, entrypoints, buildOutput) {
1937
2316
  const entriesByType = entrypoints.reduce((map, entrypoint) => {
1938
2317
  map[entrypoint.type] ??= [];
1939
2318
  map[entrypoint.type]?.push(entrypoint);
@@ -1950,13 +2329,17 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
1950
2329
  const sandboxes = entriesByType["sandbox"];
1951
2330
  const sidepanels = entriesByType["sidepanel"];
1952
2331
  if (background) {
1953
- const script = getEntrypointBundlePath(background, config.outDir, ".js");
1954
- if (config.browser === "firefox" && config.manifestVersion === 3) {
2332
+ const script = getEntrypointBundlePath(
2333
+ background,
2334
+ wxt.config.outDir,
2335
+ ".js"
2336
+ );
2337
+ if (wxt.config.browser === "firefox" && wxt.config.manifestVersion === 3) {
1955
2338
  manifest.background = {
1956
2339
  type: background.options.type,
1957
2340
  scripts: [script]
1958
2341
  };
1959
- } else if (config.manifestVersion === 3) {
2342
+ } else if (wxt.config.manifestVersion === 3) {
1960
2343
  manifest.background = {
1961
2344
  type: background.options.type,
1962
2345
  service_worker: script
@@ -1969,29 +2352,29 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
1969
2352
  }
1970
2353
  }
1971
2354
  if (bookmarks) {
1972
- if (config.browser === "firefox") {
1973
- config.logger.warn(
2355
+ if (wxt.config.browser === "firefox") {
2356
+ wxt.logger.warn(
1974
2357
  "Bookmarks are not supported by Firefox. chrome_url_overrides.bookmarks was not added to the manifest"
1975
2358
  );
1976
2359
  } else {
1977
2360
  manifest.chrome_url_overrides ??= {};
1978
2361
  manifest.chrome_url_overrides.bookmarks = getEntrypointBundlePath(
1979
2362
  bookmarks,
1980
- config.outDir,
2363
+ wxt.config.outDir,
1981
2364
  ".html"
1982
2365
  );
1983
2366
  }
1984
2367
  }
1985
2368
  if (history) {
1986
- if (config.browser === "firefox") {
1987
- config.logger.warn(
2369
+ if (wxt.config.browser === "firefox") {
2370
+ wxt.logger.warn(
1988
2371
  "Bookmarks are not supported by Firefox. chrome_url_overrides.history was not added to the manifest"
1989
2372
  );
1990
2373
  } else {
1991
2374
  manifest.chrome_url_overrides ??= {};
1992
2375
  manifest.chrome_url_overrides.history = getEntrypointBundlePath(
1993
2376
  history,
1994
- config.outDir,
2377
+ wxt.config.outDir,
1995
2378
  ".html"
1996
2379
  );
1997
2380
  }
@@ -2000,14 +2383,14 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2000
2383
  manifest.chrome_url_overrides ??= {};
2001
2384
  manifest.chrome_url_overrides.newtab = getEntrypointBundlePath(
2002
2385
  newtab,
2003
- config.outDir,
2386
+ wxt.config.outDir,
2004
2387
  ".html"
2005
2388
  );
2006
2389
  }
2007
2390
  if (popup) {
2008
2391
  const default_popup = getEntrypointBundlePath(
2009
2392
  popup,
2010
- config.outDir,
2393
+ wxt.config.outDir,
2011
2394
  ".html"
2012
2395
  );
2013
2396
  const options2 = {};
@@ -2035,28 +2418,28 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2035
2418
  if (devtools) {
2036
2419
  manifest.devtools_page = getEntrypointBundlePath(
2037
2420
  devtools,
2038
- config.outDir,
2421
+ wxt.config.outDir,
2039
2422
  ".html"
2040
2423
  );
2041
2424
  }
2042
2425
  if (options) {
2043
- const page = getEntrypointBundlePath(options, config.outDir, ".html");
2426
+ const page = getEntrypointBundlePath(options, wxt.config.outDir, ".html");
2044
2427
  manifest.options_ui = {
2045
2428
  open_in_tab: options.options.openInTab,
2046
- browser_style: config.browser === "firefox" ? options.options.browserStyle : void 0,
2047
- chrome_style: config.browser !== "firefox" ? options.options.chromeStyle : void 0,
2429
+ browser_style: wxt.config.browser === "firefox" ? options.options.browserStyle : void 0,
2430
+ chrome_style: wxt.config.browser !== "firefox" ? options.options.chromeStyle : void 0,
2048
2431
  page
2049
2432
  };
2050
2433
  }
2051
2434
  if (sandboxes?.length) {
2052
- if (config.browser === "firefox") {
2053
- config.logger.warn(
2435
+ if (wxt.config.browser === "firefox") {
2436
+ wxt.logger.warn(
2054
2437
  "Sandboxed pages not supported by Firefox. sandbox.pages was not added to the manifest"
2055
2438
  );
2056
2439
  } else {
2057
2440
  manifest.sandbox = {
2058
2441
  pages: sandboxes.map(
2059
- (entry) => getEntrypointBundlePath(entry, config.outDir, ".html")
2442
+ (entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".html")
2060
2443
  )
2061
2444
  };
2062
2445
  }
@@ -2065,33 +2448,33 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2065
2448
  const defaultSidepanel = sidepanels.find((entry) => entry.name === "sidepanel") ?? sidepanels[0];
2066
2449
  const page = getEntrypointBundlePath(
2067
2450
  defaultSidepanel,
2068
- config.outDir,
2451
+ wxt.config.outDir,
2069
2452
  ".html"
2070
2453
  );
2071
- if (config.browser === "firefox") {
2454
+ if (wxt.config.browser === "firefox") {
2072
2455
  manifest.sidebar_action = {
2073
2456
  // TODO: Add options to side panel
2074
2457
  // ...defaultSidepanel.options,
2075
2458
  default_panel: page
2076
2459
  };
2077
- } else if (config.manifestVersion === 3) {
2460
+ } else if (wxt.config.manifestVersion === 3) {
2078
2461
  manifest.side_panel = {
2079
2462
  default_path: page
2080
2463
  };
2081
2464
  } else {
2082
- config.logger.warn(
2465
+ wxt.logger.warn(
2083
2466
  "Side panel not supported by Chromium using MV2. side_panel.default_path was not added to the manifest"
2084
2467
  );
2085
2468
  }
2086
2469
  }
2087
2470
  if (contentScripts?.length) {
2088
2471
  const cssMap = getContentScriptsCssMap(buildOutput, contentScripts);
2089
- if (config.command === "serve" && config.manifestVersion === 3) {
2472
+ if (wxt.config.command === "serve" && wxt.config.manifestVersion === 3) {
2090
2473
  const hostPermissions = new Set(manifest.host_permissions ?? []);
2091
2474
  contentScripts.forEach((script) => {
2092
2475
  const matches = resolvePerBrowserOption(
2093
2476
  script.options.matches,
2094
- config.browser
2477
+ wxt.config.browser
2095
2478
  );
2096
2479
  matches.forEach((matchPattern) => {
2097
2480
  hostPermissions.add(matchPattern);
@@ -2102,7 +2485,7 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2102
2485
  );
2103
2486
  } else {
2104
2487
  const hashToEntrypointsMap = contentScripts.reduce((map, script) => {
2105
- const hash = hashContentScriptOptions(script.options, config);
2488
+ const hash = hashContentScriptOptions(script.options);
2106
2489
  if (map.has(hash))
2107
2490
  map.get(hash)?.push(script);
2108
2491
  else
@@ -2111,10 +2494,10 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2111
2494
  }, /* @__PURE__ */ new Map());
2112
2495
  const newContentScripts = Array.from(hashToEntrypointsMap.entries()).map(
2113
2496
  ([, scripts]) => ({
2114
- ...mapWxtOptionsToContentScript(scripts[0].options, config),
2497
+ ...mapWxtOptionsToContentScript(scripts[0].options),
2115
2498
  css: getContentScriptCssFiles(scripts, cssMap),
2116
2499
  js: scripts.map(
2117
- (entry) => getEntrypointBundlePath(entry, config.outDir, ".js")
2500
+ (entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".js")
2118
2501
  )
2119
2502
  })
2120
2503
  );
@@ -2124,7 +2507,6 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2124
2507
  }
2125
2508
  }
2126
2509
  const contentScriptCssResources = getContentScriptCssWebAccessibleResources(
2127
- config,
2128
2510
  contentScripts,
2129
2511
  cssMap
2130
2512
  );
@@ -2167,9 +2549,9 @@ function discoverIcons(buildOutput) {
2167
2549
  });
2168
2550
  return icons.length > 0 ? Object.fromEntries(icons) : void 0;
2169
2551
  }
2170
- function addDevModeCsp(manifest, config) {
2171
- const permission = `http://${config.server?.hostname ?? ""}/*`;
2172
- const allowedCsp = config.server?.origin ?? "http://localhost:*";
2552
+ function addDevModeCsp(manifest) {
2553
+ const permission = `http://${wxt.config.server?.hostname ?? ""}/*`;
2554
+ const allowedCsp = wxt.config.server?.origin ?? "http://localhost:*";
2173
2555
  if (manifest.manifest_version === 3) {
2174
2556
  addHostPermission(manifest, permission);
2175
2557
  } else {
@@ -2182,7 +2564,7 @@ function addDevModeCsp(manifest, config) {
2182
2564
  ) : manifest.content_security_policy ?? "script-src 'self'; object-src 'self';"
2183
2565
  // default CSP for MV2
2184
2566
  );
2185
- if (config.server)
2567
+ if (wxt.config.server)
2186
2568
  csp.add("script-src", allowedCsp);
2187
2569
  if (manifest.manifest_version === 3) {
2188
2570
  manifest.content_security_policy ??= {};
@@ -2191,9 +2573,9 @@ function addDevModeCsp(manifest, config) {
2191
2573
  manifest.content_security_policy = csp.toString();
2192
2574
  }
2193
2575
  }
2194
- function addDevModePermissions(manifest, config) {
2576
+ function addDevModePermissions(manifest) {
2195
2577
  addPermission(manifest, "tabs");
2196
- if (config.manifestVersion === 3)
2578
+ if (wxt.config.manifestVersion === 3)
2197
2579
  addPermission(manifest, "scripting");
2198
2580
  }
2199
2581
  function getContentScriptCssFiles(contentScripts, contentScriptCssMap) {
@@ -2211,7 +2593,7 @@ function getContentScriptCssFiles(contentScripts, contentScriptCssMap) {
2211
2593
  return css;
2212
2594
  return void 0;
2213
2595
  }
2214
- function getContentScriptCssWebAccessibleResources(config, contentScripts, contentScriptCssMap) {
2596
+ function getContentScriptCssWebAccessibleResources(contentScripts, contentScriptCssMap) {
2215
2597
  const resources = [];
2216
2598
  contentScripts.forEach((script) => {
2217
2599
  if (script.options.cssInjectionMode !== "ui")
@@ -2219,17 +2601,13 @@ function getContentScriptCssWebAccessibleResources(config, contentScripts, conte
2219
2601
  const cssFile = contentScriptCssMap[script.name];
2220
2602
  if (cssFile == null)
2221
2603
  return;
2222
- if (config.manifestVersion === 2) {
2223
- resources.push(cssFile);
2224
- } else {
2225
- resources.push({
2226
- resources: [cssFile],
2227
- matches: resolvePerBrowserOption(
2228
- script.options.matches,
2229
- config.browser
2230
- ).map((matchPattern) => stripPathFromMatchPattern(matchPattern))
2231
- });
2232
- }
2604
+ resources.push({
2605
+ resources: [cssFile],
2606
+ matches: resolvePerBrowserOption(
2607
+ script.options.matches,
2608
+ wxt.config.browser
2609
+ ).map((matchPattern) => stripPathFromMatchPattern(matchPattern))
2610
+ });
2233
2611
  });
2234
2612
  return resources;
2235
2613
  }
@@ -2264,30 +2642,57 @@ function stripPathFromMatchPattern(pattern) {
2264
2642
  const startOfPath = pattern.indexOf("/", protocolSepIndex + 3);
2265
2643
  return pattern.substring(0, startOfPath) + "/*";
2266
2644
  }
2645
+ function convertWebAccessibleResourcesToMv2(manifest) {
2646
+ if (manifest.web_accessible_resources == null)
2647
+ return;
2648
+ manifest.web_accessible_resources = Array.from(
2649
+ new Set(
2650
+ manifest.web_accessible_resources.flatMap((item) => {
2651
+ if (typeof item === "string")
2652
+ return item;
2653
+ return item.resources;
2654
+ })
2655
+ )
2656
+ );
2657
+ }
2658
+ function validateMv3WebAccessbileResources(manifest) {
2659
+ if (manifest.web_accessible_resources == null)
2660
+ return;
2661
+ const stringResources = manifest.web_accessible_resources.filter(
2662
+ (item) => typeof item === "string"
2663
+ );
2664
+ if (stringResources.length > 0) {
2665
+ throw Error(
2666
+ `Non-MV3 web_accessible_resources detected: ${JSON.stringify(
2667
+ stringResources
2668
+ )}. When manually defining web_accessible_resources, define them as MV3 objects ({ matches: [...], resources: [...] }), and WXT will automatically convert them to MV2 when necessary.`
2669
+ );
2670
+ }
2671
+ }
2267
2672
 
2268
2673
  // src/core/utils/building/rebuild.ts
2269
- async function rebuild(config, allEntrypoints, entrypointGroups, existingOutput = {
2674
+ async function rebuild(allEntrypoints, entrypointGroups, existingOutput = {
2270
2675
  steps: [],
2271
2676
  publicAssets: []
2272
2677
  }) {
2273
2678
  const { default: ora } = await import("ora");
2274
2679
  const spinner = ora(`Preparing...`).start();
2275
- await generateTypesDir(allEntrypoints, config).catch((err) => {
2276
- config.logger.warn("Failed to update .wxt directory:", err);
2277
- if (config.command === "build")
2680
+ await generateTypesDir(allEntrypoints).catch((err) => {
2681
+ wxt.logger.warn("Failed to update .wxt directory:", err);
2682
+ if (wxt.config.command === "build")
2278
2683
  throw err;
2279
2684
  });
2280
- const newOutput = await buildEntrypoints(entrypointGroups, config, spinner);
2685
+ const newOutput = await buildEntrypoints(entrypointGroups, spinner);
2281
2686
  const mergedOutput = {
2282
2687
  steps: [...existingOutput.steps, ...newOutput.steps],
2283
2688
  publicAssets: [...existingOutput.publicAssets, ...newOutput.publicAssets]
2284
2689
  };
2285
- const { manifest: newManifest, warnings: manifestWarnings } = await generateManifest(allEntrypoints, mergedOutput, config);
2690
+ const { manifest: newManifest, warnings: manifestWarnings } = await generateManifest(allEntrypoints, mergedOutput);
2286
2691
  const finalOutput = {
2287
2692
  manifest: newManifest,
2288
2693
  ...newOutput
2289
2694
  };
2290
- await writeManifest(newManifest, finalOutput, config);
2695
+ await writeManifest(newManifest, finalOutput);
2291
2696
  spinner.clear().stop();
2292
2697
  return {
2293
2698
  output: {
@@ -2304,7 +2709,7 @@ async function rebuild(config, allEntrypoints, entrypointGroups, existingOutput
2304
2709
  }
2305
2710
 
2306
2711
  // src/core/utils/building/internal-build.ts
2307
- import { relative as relative5 } from "node:path";
2712
+ import { relative as relative6 } from "node:path";
2308
2713
 
2309
2714
  // src/core/utils/validation.ts
2310
2715
  function validateEntrypoints(entrypoints) {
@@ -2370,32 +2775,35 @@ import consola3 from "consola";
2370
2775
 
2371
2776
  // src/core/utils/exec.ts
2372
2777
  import managePath from "manage-path";
2373
- import { resolve as resolve12 } from "node:path";
2778
+ import { resolve as resolve13 } from "node:path";
2374
2779
  var managedPath = managePath(process.env);
2375
- var exec = async (config, file, args, options) => {
2780
+ var exec = async (file, args, options) => {
2376
2781
  managedPath.restore();
2377
- managedPath.push(resolve12(config.root, "node_modules/wxt/node_modules/.bin"));
2782
+ managedPath.push(
2783
+ resolve13(wxt.config.root, "node_modules/wxt/node_modules/.bin")
2784
+ );
2378
2785
  const { execa } = await import("./execa-4F7CCWCA.js");
2379
2786
  return await execa(file, args, options);
2380
2787
  };
2381
2788
 
2382
2789
  // src/core/utils/building/internal-build.ts
2383
- async function internalBuild(config) {
2384
- const verb = config.command === "serve" ? "Pre-rendering" : "Building";
2385
- const target = `${config.browser}-mv${config.manifestVersion}`;
2386
- config.logger.info(
2387
- `${verb} ${pc4.cyan(target)} for ${pc4.cyan(config.mode)} with ${pc4.green(
2388
- `${config.builder.name} ${config.builder.version}`
2790
+ async function internalBuild() {
2791
+ await wxt.hooks.callHook("build:before", wxt);
2792
+ const verb = wxt.config.command === "serve" ? "Pre-rendering" : "Building";
2793
+ const target = `${wxt.config.browser}-mv${wxt.config.manifestVersion}`;
2794
+ wxt.logger.info(
2795
+ `${verb} ${pc5.cyan(target)} for ${pc5.cyan(wxt.config.mode)} with ${pc5.green(
2796
+ `${wxt.config.builder.name} ${wxt.config.builder.version}`
2389
2797
  )}`
2390
2798
  );
2391
2799
  const startTime = Date.now();
2392
- await fs11.rm(config.outDir, { recursive: true, force: true });
2393
- await fs11.ensureDir(config.outDir);
2394
- const entrypoints = await findEntrypoints(config);
2395
- config.logger.debug("Detected entrypoints:", entrypoints);
2800
+ await fs12.rm(wxt.config.outDir, { recursive: true, force: true });
2801
+ await fs12.ensureDir(wxt.config.outDir);
2802
+ const entrypoints = await findEntrypoints();
2803
+ wxt.logger.debug("Detected entrypoints:", entrypoints);
2396
2804
  const validationResults = validateEntrypoints(entrypoints);
2397
2805
  if (validationResults.errorCount + validationResults.warningCount > 0) {
2398
- printValidationResults(config, validationResults);
2806
+ printValidationResults(validationResults);
2399
2807
  }
2400
2808
  if (validationResults.errorCount > 0) {
2401
2809
  throw new ValidationError(`Entrypoint validation failed`, {
@@ -2403,45 +2811,52 @@ async function internalBuild(config) {
2403
2811
  });
2404
2812
  }
2405
2813
  const groups = groupEntrypoints(entrypoints);
2406
- const { output, warnings } = await rebuild(
2407
- config,
2408
- entrypoints,
2409
- groups,
2410
- void 0
2411
- );
2814
+ await wxt.hooks.callHook("entrypoints:grouped", wxt, groups);
2815
+ const { output, warnings } = await rebuild(entrypoints, groups, void 0);
2816
+ await wxt.hooks.callHook("build:done", wxt, output);
2412
2817
  await printBuildSummary(
2413
- config.logger.success,
2818
+ wxt.logger.success,
2414
2819
  `Built extension in ${formatDuration(Date.now() - startTime)}`,
2415
- output,
2416
- config
2820
+ output
2417
2821
  );
2418
2822
  for (const warning of warnings) {
2419
- config.logger.warn(...warning);
2823
+ wxt.logger.warn(...warning);
2420
2824
  }
2421
- if (config.analysis.enabled) {
2422
- await combineAnalysisStats(config);
2423
- config.logger.info(
2825
+ if (wxt.config.analysis.enabled) {
2826
+ await combineAnalysisStats();
2827
+ const statsPath = relative6(wxt.config.root, wxt.config.analysis.outputFile);
2828
+ wxt.logger.info(
2424
2829
  `Analysis complete:
2425
- ${pc4.gray("\u2514\u2500")} ${pc4.yellow("stats.html")}`
2830
+ ${pc5.gray("\u2514\u2500")} ${pc5.yellow(statsPath)}`
2426
2831
  );
2427
2832
  }
2428
2833
  return output;
2429
2834
  }
2430
- async function combineAnalysisStats(config) {
2431
- const unixFiles = await glob2(`stats-*.json`, {
2432
- cwd: config.outDir,
2835
+ async function combineAnalysisStats() {
2836
+ const unixFiles = await glob3(`stats-*.json`, {
2837
+ cwd: wxt.config.outDir,
2433
2838
  absolute: true
2434
2839
  });
2435
2840
  const absolutePaths = unixFiles.map(unnormalizePath);
2436
2841
  await exec(
2437
- config,
2438
2842
  "rollup-plugin-visualizer",
2439
- [...absolutePaths, "--template", config.analysis.template],
2440
- { cwd: config.root, stdio: "inherit" }
2843
+ [
2844
+ ...absolutePaths,
2845
+ "--template",
2846
+ wxt.config.analysis.template,
2847
+ "--filename",
2848
+ wxt.config.analysis.outputFile
2849
+ ],
2850
+ { cwd: wxt.config.root, stdio: "inherit" }
2441
2851
  );
2852
+ await Promise.all(absolutePaths.map((statsFile) => fs12.remove(statsFile)));
2442
2853
  }
2443
- function printValidationResults(config, { errorCount, errors, warningCount }) {
2444
- (errorCount > 0 ? config.logger.error : config.logger.warn)(
2854
+ function printValidationResults({
2855
+ errorCount,
2856
+ errors,
2857
+ warningCount
2858
+ }) {
2859
+ (errorCount > 0 ? wxt.logger.error : wxt.logger.warn)(
2445
2860
  `Entrypoint validation failed: ${errorCount} error${errorCount === 1 ? "" : "s"}, ${warningCount} warning${warningCount === 1 ? "" : "s"}`
2446
2861
  );
2447
2862
  const cwd = process.cwd();
@@ -2452,355 +2867,40 @@ function printValidationResults(config, { errorCount, errors, warningCount }) {
2452
2867
  return map;
2453
2868
  }, /* @__PURE__ */ new Map());
2454
2869
  Array.from(entrypointErrors.entries()).forEach(([entrypoint, errors2]) => {
2455
- consola3.log(relative5(cwd, entrypoint.inputPath));
2870
+ consola3.log(relative6(cwd, entrypoint.inputPath));
2456
2871
  console.log();
2457
2872
  errors2.forEach((err) => {
2458
- const type = err.type === "error" ? pc4.red("ERROR") : pc4.yellow("WARN");
2459
- const recieved = pc4.dim(`(recieved: ${JSON.stringify(err.value)})`);
2873
+ const type = err.type === "error" ? pc5.red("ERROR") : pc5.yellow("WARN");
2874
+ const recieved = pc5.dim(`(recieved: ${JSON.stringify(err.value)})`);
2460
2875
  consola3.log(` - ${type} ${err.message} ${recieved}`);
2461
2876
  });
2462
2877
  console.log();
2463
2878
  });
2464
2879
  }
2465
2880
 
2466
- // src/core/utils/building/find-entrypoints.ts
2467
- import glob3 from "fast-glob";
2468
- import pc5 from "picocolors";
2469
- async function findEntrypoints(config) {
2470
- const relativePaths = await glob3(Object.keys(PATH_GLOB_TO_TYPE_MAP), {
2471
- cwd: config.entrypointsDir
2472
- });
2473
- relativePaths.sort();
2474
- const pathGlobs = Object.keys(PATH_GLOB_TO_TYPE_MAP);
2475
- const entrypointInfos = relativePaths.reduce((results, relativePath) => {
2476
- const inputPath = resolve13(config.entrypointsDir, relativePath);
2477
- const name = getEntrypointName(config.entrypointsDir, inputPath);
2478
- const matchingGlob = pathGlobs.find(
2479
- (glob4) => minimatch(relativePath, glob4)
2480
- );
2481
- if (matchingGlob) {
2482
- const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
2483
- results.push({
2484
- name,
2485
- inputPath,
2486
- type,
2487
- skipped: config.filterEntrypoints != null && !config.filterEntrypoints.has(name)
2488
- });
2489
- }
2490
- return results;
2491
- }, []);
2492
- preventNoEntrypoints(config, entrypointInfos);
2493
- preventDuplicateEntrypointNames(config, entrypointInfos);
2494
- let hasBackground = false;
2495
- const entrypoints = await Promise.all(
2496
- entrypointInfos.map(async (info) => {
2497
- const { type } = info;
2498
- switch (type) {
2499
- case "popup":
2500
- return await getPopupEntrypoint(config, info);
2501
- case "options":
2502
- return await getOptionsEntrypoint(config, info);
2503
- case "background":
2504
- hasBackground = true;
2505
- return await getBackgroundEntrypoint(config, info);
2506
- case "content-script":
2507
- return await getContentScriptEntrypoint(config, info);
2508
- case "unlisted-page":
2509
- return await getUnlistedPageEntrypoint(config, info);
2510
- case "unlisted-script":
2511
- return await getUnlistedScriptEntrypoint(config, info);
2512
- case "content-script-style":
2513
- return {
2514
- ...info,
2515
- type,
2516
- outputDir: resolve13(config.outDir, CONTENT_SCRIPT_OUT_DIR),
2517
- options: {
2518
- include: void 0,
2519
- exclude: void 0
2520
- }
2521
- };
2522
- default:
2523
- return {
2524
- ...info,
2525
- type,
2526
- outputDir: config.outDir,
2527
- options: {
2528
- include: void 0,
2529
- exclude: void 0
2530
- }
2531
- };
2532
- }
2533
- })
2534
- );
2535
- if (config.command === "serve" && !hasBackground) {
2536
- entrypoints.push(
2537
- await getBackgroundEntrypoint(config, {
2538
- inputPath: VIRTUAL_NOOP_BACKGROUND_MODULE_ID,
2539
- name: "background",
2540
- type: "background",
2541
- skipped: false
2542
- })
2543
- );
2544
- }
2545
- config.logger.debug("All entrypoints:", entrypoints);
2546
- const skippedEntrypointNames = entrypointInfos.filter((item) => item.skipped).map((item) => item.name);
2547
- if (skippedEntrypointNames.length) {
2548
- config.logger.warn(
2549
- `Filter excluded the following entrypoints:
2550
- ${skippedEntrypointNames.map((item) => `${pc5.dim("-")} ${pc5.cyan(item)}`).join("\n")}`
2551
- );
2552
- }
2553
- const targetEntrypoints = entrypoints.filter((entry) => {
2554
- const { include, exclude } = entry.options;
2555
- if (include?.length && exclude?.length) {
2556
- config.logger.warn(
2557
- `The ${entry.name} entrypoint lists both include and exclude, but only one can be used per entrypoint. Entrypoint ignored.`
2558
- );
2559
- return false;
2560
- }
2561
- if (exclude?.length && !include?.length) {
2562
- return !exclude.includes(config.browser);
2563
- }
2564
- if (include?.length && !exclude?.length) {
2565
- return include.includes(config.browser);
2566
- }
2567
- if (skippedEntrypointNames.includes(entry.name)) {
2568
- return false;
2569
- }
2570
- return true;
2571
- });
2572
- config.logger.debug(`${config.browser} entrypoints:`, targetEntrypoints);
2573
- return targetEntrypoints;
2574
- }
2575
- function preventDuplicateEntrypointNames(config, files) {
2576
- const namesToPaths = files.reduce(
2577
- (map, { name, inputPath }) => {
2578
- map[name] ??= [];
2579
- map[name].push(inputPath);
2580
- return map;
2581
- },
2582
- {}
2583
- );
2584
- const errorLines = Object.entries(namesToPaths).reduce(
2585
- (lines, [name, absolutePaths]) => {
2586
- if (absolutePaths.length > 1) {
2587
- lines.push(`- ${name}`);
2588
- absolutePaths.forEach((absolutePath) => {
2589
- lines.push(` - ${relative6(config.root, absolutePath)}`);
2590
- });
2591
- }
2592
- return lines;
2881
+ // src/core/wxt.ts
2882
+ import { createHooks } from "hookable";
2883
+ var wxt;
2884
+ async function registerWxt(command, inlineConfig = {}, server) {
2885
+ const config = await resolveConfig(inlineConfig, command, server);
2886
+ const hooks = createHooks();
2887
+ wxt = {
2888
+ config,
2889
+ hooks,
2890
+ get logger() {
2891
+ return config.logger;
2593
2892
  },
2594
- []
2595
- );
2596
- if (errorLines.length > 0) {
2597
- const errorContent = errorLines.join("\n");
2598
- throw Error(
2599
- `Multiple entrypoints with the same name detected, only one entrypoint for each name is allowed.
2600
-
2601
- ${errorContent}`
2602
- );
2603
- }
2604
- }
2605
- function preventNoEntrypoints(config, files) {
2606
- if (files.length === 0) {
2607
- throw Error(`No entrypoints found in ${config.entrypointsDir}`);
2608
- }
2609
- }
2610
- function getHtmlBaseOptions(document) {
2611
- const options = {};
2612
- const includeContent = document.querySelector("meta[name='manifest.include']")?.getAttribute("content");
2613
- if (includeContent) {
2614
- options.include = JSON5.parse(includeContent);
2615
- }
2616
- const excludeContent = document.querySelector("meta[name='manifest.exclude']")?.getAttribute("content");
2617
- if (excludeContent) {
2618
- options.exclude = JSON5.parse(excludeContent);
2619
- }
2620
- return options;
2621
- }
2622
- async function getPopupEntrypoint(config, { inputPath, name, skipped }) {
2623
- const content = await fs12.readFile(inputPath, "utf-8");
2624
- const { document } = parseHTML2(content);
2625
- const options = getHtmlBaseOptions(document);
2626
- const title = document.querySelector("title");
2627
- if (title != null)
2628
- options.defaultTitle = title.textContent ?? void 0;
2629
- const defaultIconContent = document.querySelector("meta[name='manifest.default_icon']")?.getAttribute("content");
2630
- if (defaultIconContent) {
2631
- try {
2632
- options.defaultIcon = JSON5.parse(defaultIconContent);
2633
- } catch (err) {
2634
- config.logger.fatal(
2635
- `Failed to parse default_icon meta tag content as JSON5. content=${defaultIconContent}`,
2636
- err
2637
- );
2638
- }
2639
- }
2640
- const mv2TypeContent = document.querySelector("meta[name='manifest.type']")?.getAttribute("content");
2641
- if (mv2TypeContent) {
2642
- options.mv2Key = mv2TypeContent === "page_action" ? "page_action" : "browser_action";
2643
- }
2644
- const browserStyleContent = document.querySelector("meta[name='manifest.browser_style']")?.getAttribute("content");
2645
- if (browserStyleContent) {
2646
- options.browserStyle = browserStyleContent === "true";
2647
- }
2648
- return {
2649
- type: "popup",
2650
- name: "popup",
2651
- options,
2652
- inputPath,
2653
- outputDir: config.outDir,
2654
- skipped
2655
- };
2656
- }
2657
- async function getOptionsEntrypoint(config, { inputPath, name, skipped }) {
2658
- const content = await fs12.readFile(inputPath, "utf-8");
2659
- const { document } = parseHTML2(content);
2660
- const options = getHtmlBaseOptions(document);
2661
- const openInTabContent = document.querySelector("meta[name='manifest.open_in_tab']")?.getAttribute("content");
2662
- if (openInTabContent) {
2663
- options.openInTab = openInTabContent === "true";
2664
- }
2665
- const chromeStyleContent = document.querySelector("meta[name='manifest.chrome_style']")?.getAttribute("content");
2666
- if (chromeStyleContent) {
2667
- options.chromeStyle = chromeStyleContent === "true";
2668
- }
2669
- const browserStyleContent = document.querySelector("meta[name='manifest.browser_style']")?.getAttribute("content");
2670
- if (browserStyleContent) {
2671
- options.browserStyle = browserStyleContent === "true";
2672
- }
2673
- return {
2674
- type: "options",
2675
- name: "options",
2676
- options,
2677
- inputPath,
2678
- outputDir: config.outDir,
2679
- skipped
2680
- };
2681
- }
2682
- async function getUnlistedPageEntrypoint(config, { inputPath, name, skipped }) {
2683
- const content = await fs12.readFile(inputPath, "utf-8");
2684
- const { document } = parseHTML2(content);
2685
- return {
2686
- type: "unlisted-page",
2687
- name: getEntrypointName(config.entrypointsDir, inputPath),
2688
- inputPath,
2689
- outputDir: config.outDir,
2690
- options: getHtmlBaseOptions(document),
2691
- skipped
2692
- };
2693
- }
2694
- async function getUnlistedScriptEntrypoint(config, { inputPath, name, skipped }) {
2695
- const defaultExport = await importEntrypointFile(
2696
- inputPath,
2697
- config
2698
- );
2699
- if (defaultExport == null) {
2700
- throw Error(
2701
- `${name}: Default export not found, did you forget to call "export default defineUnlistedScript(...)"?`
2702
- );
2703
- }
2704
- const { main: _, ...moduleOptions } = defaultExport;
2705
- const options = moduleOptions;
2706
- return {
2707
- type: "unlisted-script",
2708
- name,
2709
- inputPath,
2710
- outputDir: config.outDir,
2711
- options,
2712
- skipped
2713
- };
2714
- }
2715
- async function getBackgroundEntrypoint(config, { inputPath, name, skipped }) {
2716
- let options = {};
2717
- if (inputPath !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
2718
- const defaultExport = await importEntrypointFile(
2719
- inputPath,
2720
- config
2721
- );
2722
- if (defaultExport == null) {
2723
- throw Error(
2724
- `${name}: Default export not found, did you forget to call "export default defineBackground(...)"?`
2725
- );
2893
+ async reloadConfig() {
2894
+ wxt.config = await resolveConfig(inlineConfig, command, server);
2726
2895
  }
2727
- const { main: _, ...moduleOptions } = defaultExport;
2728
- options = moduleOptions;
2729
- }
2730
- if (config.manifestVersion !== 3) {
2731
- delete options.type;
2732
- }
2733
- return {
2734
- type: "background",
2735
- name,
2736
- inputPath,
2737
- outputDir: config.outDir,
2738
- options: {
2739
- ...options,
2740
- type: resolvePerBrowserOption(options.type, config.browser),
2741
- persistent: resolvePerBrowserOption(options.persistent, config.browser)
2742
- },
2743
- skipped
2744
2896
  };
2897
+ wxt.hooks.addHooks(config.hooks);
2898
+ await wxt.hooks.callHook("ready", wxt);
2745
2899
  }
2746
- async function getContentScriptEntrypoint(config, { inputPath, name, skipped }) {
2747
- const { main: _, ...options } = await importEntrypointFile(inputPath, config);
2748
- if (options == null) {
2749
- throw Error(
2750
- `${name}: Default export not found, did you forget to call "export default defineContentScript(...)"?`
2751
- );
2752
- }
2753
- return {
2754
- type: "content-script",
2755
- name,
2756
- inputPath,
2757
- outputDir: resolve13(config.outDir, CONTENT_SCRIPT_OUT_DIR),
2758
- options,
2759
- skipped
2760
- };
2761
- }
2762
- var PATH_GLOB_TO_TYPE_MAP = {
2763
- "sandbox.html": "sandbox",
2764
- "sandbox/index.html": "sandbox",
2765
- "*.sandbox.html": "sandbox",
2766
- "*.sandbox/index.html": "sandbox",
2767
- "bookmarks.html": "bookmarks",
2768
- "bookmarks/index.html": "bookmarks",
2769
- "history.html": "history",
2770
- "history/index.html": "history",
2771
- "newtab.html": "newtab",
2772
- "newtab/index.html": "newtab",
2773
- "sidepanel.html": "sidepanel",
2774
- "sidepanel/index.html": "sidepanel",
2775
- "*.sidepanel.html": "sidepanel",
2776
- "*.sidepanel/index.html": "sidepanel",
2777
- "devtools.html": "devtools",
2778
- "devtools/index.html": "devtools",
2779
- "background.[jt]s": "background",
2780
- "background/index.[jt]s": "background",
2781
- [VIRTUAL_NOOP_BACKGROUND_MODULE_ID]: "background",
2782
- "content.[jt]s?(x)": "content-script",
2783
- "content/index.[jt]s?(x)": "content-script",
2784
- "*.content.[jt]s?(x)": "content-script",
2785
- "*.content/index.[jt]s?(x)": "content-script",
2786
- [`content.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
2787
- [`*.content.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
2788
- [`content/index.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
2789
- [`*.content/index.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
2790
- "popup.html": "popup",
2791
- "popup/index.html": "popup",
2792
- "options.html": "options",
2793
- "options/index.html": "options",
2794
- "*.html": "unlisted-page",
2795
- "*/index.html": "unlisted-page",
2796
- "*.[jt]s?(x)": "unlisted-script",
2797
- "*/index.[jt]s?(x)": "unlisted-script",
2798
- [`*.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style",
2799
- [`*/index.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style"
2800
- };
2801
- var CONTENT_SCRIPT_OUT_DIR = "content-scripts";
2802
2900
 
2803
2901
  export {
2902
+ wxt,
2903
+ registerWxt,
2804
2904
  detectDevChanges,
2805
2905
  getEntrypointBundlePath,
2806
2906
  resolvePerBrowserOption,
@@ -2812,7 +2912,7 @@ export {
2812
2912
  tsconfigPaths,
2813
2913
  globals,
2814
2914
  webextensionPolyfillMock,
2815
- getInternalConfig,
2915
+ resolveConfig,
2816
2916
  kebabCaseAlphanumeric,
2817
2917
  printFileList,
2818
2918
  version,