wxt 0.16.2 → 0.16.3

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,73 @@
1
1
  // package.json
2
- var version = "0.16.2";
2
+ var version = "0.16.3";
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(path6) {
12
+ return normalize(path6);
13
+ }
14
+ function unnormalizePath(path6) {
15
+ return systemPath.normalize(path6);
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
+ throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
49
+ }
50
+ }
51
+ const publicAssets = await copyPublicDirectory();
52
+ return { publicAssets, steps };
53
+ }
54
+ async function copyPublicDirectory() {
55
+ const files = await getPublicFiles();
56
+ if (files.length === 0)
57
+ return [];
58
+ const publicAssets = [];
59
+ for (const file of files) {
60
+ const srcPath = resolve(wxt.config.publicDir, file);
61
+ const outPath = resolve(wxt.config.outDir, file);
62
+ await fs2.ensureDir(dirname(outPath));
63
+ await fs2.copyFile(srcPath, outPath);
64
+ publicAssets.push({
65
+ type: "asset",
66
+ fileName: file
67
+ });
68
+ }
69
+ return publicAssets;
70
+ }
3
71
 
4
72
  // src/core/utils/arrays.ts
5
73
  function every(array, predicate) {
@@ -15,29 +83,17 @@ function some(array, predicate) {
15
83
  return false;
16
84
  }
17
85
 
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
86
  // src/core/utils/building/detect-dev-changes.ts
31
- function detectDevChanges(config, changedFiles, currentOutput) {
87
+ function detectDevChanges(changedFiles, currentOutput) {
32
88
  const isConfigChange = some(
33
89
  changedFiles,
34
- (file) => file === config.userConfigMetadata.configFile
90
+ (file) => file === wxt.config.userConfigMetadata.configFile
35
91
  );
36
92
  if (isConfigChange)
37
93
  return { type: "full-restart" };
38
94
  const isRunnerChange = some(
39
95
  changedFiles,
40
- (file) => file === config.runnerConfig.configFile
96
+ (file) => file === wxt.config.runnerConfig.configFile
41
97
  );
42
98
  if (isRunnerChange)
43
99
  return { type: "browser-restart" };
@@ -121,15 +177,23 @@ function findEffectedSteps(changedFile, currentOutput) {
121
177
  return changes;
122
178
  }
123
179
 
180
+ // src/core/utils/building/find-entrypoints.ts
181
+ import { relative as relative2, resolve as resolve3 } from "path";
182
+ import fs3 from "fs-extra";
183
+ import { minimatch } from "minimatch";
184
+ import { parseHTML } from "linkedom";
185
+ import JSON5 from "json5";
186
+ import glob2 from "fast-glob";
187
+
124
188
  // src/core/utils/entrypoints.ts
125
- import path, { relative, resolve } from "node:path";
189
+ import path, { relative, resolve as resolve2 } from "node:path";
126
190
  function getEntrypointName(entrypointsDir, inputPath) {
127
191
  const relativePath = path.relative(entrypointsDir, inputPath);
128
192
  const name = relativePath.split(/[\.\/\\]/, 2)[0];
129
193
  return name;
130
194
  }
131
195
  function getEntrypointOutputFile(entrypoint, ext) {
132
- return resolve(entrypoint.outputDir, `${entrypoint.name}${ext}`);
196
+ return resolve2(entrypoint.outputDir, `${entrypoint.name}${ext}`);
133
197
  }
134
198
  function getEntrypointBundlePath(entrypoint, outDir, ext) {
135
199
  return normalizePath(
@@ -142,71 +206,371 @@ function resolvePerBrowserOption(option, browser) {
142
206
  return option;
143
207
  }
144
208
 
209
+ // src/core/utils/constants.ts
210
+ var VIRTUAL_NOOP_BACKGROUND_MODULE_ID = "virtual:user-background";
211
+
145
212
  // 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";
213
+ import pc2 from "picocolors";
214
+ async function findEntrypoints() {
215
+ const relativePaths = await glob2(Object.keys(PATH_GLOB_TO_TYPE_MAP), {
216
+ cwd: wxt.config.entrypointsDir
217
+ });
218
+ relativePaths.sort();
219
+ const pathGlobs = Object.keys(PATH_GLOB_TO_TYPE_MAP);
220
+ const entrypointInfos = relativePaths.reduce((results, relativePath) => {
221
+ const inputPath = resolve3(wxt.config.entrypointsDir, relativePath);
222
+ const name = getEntrypointName(wxt.config.entrypointsDir, inputPath);
223
+ const matchingGlob = pathGlobs.find(
224
+ (glob4) => minimatch(relativePath, glob4)
225
+ );
226
+ if (matchingGlob) {
227
+ const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
228
+ results.push({
229
+ name,
230
+ inputPath,
231
+ type,
232
+ skipped: wxt.config.filterEntrypoints != null && !wxt.config.filterEntrypoints.has(name)
233
+ });
234
+ }
235
+ return results;
236
+ }, []);
237
+ preventNoEntrypoints(entrypointInfos);
238
+ preventDuplicateEntrypointNames(entrypointInfos);
239
+ let hasBackground = false;
240
+ const entrypoints = await Promise.all(
241
+ entrypointInfos.map(async (info) => {
242
+ const { type } = info;
243
+ switch (type) {
244
+ case "popup":
245
+ return await getPopupEntrypoint(info);
246
+ case "options":
247
+ return await getOptionsEntrypoint(info);
248
+ case "background":
249
+ hasBackground = true;
250
+ return await getBackgroundEntrypoint(info);
251
+ case "content-script":
252
+ return await getContentScriptEntrypoint(info);
253
+ case "unlisted-page":
254
+ return await getUnlistedPageEntrypoint(info);
255
+ case "unlisted-script":
256
+ return await getUnlistedScriptEntrypoint(info);
257
+ case "content-script-style":
258
+ return {
259
+ ...info,
260
+ type,
261
+ outputDir: resolve3(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
262
+ options: {
263
+ include: void 0,
264
+ exclude: void 0
265
+ }
266
+ };
267
+ default:
268
+ return {
269
+ ...info,
270
+ type,
271
+ outputDir: wxt.config.outDir,
272
+ options: {
273
+ include: void 0,
274
+ exclude: void 0
275
+ }
276
+ };
277
+ }
278
+ })
279
+ );
280
+ if (wxt.config.command === "serve" && !hasBackground) {
281
+ entrypoints.push(
282
+ await getBackgroundEntrypoint({
283
+ inputPath: VIRTUAL_NOOP_BACKGROUND_MODULE_ID,
284
+ name: "background",
285
+ type: "background",
286
+ skipped: false
287
+ })
288
+ );
289
+ }
290
+ wxt.logger.debug("All entrypoints:", entrypoints);
291
+ const skippedEntrypointNames = entrypointInfos.filter((item) => item.skipped).map((item) => item.name);
292
+ if (skippedEntrypointNames.length) {
293
+ wxt.logger.warn(
294
+ `Filter excluded the following entrypoints:
295
+ ${skippedEntrypointNames.map((item) => `${pc2.dim("-")} ${pc2.cyan(item)}`).join("\n")}`
296
+ );
297
+ }
298
+ const targetEntrypoints = entrypoints.filter((entry) => {
299
+ const { include, exclude } = entry.options;
300
+ if (include?.length && exclude?.length) {
301
+ wxt.logger.warn(
302
+ `The ${entry.name} entrypoint lists both include and exclude, but only one can be used per entrypoint. Entrypoint ignored.`
303
+ );
304
+ return false;
305
+ }
306
+ if (exclude?.length && !include?.length) {
307
+ return !exclude.includes(wxt.config.browser);
308
+ }
309
+ if (include?.length && !exclude?.length) {
310
+ return include.includes(wxt.config.browser);
311
+ }
312
+ if (skippedEntrypointNames.includes(entry.name)) {
313
+ return false;
314
+ }
315
+ return true;
316
+ });
317
+ wxt.logger.debug(`${wxt.config.browser} entrypoints:`, targetEntrypoints);
318
+ await wxt.hooks.callHook("entrypoints:resolved", wxt, targetEntrypoints);
319
+ return targetEntrypoints;
320
+ }
321
+ function preventDuplicateEntrypointNames(files) {
322
+ const namesToPaths = files.reduce(
323
+ (map, { name, inputPath }) => {
324
+ map[name] ??= [];
325
+ map[name].push(inputPath);
326
+ return map;
327
+ },
328
+ {}
329
+ );
330
+ const errorLines = Object.entries(namesToPaths).reduce(
331
+ (lines, [name, absolutePaths]) => {
332
+ if (absolutePaths.length > 1) {
333
+ lines.push(`- ${name}`);
334
+ absolutePaths.forEach((absolutePath) => {
335
+ lines.push(` - ${relative2(wxt.config.root, absolutePath)}`);
336
+ });
337
+ }
338
+ return lines;
339
+ },
340
+ []
341
+ );
342
+ if (errorLines.length > 0) {
343
+ const errorContent = errorLines.join("\n");
344
+ throw Error(
345
+ `Multiple entrypoints with the same name detected, only one entrypoint for each name is allowed.
151
346
 
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);
347
+ ${errorContent}`
348
+ );
159
349
  }
160
350
  }
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);
351
+ function preventNoEntrypoints(files) {
352
+ if (files.length === 0) {
353
+ throw Error(`No entrypoints found in ${wxt.config.entrypointsDir}`);
354
+ }
166
355
  }
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}`;
356
+ function getHtmlBaseOptions(document) {
357
+ const options = {};
358
+ const includeContent = document.querySelector("meta[name='manifest.include']")?.getAttribute("content");
359
+ if (includeContent) {
360
+ options.include = JSON5.parse(includeContent);
361
+ }
362
+ const excludeContent = document.querySelector("meta[name='manifest.exclude']")?.getAttribute("content");
363
+ if (excludeContent) {
364
+ options.exclude = JSON5.parse(excludeContent);
365
+ }
366
+ return options;
367
+ }
368
+ async function getPopupEntrypoint({
369
+ inputPath,
370
+ name,
371
+ skipped
372
+ }) {
373
+ const content = await fs3.readFile(inputPath, "utf-8");
374
+ const { document } = parseHTML(content);
375
+ const options = getHtmlBaseOptions(document);
376
+ const title = document.querySelector("title");
377
+ if (title != null)
378
+ options.defaultTitle = title.textContent ?? void 0;
379
+ const defaultIconContent = document.querySelector("meta[name='manifest.default_icon']")?.getAttribute("content");
380
+ if (defaultIconContent) {
179
381
  try {
180
- steps.push(await config.builder.build(group));
382
+ options.defaultIcon = JSON5.parse(defaultIconContent);
181
383
  } catch (err) {
182
- throw Error(`Failed to build ${groupNames.join(", ")}`, { cause: err });
384
+ wxt.logger.fatal(
385
+ `Failed to parse default_icon meta tag content as JSON5. content=${defaultIconContent}`,
386
+ err
387
+ );
183
388
  }
184
389
  }
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
- });
390
+ const mv2TypeContent = document.querySelector("meta[name='manifest.type']")?.getAttribute("content");
391
+ if (mv2TypeContent) {
392
+ options.mv2Key = mv2TypeContent === "page_action" ? "page_action" : "browser_action";
202
393
  }
203
- return publicAssets;
204
- }
205
-
206
- // src/core/utils/building/generate-wxt-dir.ts
207
- import { createUnimport } from "unimport";
208
- import fs3 from "fs-extra";
209
- import { relative as relative2, resolve as resolve3 } from "path";
394
+ const browserStyleContent = document.querySelector("meta[name='manifest.browser_style']")?.getAttribute("content");
395
+ if (browserStyleContent) {
396
+ options.browserStyle = browserStyleContent === "true";
397
+ }
398
+ return {
399
+ type: "popup",
400
+ name: "popup",
401
+ options,
402
+ inputPath,
403
+ outputDir: wxt.config.outDir,
404
+ skipped
405
+ };
406
+ }
407
+ async function getOptionsEntrypoint({
408
+ inputPath,
409
+ name,
410
+ skipped
411
+ }) {
412
+ const content = await fs3.readFile(inputPath, "utf-8");
413
+ const { document } = parseHTML(content);
414
+ const options = getHtmlBaseOptions(document);
415
+ const openInTabContent = document.querySelector("meta[name='manifest.open_in_tab']")?.getAttribute("content");
416
+ if (openInTabContent) {
417
+ options.openInTab = openInTabContent === "true";
418
+ }
419
+ const chromeStyleContent = document.querySelector("meta[name='manifest.chrome_style']")?.getAttribute("content");
420
+ if (chromeStyleContent) {
421
+ options.chromeStyle = chromeStyleContent === "true";
422
+ }
423
+ const browserStyleContent = document.querySelector("meta[name='manifest.browser_style']")?.getAttribute("content");
424
+ if (browserStyleContent) {
425
+ options.browserStyle = browserStyleContent === "true";
426
+ }
427
+ return {
428
+ type: "options",
429
+ name: "options",
430
+ options,
431
+ inputPath,
432
+ outputDir: wxt.config.outDir,
433
+ skipped
434
+ };
435
+ }
436
+ async function getUnlistedPageEntrypoint({
437
+ inputPath,
438
+ name,
439
+ skipped
440
+ }) {
441
+ const content = await fs3.readFile(inputPath, "utf-8");
442
+ const { document } = parseHTML(content);
443
+ return {
444
+ type: "unlisted-page",
445
+ name: getEntrypointName(wxt.config.entrypointsDir, inputPath),
446
+ inputPath,
447
+ outputDir: wxt.config.outDir,
448
+ options: getHtmlBaseOptions(document),
449
+ skipped
450
+ };
451
+ }
452
+ async function getUnlistedScriptEntrypoint({
453
+ inputPath,
454
+ name,
455
+ skipped
456
+ }) {
457
+ const defaultExport = await importEntrypointFile(inputPath);
458
+ if (defaultExport == null) {
459
+ throw Error(
460
+ `${name}: Default export not found, did you forget to call "export default defineUnlistedScript(...)"?`
461
+ );
462
+ }
463
+ const { main: _, ...moduleOptions } = defaultExport;
464
+ const options = moduleOptions;
465
+ return {
466
+ type: "unlisted-script",
467
+ name,
468
+ inputPath,
469
+ outputDir: wxt.config.outDir,
470
+ options,
471
+ skipped
472
+ };
473
+ }
474
+ async function getBackgroundEntrypoint({
475
+ inputPath,
476
+ name,
477
+ skipped
478
+ }) {
479
+ let options = {};
480
+ if (inputPath !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
481
+ const defaultExport = await importEntrypointFile(inputPath);
482
+ if (defaultExport == null) {
483
+ throw Error(
484
+ `${name}: Default export not found, did you forget to call "export default defineBackground(...)"?`
485
+ );
486
+ }
487
+ const { main: _, ...moduleOptions } = defaultExport;
488
+ options = moduleOptions;
489
+ }
490
+ if (wxt.config.manifestVersion !== 3) {
491
+ delete options.type;
492
+ }
493
+ return {
494
+ type: "background",
495
+ name,
496
+ inputPath,
497
+ outputDir: wxt.config.outDir,
498
+ options: {
499
+ ...options,
500
+ type: resolvePerBrowserOption(options.type, wxt.config.browser),
501
+ persistent: resolvePerBrowserOption(
502
+ options.persistent,
503
+ wxt.config.browser
504
+ )
505
+ },
506
+ skipped
507
+ };
508
+ }
509
+ async function getContentScriptEntrypoint({
510
+ inputPath,
511
+ name,
512
+ skipped
513
+ }) {
514
+ const { main: _, ...options } = await importEntrypointFile(inputPath);
515
+ if (options == null) {
516
+ throw Error(
517
+ `${name}: Default export not found, did you forget to call "export default defineContentScript(...)"?`
518
+ );
519
+ }
520
+ return {
521
+ type: "content-script",
522
+ name,
523
+ inputPath,
524
+ outputDir: resolve3(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
525
+ options,
526
+ skipped
527
+ };
528
+ }
529
+ var PATH_GLOB_TO_TYPE_MAP = {
530
+ "sandbox.html": "sandbox",
531
+ "sandbox/index.html": "sandbox",
532
+ "*.sandbox.html": "sandbox",
533
+ "*.sandbox/index.html": "sandbox",
534
+ "bookmarks.html": "bookmarks",
535
+ "bookmarks/index.html": "bookmarks",
536
+ "history.html": "history",
537
+ "history/index.html": "history",
538
+ "newtab.html": "newtab",
539
+ "newtab/index.html": "newtab",
540
+ "sidepanel.html": "sidepanel",
541
+ "sidepanel/index.html": "sidepanel",
542
+ "*.sidepanel.html": "sidepanel",
543
+ "*.sidepanel/index.html": "sidepanel",
544
+ "devtools.html": "devtools",
545
+ "devtools/index.html": "devtools",
546
+ "background.[jt]s": "background",
547
+ "background/index.[jt]s": "background",
548
+ [VIRTUAL_NOOP_BACKGROUND_MODULE_ID]: "background",
549
+ "content.[jt]s?(x)": "content-script",
550
+ "content/index.[jt]s?(x)": "content-script",
551
+ "*.content.[jt]s?(x)": "content-script",
552
+ "*.content/index.[jt]s?(x)": "content-script",
553
+ [`content.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
554
+ [`*.content.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
555
+ [`content/index.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
556
+ [`*.content/index.${CSS_EXTENSIONS_PATTERN}`]: "content-script-style",
557
+ "popup.html": "popup",
558
+ "popup/index.html": "popup",
559
+ "options.html": "options",
560
+ "options/index.html": "options",
561
+ "*.html": "unlisted-page",
562
+ "*/index.html": "unlisted-page",
563
+ "*.[jt]s?(x)": "unlisted-script",
564
+ "*/index.[jt]s?(x)": "unlisted-script",
565
+ [`*.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style",
566
+ [`*/index.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style"
567
+ };
568
+ var CONTENT_SCRIPT_OUT_DIR = "content-scripts";
569
+
570
+ // src/core/utils/building/generate-wxt-dir.ts
571
+ import { createUnimport } from "unimport";
572
+ import fs4 from "fs-extra";
573
+ import { relative as relative3, resolve as resolve4 } from "path";
210
574
 
211
575
  // src/core/utils/unimport.ts
212
576
  import { defu } from "defu";
@@ -327,23 +691,23 @@ function parseI18nMessages(messagesJson) {
327
691
  }
328
692
 
329
693
  // src/core/utils/building/generate-wxt-dir.ts
330
- async function generateTypesDir(entrypoints, config) {
331
- await fs3.ensureDir(config.typesDir);
694
+ async function generateTypesDir(entrypoints) {
695
+ await fs4.ensureDir(wxt.config.typesDir);
332
696
  const references = [];
333
- const imports = getUnimportOptions(config);
697
+ const imports = getUnimportOptions(wxt.config);
334
698
  if (imports !== false) {
335
- references.push(await writeImportsDeclarationFile(config, imports));
699
+ references.push(await writeImportsDeclarationFile(imports));
336
700
  }
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);
701
+ references.push(await writePathsDeclarationFile(entrypoints));
702
+ references.push(await writeI18nDeclarationFile());
703
+ references.push(await writeGlobalsDeclarationFile());
704
+ const mainReference = await writeMainDeclarationFile(references);
705
+ await writeTsConfigFile(mainReference);
342
706
  }
343
- async function writeImportsDeclarationFile(config, unimportOptions) {
344
- const filePath = resolve3(config.typesDir, "imports.d.ts");
707
+ async function writeImportsDeclarationFile(unimportOptions) {
708
+ const filePath = resolve4(wxt.config.typesDir, "imports.d.ts");
345
709
  const unimport2 = createUnimport(unimportOptions);
346
- await unimport2.scanImportsFromDir(void 0, { cwd: config.srcDir });
710
+ await unimport2.scanImportsFromDir(void 0, { cwd: wxt.config.srcDir });
347
711
  await writeFileIfDifferent(
348
712
  filePath,
349
713
  ["// Generated by wxt", await unimport2.generateTypeDeclarations()].join(
@@ -352,15 +716,15 @@ async function writeImportsDeclarationFile(config, unimportOptions) {
352
716
  );
353
717
  return filePath;
354
718
  }
355
- async function writePathsDeclarationFile(entrypoints, config) {
356
- const filePath = resolve3(config.typesDir, "paths.d.ts");
719
+ async function writePathsDeclarationFile(entrypoints) {
720
+ const filePath = resolve4(wxt.config.typesDir, "paths.d.ts");
357
721
  const unions = entrypoints.map(
358
722
  (entry) => getEntrypointBundlePath(
359
723
  entry,
360
- config.outDir,
724
+ wxt.config.outDir,
361
725
  entry.inputPath.endsWith(".html") ? ".html" : ".js"
362
726
  )
363
- ).concat(await getPublicFiles(config)).map(normalizePath).map((path6) => ` | "/${path6}"`).sort().join("\n");
727
+ ).concat(await getPublicFiles()).map(normalizePath).map((path6) => ` | "/${path6}"`).sort().join("\n");
364
728
  const template = `// Generated by wxt
365
729
  import "wxt/browser";
366
730
 
@@ -380,9 +744,9 @@ declare module "wxt/browser" {
380
744
  );
381
745
  return filePath;
382
746
  }
383
- async function writeI18nDeclarationFile(config) {
384
- const filePath = resolve3(config.typesDir, "i18n.d.ts");
385
- const defaultLocale = config.manifest.default_locale;
747
+ async function writeI18nDeclarationFile() {
748
+ const filePath = resolve4(wxt.config.typesDir, "i18n.d.ts");
749
+ const defaultLocale = wxt.config.manifest.default_locale;
386
750
  const template = `// Generated by wxt
387
751
  import "wxt/browser";
388
752
 
@@ -405,12 +769,12 @@ declare module "wxt/browser" {
405
769
  let messages;
406
770
  if (defaultLocale) {
407
771
  const defaultLocalePath = path2.resolve(
408
- config.publicDir,
772
+ wxt.config.publicDir,
409
773
  "_locales",
410
774
  defaultLocale,
411
775
  "messages.json"
412
776
  );
413
- const content = JSON.parse(await fs3.readFile(defaultLocalePath, "utf-8"));
777
+ const content = JSON.parse(await fs4.readFile(defaultLocalePath, "utf-8"));
414
778
  messages = parseI18nMessages(content);
415
779
  } else {
416
780
  messages = parseI18nMessages({});
@@ -433,9 +797,9 @@ declare module "wxt/browser" {
433
797
  );
434
798
  return filePath;
435
799
  }
436
- async function writeGlobalsDeclarationFile(config) {
437
- const filePath = resolve3(config.typesDir, "globals.d.ts");
438
- const globals2 = [...getGlobals(config), ...getEntrypointGlobals("")];
800
+ async function writeGlobalsDeclarationFile() {
801
+ const filePath = resolve4(wxt.config.typesDir, "globals.d.ts");
802
+ const globals2 = [...getGlobals(wxt.config), ...getEntrypointGlobals("")];
439
803
  await writeFileIfDifferent(
440
804
  filePath,
441
805
  [
@@ -451,25 +815,25 @@ async function writeGlobalsDeclarationFile(config) {
451
815
  );
452
816
  return filePath;
453
817
  }
454
- async function writeMainDeclarationFile(references, config) {
455
- const dir = config.wxtDir;
456
- const filePath = resolve3(dir, "wxt.d.ts");
818
+ async function writeMainDeclarationFile(references) {
819
+ const dir = wxt.config.wxtDir;
820
+ const filePath = resolve4(dir, "wxt.d.ts");
457
821
  await writeFileIfDifferent(
458
822
  filePath,
459
823
  [
460
824
  "// Generated by wxt",
461
825
  `/// <reference types="wxt/vite-builder-env" />`,
462
826
  ...references.map(
463
- (ref) => `/// <reference types="./${normalizePath(relative2(dir, ref))}" />`
827
+ (ref) => `/// <reference types="./${normalizePath(relative3(dir, ref))}" />`
464
828
  )
465
829
  ].join("\n") + "\n"
466
830
  );
467
831
  return filePath;
468
832
  }
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]) => {
833
+ async function writeTsConfigFile(mainReference) {
834
+ const dir = wxt.config.wxtDir;
835
+ const getTsconfigPath = (path6) => normalizePath(relative3(dir, path6));
836
+ const paths = Object.entries(wxt.config.alias).flatMap(([alias, absolutePath]) => {
473
837
  const aliasPath = getTsconfigPath(absolutePath);
474
838
  return [
475
839
  ` "${alias}": ["${aliasPath}"]`,
@@ -477,7 +841,7 @@ async function writeTsConfigFile(mainReference, config) {
477
841
  ];
478
842
  }).join(",\n");
479
843
  await writeFileIfDifferent(
480
- resolve3(dir, "tsconfig.json"),
844
+ resolve4(dir, "tsconfig.json"),
481
845
  `{
482
846
  "compilerOptions": {
483
847
  "target": "ESNext",
@@ -494,23 +858,23 @@ ${paths}
494
858
  }
495
859
  },
496
860
  "include": [
497
- "${getTsconfigPath(config.root)}/**/*",
861
+ "${getTsconfigPath(wxt.config.root)}/**/*",
498
862
  "./${getTsconfigPath(mainReference)}"
499
863
  ],
500
- "exclude": ["${getTsconfigPath(config.outBaseDir)}"]
864
+ "exclude": ["${getTsconfigPath(wxt.config.outBaseDir)}"]
501
865
  }`
502
866
  );
503
867
  }
504
868
 
505
- // src/core/utils/building/get-internal-config.ts
869
+ // src/core/utils/building/resolve-config.ts
506
870
  import { loadConfig } from "c12";
507
871
  import path4 from "node:path";
508
872
 
509
873
  // src/core/utils/cache.ts
510
- import fs4, { ensureDir } from "fs-extra";
511
- import { dirname as dirname2, resolve as resolve4 } from "path";
874
+ import fs5, { ensureDir } from "fs-extra";
875
+ import { dirname as dirname2, resolve as resolve5 } from "path";
512
876
  function createFsCache(wxtDir) {
513
- const getPath = (key) => resolve4(wxtDir, "cache", encodeURIComponent(key));
877
+ const getPath = (key) => resolve5(wxtDir, "cache", encodeURIComponent(key));
514
878
  return {
515
879
  async set(key, value) {
516
880
  const path6 = getPath(key);
@@ -520,7 +884,7 @@ function createFsCache(wxtDir) {
520
884
  async get(key) {
521
885
  const path6 = getPath(key);
522
886
  try {
523
- return await fs4.readFile(path6, "utf-8");
887
+ return await fs5.readFile(path6, "utf-8");
524
888
  } catch {
525
889
  return void 0;
526
890
  }
@@ -528,16 +892,16 @@ function createFsCache(wxtDir) {
528
892
  };
529
893
  }
530
894
 
531
- // src/core/utils/building/get-internal-config.ts
895
+ // src/core/utils/building/resolve-config.ts
532
896
  import consola, { LogLevels } from "consola";
533
897
 
534
898
  // 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";
899
+ import { parseHTML as parseHTML2 } from "linkedom";
900
+ import { dirname as dirname3, relative as relative4, resolve as resolve6 } from "node:path";
537
901
  var reactRefreshPreamble = "";
538
902
  function devHtmlPrerender(config) {
539
903
  const htmlReloadId = "@wxt/reload-html";
540
- const resolvedHtmlReloadId = resolve5(
904
+ const resolvedHtmlReloadId = resolve6(
541
905
  config.root,
542
906
  "node_modules/wxt/dist/virtual/reload-html.js"
543
907
  );
@@ -562,7 +926,7 @@ function devHtmlPrerender(config) {
562
926
  const server = config.server;
563
927
  if (config.command !== "serve" || server == null || !id.endsWith(".html"))
564
928
  return;
565
- const { document } = parseHTML(code);
929
+ const { document } = parseHTML2(code);
566
930
  const _pointToDevServer = (querySelector, attr) => pointToDevServer(config, server, id, document, querySelector, attr);
567
931
  _pointToDevServer("script[type=module]", "src");
568
932
  _pointToDevServer("link[rel=stylesheet]", "href");
@@ -585,7 +949,7 @@ function devHtmlPrerender(config) {
585
949
  const name = getEntrypointName(config.entrypointsDir, ctx.filename);
586
950
  const url = `${server.origin}/${name}.html`;
587
951
  const serverHtml = await server.transformHtml(url, html, originalUrl);
588
- const { document } = parseHTML(serverHtml);
952
+ const { document } = parseHTML2(serverHtml);
589
953
  const reactRefreshScript = Array.from(
590
954
  document.querySelectorAll("script[type=module]")
591
955
  ).find((script) => script.innerHTML.includes("@react-refresh"));
@@ -642,16 +1006,16 @@ function pointToDevServer(config, server, id, document, querySelector, attr) {
642
1006
  );
643
1007
  if (matchingAlias) {
644
1008
  const [alias, replacement] = matchingAlias;
645
- resolvedAbsolutePath = resolve5(
1009
+ resolvedAbsolutePath = resolve6(
646
1010
  config.root,
647
1011
  src.replace(alias, replacement)
648
1012
  );
649
1013
  } else {
650
- resolvedAbsolutePath = resolve5(dirname3(id), src);
1014
+ resolvedAbsolutePath = resolve6(dirname3(id), src);
651
1015
  }
652
1016
  if (resolvedAbsolutePath) {
653
1017
  const relativePath = normalizePath(
654
- relative3(config.root, resolvedAbsolutePath)
1018
+ relative4(config.root, resolvedAbsolutePath)
655
1019
  );
656
1020
  if (relativePath.startsWith(".")) {
657
1021
  let path6 = normalizePath(resolvedAbsolutePath);
@@ -771,8 +1135,8 @@ function download(config) {
771
1135
  }
772
1136
 
773
1137
  // 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";
1138
+ import { dirname as dirname4, extname, resolve as resolve7, join } from "node:path";
1139
+ import fs6, { ensureDir as ensureDir2 } from "fs-extra";
776
1140
  function multipageMove(entrypoints, config) {
777
1141
  return {
778
1142
  name: "wxt:multipage-move",
@@ -799,10 +1163,10 @@ function multipageMove(entrypoints, config) {
799
1163
  );
800
1164
  continue;
801
1165
  }
802
- const oldAbsPath = resolve6(config.outDir, oldBundlePath);
803
- const newAbsPath = resolve6(config.outDir, newBundlePath);
1166
+ const oldAbsPath = resolve7(config.outDir, oldBundlePath);
1167
+ const newAbsPath = resolve7(config.outDir, newBundlePath);
804
1168
  await ensureDir2(dirname4(newAbsPath));
805
- await fs5.move(oldAbsPath, newAbsPath, { overwrite: true });
1169
+ await fs6.move(oldAbsPath, newAbsPath, { overwrite: true });
806
1170
  const renamedChunk = {
807
1171
  ...bundle[oldBundlePath],
808
1172
  fileName: newBundlePath
@@ -815,16 +1179,16 @@ function multipageMove(entrypoints, config) {
815
1179
  };
816
1180
  }
817
1181
  async function removeEmptyDirs(dir) {
818
- const files = await fs5.readdir(dir);
1182
+ const files = await fs6.readdir(dir);
819
1183
  for (const file of files) {
820
1184
  const filePath = join(dir, file);
821
- const stats = await fs5.stat(filePath);
1185
+ const stats = await fs6.stat(filePath);
822
1186
  if (stats.isDirectory()) {
823
1187
  await removeEmptyDirs(filePath);
824
1188
  }
825
1189
  }
826
1190
  try {
827
- await fs5.rmdir(dir);
1191
+ await fs6.rmdir(dir);
828
1192
  } catch {
829
1193
  }
830
1194
  }
@@ -865,8 +1229,8 @@ function unimport(config) {
865
1229
  }
866
1230
 
867
1231
  // src/core/builders/vite/plugins/virtualEntrypoint.ts
868
- import fs6 from "fs-extra";
869
- import { resolve as resolve7 } from "path";
1232
+ import fs7 from "fs-extra";
1233
+ import { resolve as resolve8 } from "path";
870
1234
  function virtualEntrypoint(type, config) {
871
1235
  const virtualId = `virtual:wxt-${type}?`;
872
1236
  const resolvedVirtualId = `\0${virtualId}`;
@@ -883,8 +1247,8 @@ function virtualEntrypoint(type, config) {
883
1247
  if (!id.startsWith(resolvedVirtualId))
884
1248
  return;
885
1249
  const inputPath = id.replace(resolvedVirtualId, "");
886
- const template = await fs6.readFile(
887
- resolve7(
1250
+ const template = await fs7.readFile(
1251
+ resolve8(
888
1252
  config.root,
889
1253
  `node_modules/wxt/dist/virtual/${type}-entrypoint.js`
890
1254
  ),
@@ -909,9 +1273,6 @@ function tsconfigPaths(config) {
909
1273
  };
910
1274
  }
911
1275
 
912
- // src/core/utils/constants.ts
913
- var VIRTUAL_NOOP_BACKGROUND_MODULE_ID = "virtual:user-background";
914
-
915
1276
  // src/core/builders/vite/plugins/noopBackground.ts
916
1277
  function noopBackground() {
917
1278
  const virtualModuleId = VIRTUAL_NOOP_BACKGROUND_MODULE_ID;
@@ -1278,9 +1639,9 @@ function getRollupEntry(entrypoint) {
1278
1639
  return virtualEntrypointType ? `virtual:wxt-${virtualEntrypointType}?${entrypoint.inputPath}` : entrypoint.inputPath;
1279
1640
  }
1280
1641
 
1281
- // src/core/utils/building/get-internal-config.ts
1642
+ // src/core/utils/building/resolve-config.ts
1282
1643
  import defu2 from "defu";
1283
- async function getInternalConfig(inlineConfig, command, server) {
1644
+ async function resolveConfig(inlineConfig, command, server) {
1284
1645
  let userConfig = {};
1285
1646
  let userConfigMetadata;
1286
1647
  if (inlineConfig.configFile !== false) {
@@ -1374,7 +1735,8 @@ async function getInternalConfig(inlineConfig, command, server) {
1374
1735
  server,
1375
1736
  dev: {
1376
1737
  reloadCommand
1377
- }
1738
+ },
1739
+ hooks: mergedConfig.hooks ?? {}
1378
1740
  };
1379
1741
  const builder = await createViteBuilder(
1380
1742
  inlineConfig,
@@ -1411,6 +1773,10 @@ function mergeInlineConfig(inlineConfig, userConfig) {
1411
1773
  inlineConfig.zip ?? {},
1412
1774
  userConfig.zip ?? {}
1413
1775
  );
1776
+ const hooks = defu2(
1777
+ inlineConfig.hooks ?? {},
1778
+ userConfig.hooks ?? {}
1779
+ );
1414
1780
  return {
1415
1781
  root: inlineConfig.root ?? userConfig.root,
1416
1782
  browser: inlineConfig.browser ?? userConfig.browser,
@@ -1445,7 +1811,8 @@ function mergeInlineConfig(inlineConfig, userConfig) {
1445
1811
  dev: {
1446
1812
  ...userConfig.dev,
1447
1813
  ...inlineConfig.dev
1448
- }
1814
+ },
1815
+ hooks
1449
1816
  };
1450
1817
  }
1451
1818
  function resolveInternalZipConfig(root, mergedConfig) {
@@ -1513,8 +1880,8 @@ var ENTRY_TYPE_TO_GROUP_MAP = {
1513
1880
  // src/core/utils/building/import-entrypoint.ts
1514
1881
  import createJITI from "jiti";
1515
1882
  import { createUnimport as createUnimport3 } from "unimport";
1516
- import fs7 from "fs-extra";
1517
- import { relative as relative4, resolve as resolve8 } from "node:path";
1883
+ import fs8 from "fs-extra";
1884
+ import { relative as relative5, resolve as resolve9 } from "node:path";
1518
1885
 
1519
1886
  // src/core/utils/strings.ts
1520
1887
  function kebabCaseAlphanumeric(str) {
@@ -1536,30 +1903,30 @@ ${noImports}`;
1536
1903
  // src/core/utils/building/import-entrypoint.ts
1537
1904
  import { transformSync } from "esbuild";
1538
1905
  import { fileURLToPath } from "node:url";
1539
- async function importEntrypointFile(path6, config) {
1540
- config.logger.debug("Loading file metadata:", path6);
1906
+ async function importEntrypointFile(path6) {
1907
+ wxt.logger.debug("Loading file metadata:", path6);
1541
1908
  const normalPath = normalizePath(path6);
1542
1909
  const unimport2 = createUnimport3({
1543
- ...getUnimportOptions(config),
1910
+ ...getUnimportOptions(wxt.config),
1544
1911
  // Only allow specific imports, not all from the project
1545
1912
  dirs: []
1546
1913
  });
1547
1914
  await unimport2.init();
1548
- const text = await fs7.readFile(path6, "utf-8");
1915
+ const text = await fs8.readFile(path6, "utf-8");
1549
1916
  const textNoImports = removeProjectImportStatements(text);
1550
1917
  const { code } = await unimport2.injectImports(textNoImports);
1551
- config.logger.debug(
1918
+ wxt.logger.debug(
1552
1919
  ["Text:", text, "No imports:", textNoImports, "Code:", code].join("\n")
1553
1920
  );
1554
1921
  const jiti = createJITI(
1555
1922
  typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url),
1556
1923
  {
1557
1924
  cache: false,
1558
- debug: config.debug,
1925
+ debug: wxt.config.debug,
1559
1926
  esmResolve: true,
1560
1927
  alias: {
1561
- "webextension-polyfill": resolve8(
1562
- config.root,
1928
+ "webextension-polyfill": resolve9(
1929
+ wxt.config.root,
1563
1930
  "node_modules/wxt/dist/virtual/mock-browser.js"
1564
1931
  )
1565
1932
  },
@@ -1591,7 +1958,7 @@ async function importEntrypointFile(path6, config) {
1591
1958
  const res = await jiti(path6);
1592
1959
  return res.default;
1593
1960
  } catch (err) {
1594
- const filePath = relative4(config.root, path6);
1961
+ const filePath = relative5(wxt.config.root, path6);
1595
1962
  if (err instanceof ReferenceError) {
1596
1963
  const variableName = err.message.replace(" is not defined", "");
1597
1964
  throw Error(
@@ -1599,7 +1966,7 @@ async function importEntrypointFile(path6, config) {
1599
1966
  { cause: err }
1600
1967
  );
1601
1968
  } else {
1602
- config.logger.error(err);
1969
+ wxt.logger.error(err);
1603
1970
  throw Error(`Failed to load entrypoint: ${filePath}`, { cause: err });
1604
1971
  }
1605
1972
  }
@@ -1614,16 +1981,16 @@ function getEsbuildOptions(opts) {
1614
1981
  }
1615
1982
 
1616
1983
  // src/core/utils/building/internal-build.ts
1617
- import pc4 from "picocolors";
1618
- import fs11 from "fs-extra";
1984
+ import pc5 from "picocolors";
1985
+ import fs12 from "fs-extra";
1619
1986
 
1620
1987
  // src/core/utils/log/printBuildSummary.ts
1621
- import { resolve as resolve9 } from "path";
1988
+ import { resolve as resolve10 } from "path";
1622
1989
 
1623
1990
  // src/core/utils/log/printFileList.ts
1624
1991
  import path5 from "node:path";
1625
- import pc2 from "picocolors";
1626
- import fs8 from "fs-extra";
1992
+ import pc3 from "picocolors";
1993
+ import fs9 from "fs-extra";
1627
1994
  import { filesize } from "filesize";
1628
1995
 
1629
1996
  // src/core/utils/log/printTable.ts
@@ -1664,36 +2031,36 @@ async function printFileList(log, header, baseDir, files) {
1664
2031
  ];
1665
2032
  const prefix = i === files.length - 1 ? " \u2514\u2500" : " \u251C\u2500";
1666
2033
  const color = getChunkColor(file);
1667
- const stats = await fs8.lstat(file);
2034
+ const stats = await fs9.lstat(file);
1668
2035
  totalSize += stats.size;
1669
2036
  const size = String(filesize(stats.size));
1670
2037
  return [
1671
- `${pc2.gray(prefix)} ${pc2.dim(parts[0])}${color(parts[1])}`,
1672
- pc2.dim(size)
2038
+ `${pc3.gray(prefix)} ${pc3.dim(parts[0])}${color(parts[1])}`,
2039
+ pc3.dim(size)
1673
2040
  ];
1674
2041
  })
1675
2042
  );
1676
- fileRows.push([`${pc2.cyan("\u03A3 Total size:")} ${String(filesize(totalSize))}`]);
2043
+ fileRows.push([`${pc3.cyan("\u03A3 Total size:")} ${String(filesize(totalSize))}`]);
1677
2044
  printTable(log, header, fileRows);
1678
2045
  }
1679
- var DEFAULT_COLOR = pc2.blue;
2046
+ var DEFAULT_COLOR = pc3.blue;
1680
2047
  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
2048
+ ".js.map": pc3.gray,
2049
+ ".cjs.map": pc3.gray,
2050
+ ".mjs.map": pc3.gray,
2051
+ ".html": pc3.green,
2052
+ ".css": pc3.magenta,
2053
+ ".js": pc3.cyan,
2054
+ ".cjs": pc3.cyan,
2055
+ ".mjs": pc3.cyan,
2056
+ ".zip": pc3.yellow
1690
2057
  };
1691
2058
  function getChunkColor(filename) {
1692
2059
  return Object.entries(CHUNK_COLORS).find(([key]) => filename.endsWith(key))?.[1] ?? DEFAULT_COLOR;
1693
2060
  }
1694
2061
 
1695
2062
  // src/core/utils/log/printBuildSummary.ts
1696
- async function printBuildSummary(log, header, output, config) {
2063
+ async function printBuildSummary(log, header, output) {
1697
2064
  const chunks = [
1698
2065
  ...output.steps.flatMap((step) => step.chunks),
1699
2066
  ...output.publicAssets
@@ -1705,8 +2072,10 @@ async function printBuildSummary(log, header, output, config) {
1705
2072
  return diff;
1706
2073
  return l.fileName.localeCompare(r.fileName);
1707
2074
  });
1708
- const files = chunks.map((chunk) => resolve9(config.outDir, chunk.fileName));
1709
- await printFileList(log, header, config.outDir, files);
2075
+ const files = chunks.map(
2076
+ (chunk) => resolve10(wxt.config.outDir, chunk.fileName)
2077
+ );
2078
+ await printFileList(log, header, wxt.config.outDir, files);
1710
2079
  }
1711
2080
  var DEFAULT_SORT_WEIGHT = 100;
1712
2081
  var CHUNK_SORT_WEIGHTS = {
@@ -1723,15 +2092,15 @@ function getChunkSortWeight(filename) {
1723
2092
  }
1724
2093
 
1725
2094
  // src/core/utils/log/printHeader.ts
1726
- import pc3 from "picocolors";
2095
+ import pc4 from "picocolors";
1727
2096
  import { consola as consola2 } from "consola";
1728
2097
 
1729
2098
  // src/core/utils/building/internal-build.ts
1730
- import glob2 from "fast-glob";
2099
+ import glob3 from "fast-glob";
1731
2100
 
1732
2101
  // src/core/utils/manifest.ts
1733
- import fs10 from "fs-extra";
1734
- import { resolve as resolve11 } from "path";
2102
+ import fs11 from "fs-extra";
2103
+ import { resolve as resolve12 } from "path";
1735
2104
 
1736
2105
  // src/core/utils/content-security-policy.ts
1737
2106
  var ContentSecurityPolicy = class _ContentSecurityPolicy {
@@ -1777,8 +2146,8 @@ var ContentSecurityPolicy = class _ContentSecurityPolicy {
1777
2146
  };
1778
2147
 
1779
2148
  // src/core/utils/content-scripts.ts
1780
- function hashContentScriptOptions(options, config) {
1781
- const simplifiedOptions = mapWxtOptionsToContentScript(options, config);
2149
+ function hashContentScriptOptions(options) {
2150
+ const simplifiedOptions = mapWxtOptionsToContentScript(options);
1782
2151
  Object.keys(simplifiedOptions).forEach((key) => {
1783
2152
  if (simplifiedOptions[key] == null)
1784
2153
  delete simplifiedOptions[key];
@@ -1804,45 +2173,45 @@ function hashContentScriptOptions(options, config) {
1804
2173
  }).sort((l, r) => l[0].localeCompare(r[0]))
1805
2174
  );
1806
2175
  }
1807
- function mapWxtOptionsToContentScript(options, config) {
2176
+ function mapWxtOptionsToContentScript(options) {
1808
2177
  return {
1809
- matches: resolvePerBrowserOption(options.matches, config.browser),
1810
- all_frames: resolvePerBrowserOption(options.allFrames, config.browser),
2178
+ matches: resolvePerBrowserOption(options.matches, wxt.config.browser),
2179
+ all_frames: resolvePerBrowserOption(options.allFrames, wxt.config.browser),
1811
2180
  match_about_blank: resolvePerBrowserOption(
1812
2181
  options.matchAboutBlank,
1813
- config.browser
2182
+ wxt.config.browser
1814
2183
  ),
1815
2184
  exclude_globs: resolvePerBrowserOption(
1816
2185
  options.excludeGlobs,
1817
- config.browser
2186
+ wxt.config.browser
1818
2187
  ),
1819
2188
  exclude_matches: resolvePerBrowserOption(
1820
2189
  options.excludeMatches,
1821
- config.browser
2190
+ wxt.config.browser
1822
2191
  ),
1823
2192
  include_globs: resolvePerBrowserOption(
1824
2193
  options.includeGlobs,
1825
- config.browser
2194
+ wxt.config.browser
1826
2195
  ),
1827
- run_at: resolvePerBrowserOption(options.runAt, config.browser),
2196
+ run_at: resolvePerBrowserOption(options.runAt, wxt.config.browser),
1828
2197
  // @ts-expect-error: untyped chrome options
1829
2198
  match_origin_as_fallback: resolvePerBrowserOption(
1830
2199
  options.matchOriginAsFallback,
1831
- config.browser
2200
+ wxt.config.browser
1832
2201
  ),
1833
2202
  world: options.world
1834
2203
  };
1835
2204
  }
1836
2205
 
1837
2206
  // 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");
2207
+ import { resolve as resolve11 } from "node:path";
2208
+ import fs10 from "fs-extra";
2209
+ async function getPackageJson() {
2210
+ const file = resolve11(wxt.config.root, "package.json");
1842
2211
  try {
1843
- return await fs9.readJson(file);
2212
+ return await fs10.readJson(file);
1844
2213
  } catch (err) {
1845
- config.logger.debug(
2214
+ wxt.logger.debug(
1846
2215
  `Failed to read package.json at: ${file}. Returning undefined.`
1847
2216
  );
1848
2217
  return {};
@@ -1852,40 +2221,40 @@ async function getPackageJson(config) {
1852
2221
  // src/core/utils/manifest.ts
1853
2222
  import { produce } from "immer";
1854
2223
  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);
2224
+ async function writeManifest(manifest, output) {
2225
+ const str = wxt.config.mode === "production" ? JSON.stringify(manifest) : JSON.stringify(manifest, null, 2);
2226
+ await fs11.ensureDir(wxt.config.outDir);
2227
+ await writeFileIfDifferent(resolve12(wxt.config.outDir, "manifest.json"), str);
1859
2228
  output.publicAssets.unshift({
1860
2229
  type: "asset",
1861
2230
  fileName: "manifest.json"
1862
2231
  });
1863
2232
  }
1864
- async function generateManifest(entrypoints, buildOutput, config) {
2233
+ async function generateManifest(entrypoints, buildOutput) {
1865
2234
  const warnings = [];
1866
- const pkg = await getPackageJson(config);
1867
- let versionName = config.manifest.version_name ?? config.manifest.version ?? pkg?.version;
2235
+ const pkg = await getPackageJson();
2236
+ let versionName = wxt.config.manifest.version_name ?? wxt.config.manifest.version ?? pkg?.version;
1868
2237
  if (versionName == null) {
1869
2238
  versionName = "0.0.0";
1870
- config.logger.warn(
2239
+ wxt.logger.warn(
1871
2240
  '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
2241
  );
1873
2242
  }
1874
- const version2 = config.manifest.version ?? simplifyVersion(versionName);
2243
+ const version2 = wxt.config.manifest.version ?? simplifyVersion(versionName);
1875
2244
  const baseManifest = {
1876
- manifest_version: config.manifestVersion,
2245
+ manifest_version: wxt.config.manifestVersion,
1877
2246
  name: pkg?.name,
1878
2247
  description: pkg?.description,
1879
2248
  version: version2,
1880
2249
  short_name: pkg?.shortName,
1881
2250
  icons: discoverIcons(buildOutput)
1882
2251
  };
1883
- const userManifest = config.manifest;
2252
+ const userManifest = wxt.config.manifest;
1884
2253
  const manifest = defu3(
1885
2254
  userManifest,
1886
2255
  baseManifest
1887
2256
  );
1888
- if (config.command === "serve" && config.dev.reloadCommand) {
2257
+ if (wxt.config.command === "serve" && wxt.config.dev.reloadCommand) {
1889
2258
  if (manifest.commands && Object.keys(manifest.commands).length >= 4) {
1890
2259
  warnings.push([
1891
2260
  "Extension already has 4 registered commands, WXT's reload command is disabled"
@@ -1895,20 +2264,21 @@ async function generateManifest(entrypoints, buildOutput, config) {
1895
2264
  manifest.commands["wxt:reload-extension"] = {
1896
2265
  description: "Reload the extension during development",
1897
2266
  suggested_key: {
1898
- default: config.dev.reloadCommand
2267
+ default: wxt.config.dev.reloadCommand
1899
2268
  }
1900
2269
  };
1901
2270
  }
1902
2271
  }
1903
2272
  manifest.version = version2;
1904
2273
  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);
2274
+ wxt.config.browser === "firefox" || versionName === version2 ? void 0 : versionName;
2275
+ addEntrypoints(manifest, entrypoints, buildOutput);
2276
+ if (wxt.config.command === "serve")
2277
+ addDevModeCsp(manifest);
2278
+ if (wxt.config.command === "serve")
2279
+ addDevModePermissions(manifest);
2280
+ const finalManifest = produce(manifest, wxt.config.transformManifest);
2281
+ await wxt.hooks.callHook("build:manifestGenerated", wxt, finalManifest);
1912
2282
  if (finalManifest.name == null)
1913
2283
  throw Error(
1914
2284
  "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"
@@ -1933,7 +2303,7 @@ function simplifyVersion(versionName) {
1933
2303
  );
1934
2304
  return version2;
1935
2305
  }
1936
- function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2306
+ function addEntrypoints(manifest, entrypoints, buildOutput) {
1937
2307
  const entriesByType = entrypoints.reduce((map, entrypoint) => {
1938
2308
  map[entrypoint.type] ??= [];
1939
2309
  map[entrypoint.type]?.push(entrypoint);
@@ -1950,13 +2320,17 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
1950
2320
  const sandboxes = entriesByType["sandbox"];
1951
2321
  const sidepanels = entriesByType["sidepanel"];
1952
2322
  if (background) {
1953
- const script = getEntrypointBundlePath(background, config.outDir, ".js");
1954
- if (config.browser === "firefox" && config.manifestVersion === 3) {
2323
+ const script = getEntrypointBundlePath(
2324
+ background,
2325
+ wxt.config.outDir,
2326
+ ".js"
2327
+ );
2328
+ if (wxt.config.browser === "firefox" && wxt.config.manifestVersion === 3) {
1955
2329
  manifest.background = {
1956
2330
  type: background.options.type,
1957
2331
  scripts: [script]
1958
2332
  };
1959
- } else if (config.manifestVersion === 3) {
2333
+ } else if (wxt.config.manifestVersion === 3) {
1960
2334
  manifest.background = {
1961
2335
  type: background.options.type,
1962
2336
  service_worker: script
@@ -1969,29 +2343,29 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
1969
2343
  }
1970
2344
  }
1971
2345
  if (bookmarks) {
1972
- if (config.browser === "firefox") {
1973
- config.logger.warn(
2346
+ if (wxt.config.browser === "firefox") {
2347
+ wxt.logger.warn(
1974
2348
  "Bookmarks are not supported by Firefox. chrome_url_overrides.bookmarks was not added to the manifest"
1975
2349
  );
1976
2350
  } else {
1977
2351
  manifest.chrome_url_overrides ??= {};
1978
2352
  manifest.chrome_url_overrides.bookmarks = getEntrypointBundlePath(
1979
2353
  bookmarks,
1980
- config.outDir,
2354
+ wxt.config.outDir,
1981
2355
  ".html"
1982
2356
  );
1983
2357
  }
1984
2358
  }
1985
2359
  if (history) {
1986
- if (config.browser === "firefox") {
1987
- config.logger.warn(
2360
+ if (wxt.config.browser === "firefox") {
2361
+ wxt.logger.warn(
1988
2362
  "Bookmarks are not supported by Firefox. chrome_url_overrides.history was not added to the manifest"
1989
2363
  );
1990
2364
  } else {
1991
2365
  manifest.chrome_url_overrides ??= {};
1992
2366
  manifest.chrome_url_overrides.history = getEntrypointBundlePath(
1993
2367
  history,
1994
- config.outDir,
2368
+ wxt.config.outDir,
1995
2369
  ".html"
1996
2370
  );
1997
2371
  }
@@ -2000,14 +2374,14 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2000
2374
  manifest.chrome_url_overrides ??= {};
2001
2375
  manifest.chrome_url_overrides.newtab = getEntrypointBundlePath(
2002
2376
  newtab,
2003
- config.outDir,
2377
+ wxt.config.outDir,
2004
2378
  ".html"
2005
2379
  );
2006
2380
  }
2007
2381
  if (popup) {
2008
2382
  const default_popup = getEntrypointBundlePath(
2009
2383
  popup,
2010
- config.outDir,
2384
+ wxt.config.outDir,
2011
2385
  ".html"
2012
2386
  );
2013
2387
  const options2 = {};
@@ -2035,28 +2409,28 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2035
2409
  if (devtools) {
2036
2410
  manifest.devtools_page = getEntrypointBundlePath(
2037
2411
  devtools,
2038
- config.outDir,
2412
+ wxt.config.outDir,
2039
2413
  ".html"
2040
2414
  );
2041
2415
  }
2042
2416
  if (options) {
2043
- const page = getEntrypointBundlePath(options, config.outDir, ".html");
2417
+ const page = getEntrypointBundlePath(options, wxt.config.outDir, ".html");
2044
2418
  manifest.options_ui = {
2045
2419
  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,
2420
+ browser_style: wxt.config.browser === "firefox" ? options.options.browserStyle : void 0,
2421
+ chrome_style: wxt.config.browser !== "firefox" ? options.options.chromeStyle : void 0,
2048
2422
  page
2049
2423
  };
2050
2424
  }
2051
2425
  if (sandboxes?.length) {
2052
- if (config.browser === "firefox") {
2053
- config.logger.warn(
2426
+ if (wxt.config.browser === "firefox") {
2427
+ wxt.logger.warn(
2054
2428
  "Sandboxed pages not supported by Firefox. sandbox.pages was not added to the manifest"
2055
2429
  );
2056
2430
  } else {
2057
2431
  manifest.sandbox = {
2058
2432
  pages: sandboxes.map(
2059
- (entry) => getEntrypointBundlePath(entry, config.outDir, ".html")
2433
+ (entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".html")
2060
2434
  )
2061
2435
  };
2062
2436
  }
@@ -2065,33 +2439,33 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2065
2439
  const defaultSidepanel = sidepanels.find((entry) => entry.name === "sidepanel") ?? sidepanels[0];
2066
2440
  const page = getEntrypointBundlePath(
2067
2441
  defaultSidepanel,
2068
- config.outDir,
2442
+ wxt.config.outDir,
2069
2443
  ".html"
2070
2444
  );
2071
- if (config.browser === "firefox") {
2445
+ if (wxt.config.browser === "firefox") {
2072
2446
  manifest.sidebar_action = {
2073
2447
  // TODO: Add options to side panel
2074
2448
  // ...defaultSidepanel.options,
2075
2449
  default_panel: page
2076
2450
  };
2077
- } else if (config.manifestVersion === 3) {
2451
+ } else if (wxt.config.manifestVersion === 3) {
2078
2452
  manifest.side_panel = {
2079
2453
  default_path: page
2080
2454
  };
2081
2455
  } else {
2082
- config.logger.warn(
2456
+ wxt.logger.warn(
2083
2457
  "Side panel not supported by Chromium using MV2. side_panel.default_path was not added to the manifest"
2084
2458
  );
2085
2459
  }
2086
2460
  }
2087
2461
  if (contentScripts?.length) {
2088
2462
  const cssMap = getContentScriptsCssMap(buildOutput, contentScripts);
2089
- if (config.command === "serve" && config.manifestVersion === 3) {
2463
+ if (wxt.config.command === "serve" && wxt.config.manifestVersion === 3) {
2090
2464
  const hostPermissions = new Set(manifest.host_permissions ?? []);
2091
2465
  contentScripts.forEach((script) => {
2092
2466
  const matches = resolvePerBrowserOption(
2093
2467
  script.options.matches,
2094
- config.browser
2468
+ wxt.config.browser
2095
2469
  );
2096
2470
  matches.forEach((matchPattern) => {
2097
2471
  hostPermissions.add(matchPattern);
@@ -2102,7 +2476,7 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2102
2476
  );
2103
2477
  } else {
2104
2478
  const hashToEntrypointsMap = contentScripts.reduce((map, script) => {
2105
- const hash = hashContentScriptOptions(script.options, config);
2479
+ const hash = hashContentScriptOptions(script.options);
2106
2480
  if (map.has(hash))
2107
2481
  map.get(hash)?.push(script);
2108
2482
  else
@@ -2111,10 +2485,10 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2111
2485
  }, /* @__PURE__ */ new Map());
2112
2486
  const newContentScripts = Array.from(hashToEntrypointsMap.entries()).map(
2113
2487
  ([, scripts]) => ({
2114
- ...mapWxtOptionsToContentScript(scripts[0].options, config),
2488
+ ...mapWxtOptionsToContentScript(scripts[0].options),
2115
2489
  css: getContentScriptCssFiles(scripts, cssMap),
2116
2490
  js: scripts.map(
2117
- (entry) => getEntrypointBundlePath(entry, config.outDir, ".js")
2491
+ (entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".js")
2118
2492
  )
2119
2493
  })
2120
2494
  );
@@ -2124,7 +2498,6 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
2124
2498
  }
2125
2499
  }
2126
2500
  const contentScriptCssResources = getContentScriptCssWebAccessibleResources(
2127
- config,
2128
2501
  contentScripts,
2129
2502
  cssMap
2130
2503
  );
@@ -2167,9 +2540,9 @@ function discoverIcons(buildOutput) {
2167
2540
  });
2168
2541
  return icons.length > 0 ? Object.fromEntries(icons) : void 0;
2169
2542
  }
2170
- function addDevModeCsp(manifest, config) {
2171
- const permission = `http://${config.server?.hostname ?? ""}/*`;
2172
- const allowedCsp = config.server?.origin ?? "http://localhost:*";
2543
+ function addDevModeCsp(manifest) {
2544
+ const permission = `http://${wxt.config.server?.hostname ?? ""}/*`;
2545
+ const allowedCsp = wxt.config.server?.origin ?? "http://localhost:*";
2173
2546
  if (manifest.manifest_version === 3) {
2174
2547
  addHostPermission(manifest, permission);
2175
2548
  } else {
@@ -2182,7 +2555,7 @@ function addDevModeCsp(manifest, config) {
2182
2555
  ) : manifest.content_security_policy ?? "script-src 'self'; object-src 'self';"
2183
2556
  // default CSP for MV2
2184
2557
  );
2185
- if (config.server)
2558
+ if (wxt.config.server)
2186
2559
  csp.add("script-src", allowedCsp);
2187
2560
  if (manifest.manifest_version === 3) {
2188
2561
  manifest.content_security_policy ??= {};
@@ -2191,9 +2564,9 @@ function addDevModeCsp(manifest, config) {
2191
2564
  manifest.content_security_policy = csp.toString();
2192
2565
  }
2193
2566
  }
2194
- function addDevModePermissions(manifest, config) {
2567
+ function addDevModePermissions(manifest) {
2195
2568
  addPermission(manifest, "tabs");
2196
- if (config.manifestVersion === 3)
2569
+ if (wxt.config.manifestVersion === 3)
2197
2570
  addPermission(manifest, "scripting");
2198
2571
  }
2199
2572
  function getContentScriptCssFiles(contentScripts, contentScriptCssMap) {
@@ -2211,7 +2584,7 @@ function getContentScriptCssFiles(contentScripts, contentScriptCssMap) {
2211
2584
  return css;
2212
2585
  return void 0;
2213
2586
  }
2214
- function getContentScriptCssWebAccessibleResources(config, contentScripts, contentScriptCssMap) {
2587
+ function getContentScriptCssWebAccessibleResources(contentScripts, contentScriptCssMap) {
2215
2588
  const resources = [];
2216
2589
  contentScripts.forEach((script) => {
2217
2590
  if (script.options.cssInjectionMode !== "ui")
@@ -2219,14 +2592,14 @@ function getContentScriptCssWebAccessibleResources(config, contentScripts, conte
2219
2592
  const cssFile = contentScriptCssMap[script.name];
2220
2593
  if (cssFile == null)
2221
2594
  return;
2222
- if (config.manifestVersion === 2) {
2595
+ if (wxt.config.manifestVersion === 2) {
2223
2596
  resources.push(cssFile);
2224
2597
  } else {
2225
2598
  resources.push({
2226
2599
  resources: [cssFile],
2227
2600
  matches: resolvePerBrowserOption(
2228
2601
  script.options.matches,
2229
- config.browser
2602
+ wxt.config.browser
2230
2603
  ).map((matchPattern) => stripPathFromMatchPattern(matchPattern))
2231
2604
  });
2232
2605
  }
@@ -2266,28 +2639,28 @@ function stripPathFromMatchPattern(pattern) {
2266
2639
  }
2267
2640
 
2268
2641
  // src/core/utils/building/rebuild.ts
2269
- async function rebuild(config, allEntrypoints, entrypointGroups, existingOutput = {
2642
+ async function rebuild(allEntrypoints, entrypointGroups, existingOutput = {
2270
2643
  steps: [],
2271
2644
  publicAssets: []
2272
2645
  }) {
2273
2646
  const { default: ora } = await import("ora");
2274
2647
  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")
2648
+ await generateTypesDir(allEntrypoints).catch((err) => {
2649
+ wxt.logger.warn("Failed to update .wxt directory:", err);
2650
+ if (wxt.config.command === "build")
2278
2651
  throw err;
2279
2652
  });
2280
- const newOutput = await buildEntrypoints(entrypointGroups, config, spinner);
2653
+ const newOutput = await buildEntrypoints(entrypointGroups, spinner);
2281
2654
  const mergedOutput = {
2282
2655
  steps: [...existingOutput.steps, ...newOutput.steps],
2283
2656
  publicAssets: [...existingOutput.publicAssets, ...newOutput.publicAssets]
2284
2657
  };
2285
- const { manifest: newManifest, warnings: manifestWarnings } = await generateManifest(allEntrypoints, mergedOutput, config);
2658
+ const { manifest: newManifest, warnings: manifestWarnings } = await generateManifest(allEntrypoints, mergedOutput);
2286
2659
  const finalOutput = {
2287
2660
  manifest: newManifest,
2288
2661
  ...newOutput
2289
2662
  };
2290
- await writeManifest(newManifest, finalOutput, config);
2663
+ await writeManifest(newManifest, finalOutput);
2291
2664
  spinner.clear().stop();
2292
2665
  return {
2293
2666
  output: {
@@ -2304,7 +2677,7 @@ async function rebuild(config, allEntrypoints, entrypointGroups, existingOutput
2304
2677
  }
2305
2678
 
2306
2679
  // src/core/utils/building/internal-build.ts
2307
- import { relative as relative5 } from "node:path";
2680
+ import { relative as relative6 } from "node:path";
2308
2681
 
2309
2682
  // src/core/utils/validation.ts
2310
2683
  function validateEntrypoints(entrypoints) {
@@ -2370,32 +2743,35 @@ import consola3 from "consola";
2370
2743
 
2371
2744
  // src/core/utils/exec.ts
2372
2745
  import managePath from "manage-path";
2373
- import { resolve as resolve12 } from "node:path";
2746
+ import { resolve as resolve13 } from "node:path";
2374
2747
  var managedPath = managePath(process.env);
2375
- var exec = async (config, file, args, options) => {
2748
+ var exec = async (file, args, options) => {
2376
2749
  managedPath.restore();
2377
- managedPath.push(resolve12(config.root, "node_modules/wxt/node_modules/.bin"));
2750
+ managedPath.push(
2751
+ resolve13(wxt.config.root, "node_modules/wxt/node_modules/.bin")
2752
+ );
2378
2753
  const { execa } = await import("./execa-4F7CCWCA.js");
2379
2754
  return await execa(file, args, options);
2380
2755
  };
2381
2756
 
2382
2757
  // 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}`
2758
+ async function internalBuild() {
2759
+ await wxt.hooks.callHook("build:before", wxt);
2760
+ const verb = wxt.config.command === "serve" ? "Pre-rendering" : "Building";
2761
+ const target = `${wxt.config.browser}-mv${wxt.config.manifestVersion}`;
2762
+ wxt.logger.info(
2763
+ `${verb} ${pc5.cyan(target)} for ${pc5.cyan(wxt.config.mode)} with ${pc5.green(
2764
+ `${wxt.config.builder.name} ${wxt.config.builder.version}`
2389
2765
  )}`
2390
2766
  );
2391
2767
  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);
2768
+ await fs12.rm(wxt.config.outDir, { recursive: true, force: true });
2769
+ await fs12.ensureDir(wxt.config.outDir);
2770
+ const entrypoints = await findEntrypoints();
2771
+ wxt.logger.debug("Detected entrypoints:", entrypoints);
2396
2772
  const validationResults = validateEntrypoints(entrypoints);
2397
2773
  if (validationResults.errorCount + validationResults.warningCount > 0) {
2398
- printValidationResults(config, validationResults);
2774
+ printValidationResults(validationResults);
2399
2775
  }
2400
2776
  if (validationResults.errorCount > 0) {
2401
2777
  throw new ValidationError(`Entrypoint validation failed`, {
@@ -2403,45 +2779,44 @@ async function internalBuild(config) {
2403
2779
  });
2404
2780
  }
2405
2781
  const groups = groupEntrypoints(entrypoints);
2406
- const { output, warnings } = await rebuild(
2407
- config,
2408
- entrypoints,
2409
- groups,
2410
- void 0
2411
- );
2782
+ await wxt.hooks.callHook("entrypoints:grouped", wxt, groups);
2783
+ const { output, warnings } = await rebuild(entrypoints, groups, void 0);
2784
+ await wxt.hooks.callHook("build:done", wxt, output);
2412
2785
  await printBuildSummary(
2413
- config.logger.success,
2786
+ wxt.logger.success,
2414
2787
  `Built extension in ${formatDuration(Date.now() - startTime)}`,
2415
- output,
2416
- config
2788
+ output
2417
2789
  );
2418
2790
  for (const warning of warnings) {
2419
- config.logger.warn(...warning);
2791
+ wxt.logger.warn(...warning);
2420
2792
  }
2421
- if (config.analysis.enabled) {
2422
- await combineAnalysisStats(config);
2423
- config.logger.info(
2793
+ if (wxt.config.analysis.enabled) {
2794
+ await combineAnalysisStats();
2795
+ wxt.logger.info(
2424
2796
  `Analysis complete:
2425
- ${pc4.gray("\u2514\u2500")} ${pc4.yellow("stats.html")}`
2797
+ ${pc5.gray("\u2514\u2500")} ${pc5.yellow("stats.html")}`
2426
2798
  );
2427
2799
  }
2428
2800
  return output;
2429
2801
  }
2430
- async function combineAnalysisStats(config) {
2431
- const unixFiles = await glob2(`stats-*.json`, {
2432
- cwd: config.outDir,
2802
+ async function combineAnalysisStats() {
2803
+ const unixFiles = await glob3(`stats-*.json`, {
2804
+ cwd: wxt.config.outDir,
2433
2805
  absolute: true
2434
2806
  });
2435
2807
  const absolutePaths = unixFiles.map(unnormalizePath);
2436
2808
  await exec(
2437
- config,
2438
2809
  "rollup-plugin-visualizer",
2439
- [...absolutePaths, "--template", config.analysis.template],
2440
- { cwd: config.root, stdio: "inherit" }
2810
+ [...absolutePaths, "--template", wxt.config.analysis.template],
2811
+ { cwd: wxt.config.root, stdio: "inherit" }
2441
2812
  );
2442
2813
  }
2443
- function printValidationResults(config, { errorCount, errors, warningCount }) {
2444
- (errorCount > 0 ? config.logger.error : config.logger.warn)(
2814
+ function printValidationResults({
2815
+ errorCount,
2816
+ errors,
2817
+ warningCount
2818
+ }) {
2819
+ (errorCount > 0 ? wxt.logger.error : wxt.logger.warn)(
2445
2820
  `Entrypoint validation failed: ${errorCount} error${errorCount === 1 ? "" : "s"}, ${warningCount} warning${warningCount === 1 ? "" : "s"}`
2446
2821
  );
2447
2822
  const cwd = process.cwd();
@@ -2452,355 +2827,40 @@ function printValidationResults(config, { errorCount, errors, warningCount }) {
2452
2827
  return map;
2453
2828
  }, /* @__PURE__ */ new Map());
2454
2829
  Array.from(entrypointErrors.entries()).forEach(([entrypoint, errors2]) => {
2455
- consola3.log(relative5(cwd, entrypoint.inputPath));
2830
+ consola3.log(relative6(cwd, entrypoint.inputPath));
2456
2831
  console.log();
2457
2832
  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)})`);
2833
+ const type = err.type === "error" ? pc5.red("ERROR") : pc5.yellow("WARN");
2834
+ const recieved = pc5.dim(`(recieved: ${JSON.stringify(err.value)})`);
2460
2835
  consola3.log(` - ${type} ${err.message} ${recieved}`);
2461
2836
  });
2462
2837
  console.log();
2463
2838
  });
2464
2839
  }
2465
2840
 
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;
2841
+ // src/core/wxt.ts
2842
+ import { createHooks } from "hookable";
2843
+ var wxt;
2844
+ async function registerWxt(command, inlineConfig = {}, server) {
2845
+ const config = await resolveConfig(inlineConfig, command, server);
2846
+ const hooks = createHooks();
2847
+ wxt = {
2848
+ config,
2849
+ hooks,
2850
+ get logger() {
2851
+ return config.logger;
2593
2852
  },
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
- );
2853
+ async reloadConfig() {
2854
+ wxt.config = await resolveConfig(inlineConfig, command, server);
2726
2855
  }
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
- };
2745
- }
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
2856
  };
2857
+ wxt.hooks.addHooks(config.hooks);
2858
+ await wxt.hooks.callHook("ready", wxt);
2761
2859
  }
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
2860
 
2803
2861
  export {
2862
+ wxt,
2863
+ registerWxt,
2804
2864
  detectDevChanges,
2805
2865
  getEntrypointBundlePath,
2806
2866
  resolvePerBrowserOption,
@@ -2812,7 +2872,7 @@ export {
2812
2872
  tsconfigPaths,
2813
2873
  globals,
2814
2874
  webextensionPolyfillMock,
2815
- getInternalConfig,
2875
+ resolveConfig,
2816
2876
  kebabCaseAlphanumeric,
2817
2877
  printFileList,
2818
2878
  version,