wxt 0.14.2-alpha2 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import "./chunk-VBXJIVYU.js";
4
4
  import cac from "cac";
5
5
 
6
6
  // package.json
7
- var version = "0.14.2-alpha2";
7
+ var version = "0.14.2";
8
8
 
9
9
  // src/core/utils/fs.ts
10
10
  import fs from "fs-extra";
@@ -13,11 +13,11 @@ import glob from "fast-glob";
13
13
  // src/core/utils/paths.ts
14
14
  import systemPath from "node:path";
15
15
  import normalize from "normalize-path";
16
- function normalizePath(path6) {
17
- return normalize(path6);
16
+ function normalizePath(path7) {
17
+ return normalize(path7);
18
18
  }
19
- function unnormalizePath(path6) {
20
- return systemPath.normalize(path6);
19
+ function unnormalizePath(path7) {
20
+ return systemPath.normalize(path7);
21
21
  }
22
22
  var CSS_EXTENSIONS = ["css", "scss", "sass", "less", "styl", "stylus"];
23
23
  var CSS_EXTENSIONS_PATTERN = `+(${CSS_EXTENSIONS.join("|")})`;
@@ -38,145 +38,8 @@ async function getPublicFiles(config) {
38
38
 
39
39
  // src/core/utils/building/build-entrypoints.ts
40
40
  import fs2 from "fs-extra";
41
- import { dirname, resolve, extname } from "node:path";
41
+ import { dirname, resolve } from "path";
42
42
  import pc from "picocolors";
43
-
44
- // src/i18n/node.ts
45
- import { readFile } from "node:fs/promises";
46
- import JSON5 from "json5";
47
- import YAML from "yaml";
48
- async function readMessagesFile(file) {
49
- const text = await readFile(file, "utf-8");
50
- return readMessagesText(text);
51
- }
52
- function readMessagesText(text) {
53
- const parsers = [
54
- JSON.parse,
55
- JSON5.parse,
56
- YAML.parse
57
- ];
58
- for (const parse of parsers) {
59
- try {
60
- const result = parse(text);
61
- if (typeof result === "object") {
62
- return readMessagesObject(result);
63
- }
64
- } catch {
65
- continue;
66
- }
67
- }
68
- throw Error("I18n messages text is not valid JSON, JSON5, or YAML");
69
- }
70
- function readMessagesObject(input) {
71
- const messagesFromInput = findEntries([], input);
72
- return [...messagesFromInput, ...PREDEFINED_MESSAGES];
73
- }
74
- function convertMessagesToManifest(messages) {
75
- return messages.filter((message) => !message.isBuiltin).reduce((schema, { name, entry }) => {
76
- schema[name] = entry;
77
- return schema;
78
- }, {});
79
- }
80
- function findEntries(keyPath, input) {
81
- const name = keyPath.join("_");
82
- if (isBasicEntry(input))
83
- return [
84
- {
85
- name,
86
- entry: { message: input }
87
- }
88
- ];
89
- if (isManifestEntry(input))
90
- return [
91
- {
92
- name,
93
- entry: input
94
- }
95
- ];
96
- if (isPluralEntry(input))
97
- return [
98
- {
99
- name,
100
- entry: {
101
- message: Object.values(input).join(" | ")
102
- },
103
- isPlural: true
104
- }
105
- ];
106
- return Object.entries(input).reduce((items, [key, child]) => {
107
- const nestedEntries = findEntries(keyPath.concat(key), child);
108
- return [...items, ...nestedEntries];
109
- }, []);
110
- }
111
- function isBasicEntry(entry) {
112
- return typeof entry === "string";
113
- }
114
- function isManifestEntry(entry) {
115
- const keys = Object.keys(entry);
116
- if (keys.length < 1 || keys.length > 3)
117
- return false;
118
- const knownKeys = /* @__PURE__ */ new Set(["message", "placeholders", "description"]);
119
- const unknownKeys = keys.filter((key) => !knownKeys.has(key));
120
- return unknownKeys.length === 0;
121
- }
122
- function isPluralEntry(entry) {
123
- const keys = Object.keys(entry);
124
- if (keys.length === 0)
125
- return false;
126
- const invalidKeys = keys.filter((key) => key !== "n" && isNaN(Number(key)));
127
- return invalidKeys.length === 0;
128
- }
129
- var PREDEFINED_MESSAGES = [
130
- {
131
- name: "@@extension_id",
132
- isBuiltin: true,
133
- entry: {
134
- message: "<browser.runtime.id>",
135
- description: "The extension or app ID; you might use this string to construct URLs for resources inside the extension. Even unlocalized extensions can use this message.\nNote: You can't use this message in a manifest file."
136
- }
137
- },
138
- {
139
- name: "@@ui_locale",
140
- isBuiltin: true,
141
- entry: {
142
- message: "<browser.i18n.getUiLocale()>"
143
- }
144
- },
145
- {
146
- name: "@@bidi_dir",
147
- isBuiltin: true,
148
- entry: {
149
- message: "<ltr|rtl>",
150
- description: 'The text direction for the current locale, either "ltr" for left-to-right languages such as English or "rtl" for right-to-left languages such as Japanese.'
151
- }
152
- },
153
- {
154
- name: "@@bidi_reversed_dir",
155
- isBuiltin: true,
156
- entry: {
157
- message: "<rtl|ltr>",
158
- description: `If the @@bidi_dir is "ltr", then this is "rtl"; otherwise, it's "ltr".`
159
- }
160
- },
161
- {
162
- name: "@@bidi_start_edge",
163
- isBuiltin: true,
164
- entry: {
165
- message: "<left|right>",
166
- description: `If the @@bidi_dir is "ltr", then this is "left"; otherwise, it's "right".`
167
- }
168
- },
169
- {
170
- name: "@@bidi_end_edge",
171
- isBuiltin: true,
172
- entry: {
173
- message: "<right|left>",
174
- description: `If the @@bidi_dir is "ltr", then this is "right"; otherwise, it's "left".`
175
- }
176
- }
177
- ];
178
-
179
- // src/core/utils/building/build-entrypoints.ts
180
43
  async function buildEntrypoints(groups, config, spinner) {
181
44
  const steps = [];
182
45
  for (let i = 0; i < groups.length; i++) {
@@ -185,10 +48,7 @@ async function buildEntrypoints(groups, config, spinner) {
185
48
  spinner.text = pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNames}`;
186
49
  steps.push(await config.builder.build(group));
187
50
  }
188
- const publicAssets = (await Promise.all([
189
- copyPublicDirectory(config),
190
- copyLocalesDirectory(config)
191
- ])).flat();
51
+ const publicAssets = await copyPublicDirectory(config);
192
52
  return { publicAssets, steps };
193
53
  }
194
54
  async function copyPublicDirectory(config) {
@@ -208,28 +68,6 @@ async function copyPublicDirectory(config) {
208
68
  }
209
69
  return publicAssets;
210
70
  }
211
- async function copyLocalesDirectory(config) {
212
- const localesExist = await fs2.exists(config.localesDir);
213
- if (!localesExist || config.manifest.default_locale == null)
214
- return [];
215
- const files = await fs2.readdir(config.localesDir);
216
- return await Promise.all(
217
- files.map(async (file) => {
218
- const locale = file.replace(extname(file), "");
219
- const fileName = unnormalizePath(`_locales/${locale}/messages.json`);
220
- const srcPath = resolve(config.localesDir, file);
221
- const outPath = resolve(config.outDir, fileName);
222
- const messages = await readMessagesFile(srcPath);
223
- const json = convertMessagesToManifest(messages);
224
- await fs2.ensureDir(dirname(outPath));
225
- await fs2.writeJson(outPath, json);
226
- return {
227
- fileName,
228
- type: "asset"
229
- };
230
- })
231
- );
232
- }
233
71
 
234
72
  // src/core/utils/arrays.ts
235
73
  function every(array, predicate) {
@@ -328,7 +166,7 @@ import { relative as relative2, resolve as resolve3 } from "path";
328
166
  import fs3 from "fs-extra";
329
167
  import { minimatch } from "minimatch";
330
168
  import { parseHTML } from "linkedom";
331
- import JSON52 from "json5";
169
+ import JSON5 from "json5";
332
170
  import glob2 from "fast-glob";
333
171
 
334
172
  // src/core/utils/entrypoints.ts
@@ -356,6 +194,7 @@ function resolvePerBrowserOption(option, browser) {
356
194
  var VIRTUAL_NOOP_BACKGROUND_MODULE_ID = "virtual:user-background";
357
195
 
358
196
  // src/core/utils/building/find-entrypoints.ts
197
+ import pc2 from "picocolors";
359
198
  async function findEntrypoints(config) {
360
199
  const relativePaths = await glob2(Object.keys(PATH_GLOB_TO_TYPE_MAP), {
361
200
  cwd: config.entrypointsDir
@@ -366,11 +205,16 @@ async function findEntrypoints(config) {
366
205
  const inputPath = resolve3(config.entrypointsDir, relativePath);
367
206
  const name = getEntrypointName(config.entrypointsDir, inputPath);
368
207
  const matchingGlob = pathGlobs.find(
369
- (glob6) => minimatch(relativePath, glob6)
208
+ (glob5) => minimatch(relativePath, glob5)
370
209
  );
371
210
  if (matchingGlob) {
372
211
  const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
373
- results.push({ name, inputPath, type });
212
+ results.push({
213
+ name,
214
+ inputPath,
215
+ type,
216
+ skipped: config.filterEntrypoints != null && !config.filterEntrypoints.has(name)
217
+ });
374
218
  }
375
219
  return results;
376
220
  }, []);
@@ -422,11 +266,19 @@ async function findEntrypoints(config) {
422
266
  await getBackgroundEntrypoint(config, {
423
267
  inputPath: VIRTUAL_NOOP_BACKGROUND_MODULE_ID,
424
268
  name: "background",
425
- type: "background"
269
+ type: "background",
270
+ skipped: false
426
271
  })
427
272
  );
428
273
  }
429
274
  config.logger.debug("All entrypoints:", entrypoints);
275
+ const skippedEntrypointNames = entrypointInfos.filter((item) => item.skipped).map((item) => item.name);
276
+ if (skippedEntrypointNames.length) {
277
+ config.logger.warn(
278
+ `Filter excluded the following entrypoints:
279
+ ${skippedEntrypointNames.map((item) => `${pc2.dim("-")} ${pc2.cyan(item)}`).join("\n")}`
280
+ );
281
+ }
430
282
  const targetEntrypoints = entrypoints.filter((entry) => {
431
283
  const { include, exclude } = entry.options;
432
284
  if (include?.length && exclude?.length) {
@@ -441,6 +293,9 @@ async function findEntrypoints(config) {
441
293
  if (include?.length && !exclude?.length) {
442
294
  return include.includes(config.browser);
443
295
  }
296
+ if (skippedEntrypointNames.includes(entry.name)) {
297
+ return false;
298
+ }
444
299
  return true;
445
300
  });
446
301
  config.logger.debug(`${config.browser} entrypoints:`, targetEntrypoints);
@@ -485,15 +340,15 @@ function getHtmlBaseOptions(document) {
485
340
  const options = {};
486
341
  const includeContent = document.querySelector("meta[name='manifest.include']")?.getAttribute("content");
487
342
  if (includeContent) {
488
- options.include = JSON52.parse(includeContent);
343
+ options.include = JSON5.parse(includeContent);
489
344
  }
490
345
  const excludeContent = document.querySelector("meta[name='manifest.exclude']")?.getAttribute("content");
491
346
  if (excludeContent) {
492
- options.exclude = JSON52.parse(excludeContent);
347
+ options.exclude = JSON5.parse(excludeContent);
493
348
  }
494
349
  return options;
495
350
  }
496
- async function getPopupEntrypoint(config, { inputPath, name }) {
351
+ async function getPopupEntrypoint(config, { inputPath, name, skipped }) {
497
352
  const content = await fs3.readFile(inputPath, "utf-8");
498
353
  const { document } = parseHTML(content);
499
354
  const options = getHtmlBaseOptions(document);
@@ -503,7 +358,7 @@ async function getPopupEntrypoint(config, { inputPath, name }) {
503
358
  const defaultIconContent = document.querySelector("meta[name='manifest.default_icon']")?.getAttribute("content");
504
359
  if (defaultIconContent) {
505
360
  try {
506
- options.defaultIcon = JSON52.parse(defaultIconContent);
361
+ options.defaultIcon = JSON5.parse(defaultIconContent);
507
362
  } catch (err) {
508
363
  config.logger.fatal(
509
364
  `Failed to parse default_icon meta tag content as JSON5. content=${defaultIconContent}`,
@@ -524,10 +379,11 @@ async function getPopupEntrypoint(config, { inputPath, name }) {
524
379
  name: "popup",
525
380
  options,
526
381
  inputPath,
527
- outputDir: config.outDir
382
+ outputDir: config.outDir,
383
+ skipped
528
384
  };
529
385
  }
530
- async function getOptionsEntrypoint(config, { inputPath, name }) {
386
+ async function getOptionsEntrypoint(config, { inputPath, name, skipped }) {
531
387
  const content = await fs3.readFile(inputPath, "utf-8");
532
388
  const { document } = parseHTML(content);
533
389
  const options = getHtmlBaseOptions(document);
@@ -548,10 +404,11 @@ async function getOptionsEntrypoint(config, { inputPath, name }) {
548
404
  name: "options",
549
405
  options,
550
406
  inputPath,
551
- outputDir: config.outDir
407
+ outputDir: config.outDir,
408
+ skipped
552
409
  };
553
410
  }
554
- async function getUnlistedPageEntrypoint(config, { inputPath, name }) {
411
+ async function getUnlistedPageEntrypoint(config, { inputPath, name, skipped }) {
555
412
  const content = await fs3.readFile(inputPath, "utf-8");
556
413
  const { document } = parseHTML(content);
557
414
  return {
@@ -559,10 +416,11 @@ async function getUnlistedPageEntrypoint(config, { inputPath, name }) {
559
416
  name: getEntrypointName(config.entrypointsDir, inputPath),
560
417
  inputPath,
561
418
  outputDir: config.outDir,
562
- options: getHtmlBaseOptions(document)
419
+ options: getHtmlBaseOptions(document),
420
+ skipped
563
421
  };
564
422
  }
565
- async function getUnlistedScriptEntrypoint(config, { inputPath, name }) {
423
+ async function getUnlistedScriptEntrypoint(config, { inputPath, name, skipped }) {
566
424
  const defaultExport = await importEntrypointFile(
567
425
  inputPath,
568
426
  config
@@ -579,10 +437,11 @@ async function getUnlistedScriptEntrypoint(config, { inputPath, name }) {
579
437
  name,
580
438
  inputPath,
581
439
  outputDir: config.outDir,
582
- options
440
+ options,
441
+ skipped
583
442
  };
584
443
  }
585
- async function getBackgroundEntrypoint(config, { inputPath, name }) {
444
+ async function getBackgroundEntrypoint(config, { inputPath, name, skipped }) {
586
445
  let options = {};
587
446
  if (inputPath !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
588
447
  const defaultExport = await importEntrypointFile(
@@ -606,10 +465,11 @@ async function getBackgroundEntrypoint(config, { inputPath, name }) {
606
465
  ...options,
607
466
  type: resolvePerBrowserOption(options.type, config.browser),
608
467
  persistent: resolvePerBrowserOption(options.persistent, config.browser)
609
- }
468
+ },
469
+ skipped
610
470
  };
611
471
  }
612
- async function getContentScriptEntrypoint(config, { inputPath, name }) {
472
+ async function getContentScriptEntrypoint(config, { inputPath, name, skipped }) {
613
473
  const { main: _, ...options } = await importEntrypointFile(inputPath, config);
614
474
  if (options == null) {
615
475
  throw Error(
@@ -621,7 +481,8 @@ async function getContentScriptEntrypoint(config, { inputPath, name }) {
621
481
  name,
622
482
  inputPath,
623
483
  outputDir: resolve3(config.outDir, CONTENT_SCRIPT_OUT_DIR),
624
- options
484
+ options,
485
+ skipped
625
486
  };
626
487
  }
627
488
  var PATH_GLOB_TO_TYPE_MAP = {
@@ -679,8 +540,7 @@ function getUnimportOptions(config) {
679
540
  debugLog: config.logger.debug,
680
541
  imports: [
681
542
  { name: "defineConfig", from: "wxt" },
682
- { name: "fakeBrowser", from: "wxt/testing" },
683
- { name: "i18n", from: "wxt/i18n" }
543
+ { name: "fakeBrowser", from: "wxt/testing" }
684
544
  ],
685
545
  presets: [
686
546
  { package: "wxt/client" },
@@ -753,7 +613,46 @@ function surroundInUnderscore(name) {
753
613
  }
754
614
 
755
615
  // src/core/utils/building/generate-wxt-dir.ts
756
- import glob3 from "fast-glob";
616
+ import path2 from "node:path";
617
+
618
+ // src/core/utils/i18n.ts
619
+ var predefinedMessages = {
620
+ "@@extension_id": {
621
+ message: "<browser.runtime.id>",
622
+ description: "The extension or app ID; you might use this string to construct URLs for resources inside the extension. Even unlocalized extensions can use this message.\nNote: You can't use this message in a manifest file."
623
+ },
624
+ "@@ui_locale": {
625
+ message: "<browser.i18n.getUiLocale()>",
626
+ description: ""
627
+ },
628
+ "@@bidi_dir": {
629
+ message: "<ltr|rtl>",
630
+ description: 'The text direction for the current locale, either "ltr" for left-to-right languages such as English or "rtl" for right-to-left languages such as Japanese.'
631
+ },
632
+ "@@bidi_reversed_dir": {
633
+ message: "<rtl|ltr>",
634
+ description: `If the @@bidi_dir is "ltr", then this is "rtl"; otherwise, it's "ltr".`
635
+ },
636
+ "@@bidi_start_edge": {
637
+ message: "<left|right>",
638
+ description: `If the @@bidi_dir is "ltr", then this is "left"; otherwise, it's "right".`
639
+ },
640
+ "@@bidi_end_edge": {
641
+ message: "<right|left>",
642
+ description: `If the @@bidi_dir is "ltr", then this is "right"; otherwise, it's "left".`
643
+ }
644
+ };
645
+ function parseI18nMessages(messagesJson) {
646
+ return Object.entries({
647
+ ...predefinedMessages,
648
+ ...messagesJson
649
+ }).map(([name, details]) => ({
650
+ name,
651
+ ...details
652
+ }));
653
+ }
654
+
655
+ // src/core/utils/building/generate-wxt-dir.ts
757
656
  async function generateTypesDir(entrypoints, config) {
758
657
  await fs4.ensureDir(config.typesDir);
759
658
  const references = [];
@@ -787,15 +686,17 @@ async function writePathsDeclarationFile(entrypoints, config) {
787
686
  config.outDir,
788
687
  entry.inputPath.endsWith(".html") ? ".html" : ".js"
789
688
  )
790
- ).concat(await getPublicFiles(config)).map(normalizePath).map((path6) => ` | "/${path6}"`).sort().join("\n");
689
+ ).concat(await getPublicFiles(config)).map(normalizePath).map((path7) => ` | "/${path7}"`).sort().join("\n");
791
690
  const template = `// Generated by wxt
792
691
  import "wxt/browser";
793
692
 
794
693
  declare module "wxt/browser" {
795
694
  export type PublicPath =
796
695
  {{ union }}
696
+ type HtmlPublicPath = Extract<PublicPath, \`\${string}.html\`>
797
697
  export interface WxtRuntime extends Runtime.Static {
798
698
  getURL(path: PublicPath): string;
699
+ getURL(path: \`\${HtmlPublicPath}\${string}\`): string;
799
700
  }
800
701
  }
801
702
  `;
@@ -823,36 +724,28 @@ declare module "wxt/browser" {
823
724
  }
824
725
 
825
726
  export interface WxtI18n extends I18n.Static {
826
- {{ browserOverrides }}
827
- }
828
- }
829
-
830
- declare module "wxt/i18n" {
831
- export interface WxtMessageSchema {
832
- t: {
833
- {{ translationTOverrides }}
834
- };
835
- tp: {
836
- {{ translationTpOverrides }}
837
- };
727
+ {{ overrides }}
838
728
  }
839
729
  }
840
730
  `;
841
731
  let messages;
842
732
  if (defaultLocale) {
843
- const [defaultLocalePath] = await glob3(`${defaultLocale}.*`, {
844
- cwd: config.localesDir,
845
- absolute: true
846
- });
847
- messages = await readMessagesFile(defaultLocalePath);
733
+ const defaultLocalePath = path2.resolve(
734
+ config.publicDir,
735
+ "_locales",
736
+ defaultLocale,
737
+ "messages.json"
738
+ );
739
+ const content = JSON.parse(await fs4.readFile(defaultLocalePath, "utf-8"));
740
+ messages = parseI18nMessages(content);
848
741
  } else {
849
- messages = PREDEFINED_MESSAGES;
742
+ messages = parseI18nMessages({});
850
743
  }
851
744
  const overrides = messages.map((message) => {
852
745
  return ` /**
853
- * ${message.entry.description ?? "No message description."}
746
+ * ${message.description ?? "No message description."}
854
747
  *
855
- * "${message.entry.message}"
748
+ * "${message.message}"
856
749
  */
857
750
  getMessage(
858
751
  messageName: "${message.name}",
@@ -862,13 +755,7 @@ declare module "wxt/i18n" {
862
755
  });
863
756
  await writeFileIfDifferent(
864
757
  filePath,
865
- template.replace("{{ browserOverrides }}", overrides.join("\n")).replace(
866
- "{{ translationTOverrides }}",
867
- messages.filter((message) => !message.isPlural).map((message) => ` "${message.name}": any;`).join("\n")
868
- ).replace(
869
- "{{ translationTpOverrides }}",
870
- messages.filter((message) => message.isPlural).map((message) => ` "${message.name}": any;`).join("\n")
871
- )
758
+ template.replace("{{ overrides }}", overrides.join("\n"))
872
759
  );
873
760
  return filePath;
874
761
  }
@@ -904,7 +791,7 @@ async function writeMainDeclarationFile(references, config) {
904
791
  }
905
792
  async function writeTsConfigFile(mainReference, config) {
906
793
  const dir = config.wxtDir;
907
- const getTsconfigPath = (path6) => normalizePath(relative3(dir, path6));
794
+ const getTsconfigPath = (path7) => normalizePath(relative3(dir, path7));
908
795
  const paths = Object.entries(config.alias).flatMap(([alias, absolutePath]) => {
909
796
  const aliasPath = getTsconfigPath(absolutePath);
910
797
  return [
@@ -940,7 +827,7 @@ ${paths}
940
827
 
941
828
  // src/core/utils/building/get-internal-config.ts
942
829
  import { loadConfig } from "c12";
943
- import path2 from "node:path";
830
+ import path3 from "node:path";
944
831
 
945
832
  // src/core/utils/cache.ts
946
833
  import fs5, { ensureDir } from "fs-extra";
@@ -949,14 +836,14 @@ function createFsCache(wxtDir) {
949
836
  const getPath = (key) => resolve5(wxtDir, "cache", encodeURIComponent(key));
950
837
  return {
951
838
  async set(key, value) {
952
- const path6 = getPath(key);
953
- await ensureDir(dirname2(path6));
954
- await writeFileIfDifferent(path6, value);
839
+ const path7 = getPath(key);
840
+ await ensureDir(dirname2(path7));
841
+ await writeFileIfDifferent(path7, value);
955
842
  },
956
843
  async get(key) {
957
- const path6 = getPath(key);
844
+ const path7 = getPath(key);
958
845
  try {
959
- return await fs5.readFile(path6, "utf-8");
846
+ return await fs5.readFile(path7, "utf-8");
960
847
  } catch {
961
848
  return void 0;
962
849
  }
@@ -1178,7 +1065,7 @@ function download(config) {
1178
1065
  }
1179
1066
 
1180
1067
  // src/core/builders/vite/plugins/multipageMove.ts
1181
- import { dirname as dirname4, extname as extname2, resolve as resolve7, join } from "node:path";
1068
+ import { dirname as dirname4, extname, resolve as resolve7, join } from "node:path";
1182
1069
  import fs6, { ensureDir as ensureDir2 } from "fs-extra";
1183
1070
  function multipageMove(entrypoints, config) {
1184
1071
  return {
@@ -1197,7 +1084,7 @@ function multipageMove(entrypoints, config) {
1197
1084
  const newBundlePath = getEntrypointBundlePath(
1198
1085
  entrypoint,
1199
1086
  config.outDir,
1200
- extname2(oldBundlePath)
1087
+ extname(oldBundlePath)
1201
1088
  );
1202
1089
  if (newBundlePath === oldBundlePath) {
1203
1090
  config.logger.debug(
@@ -1238,7 +1125,7 @@ async function removeEmptyDirs(dir) {
1238
1125
 
1239
1126
  // src/core/builders/vite/plugins/unimport.ts
1240
1127
  import { createUnimport as createUnimport2 } from "unimport";
1241
- import { extname as extname3 } from "path";
1128
+ import { extname as extname2 } from "path";
1242
1129
  var ENABLED_EXTENSIONS = /* @__PURE__ */ new Set([
1243
1130
  ".js",
1244
1131
  ".jsx",
@@ -1260,7 +1147,7 @@ function unimport(config) {
1260
1147
  async transform(code, id) {
1261
1148
  if (id.includes("node_modules"))
1262
1149
  return;
1263
- if (!ENABLED_EXTENSIONS.has(extname3(id)))
1150
+ if (!ENABLED_EXTENSIONS.has(extname2(id)))
1264
1151
  return;
1265
1152
  return unimport2.injectImports(code, id);
1266
1153
  }
@@ -1652,20 +1539,20 @@ async function getInternalConfig(inlineConfig, command, server) {
1652
1539
  const manifestVersion = mergedConfig.manifestVersion ?? (browser === "firefox" || browser === "safari" ? 2 : 3);
1653
1540
  const mode = mergedConfig.mode ?? (command === "build" ? "production" : "development");
1654
1541
  const env = { browser, command, manifestVersion, mode };
1655
- const root = path2.resolve(
1542
+ const root = path3.resolve(
1656
1543
  inlineConfig.root ?? userConfig.root ?? process.cwd()
1657
1544
  );
1658
- const wxtDir = path2.resolve(root, ".wxt");
1659
- const srcDir = path2.resolve(root, mergedConfig.srcDir ?? root);
1660
- const entrypointsDir = path2.resolve(
1545
+ const wxtDir = path3.resolve(root, ".wxt");
1546
+ const srcDir = path3.resolve(root, mergedConfig.srcDir ?? root);
1547
+ const entrypointsDir = path3.resolve(
1661
1548
  srcDir,
1662
1549
  mergedConfig.entrypointsDir ?? "entrypoints"
1663
1550
  );
1664
- const publicDir = path2.resolve(srcDir, mergedConfig.publicDir ?? "public");
1665
- const localesDir = path2.resolve(srcDir, mergedConfig.localesDir ?? "locales");
1666
- const typesDir = path2.resolve(wxtDir, "types");
1667
- const outBaseDir = path2.resolve(root, mergedConfig.outDir ?? ".output");
1668
- const outDir = path2.resolve(outBaseDir, `${browser}-mv${manifestVersion}`);
1551
+ const filterEntrypoints = !!mergedConfig.filterEntrypoints?.length ? new Set(mergedConfig.filterEntrypoints) : void 0;
1552
+ const publicDir = path3.resolve(srcDir, mergedConfig.publicDir ?? "public");
1553
+ const typesDir = path3.resolve(wxtDir, "types");
1554
+ const outBaseDir = path3.resolve(root, mergedConfig.outDir ?? ".output");
1555
+ const outDir = path3.resolve(outBaseDir, `${browser}-mv${manifestVersion}`);
1669
1556
  const runnerConfig = await loadConfig({
1670
1557
  name: "web-ext",
1671
1558
  cwd: root,
@@ -1681,13 +1568,14 @@ async function getInternalConfig(inlineConfig, command, server) {
1681
1568
  "~": srcDir,
1682
1569
  "@@": root,
1683
1570
  "~~": root
1684
- }).map(([key, value]) => [key, path2.resolve(root, value)])
1571
+ }).map(([key, value]) => [key, path3.resolve(root, value)])
1685
1572
  );
1686
1573
  const finalConfig = {
1687
1574
  browser,
1688
1575
  command,
1689
1576
  debug,
1690
1577
  entrypointsDir,
1578
+ filterEntrypoints,
1691
1579
  env,
1692
1580
  fsCache: createFsCache(wxtDir),
1693
1581
  imports: mergedConfig.imports ?? {},
@@ -1698,7 +1586,6 @@ async function getInternalConfig(inlineConfig, command, server) {
1698
1586
  outBaseDir,
1699
1587
  outDir,
1700
1588
  publicDir,
1701
- localesDir,
1702
1589
  root,
1703
1590
  runnerConfig,
1704
1591
  srcDir,
@@ -1762,12 +1649,12 @@ function mergeInlineConfig(inlineConfig, userConfig) {
1762
1649
  configFile: inlineConfig.configFile,
1763
1650
  debug: inlineConfig.debug ?? userConfig.debug,
1764
1651
  entrypointsDir: inlineConfig.entrypointsDir ?? userConfig.entrypointsDir,
1652
+ filterEntrypoints: inlineConfig.filterEntrypoints ?? userConfig.filterEntrypoints,
1765
1653
  imports,
1766
1654
  logger: inlineConfig.logger ?? userConfig.logger,
1767
1655
  manifest,
1768
1656
  mode: inlineConfig.mode ?? userConfig.mode,
1769
1657
  publicDir: inlineConfig.publicDir ?? userConfig.publicDir,
1770
- localesDir: inlineConfig.localesDir ?? userConfig.localesDir,
1771
1658
  runner,
1772
1659
  srcDir: inlineConfig.srcDir ?? userConfig.srcDir,
1773
1660
  outDir: inlineConfig.outDir ?? userConfig.outDir,
@@ -1850,7 +1737,7 @@ var ENTRY_TYPE_TO_GROUP_MAP = {
1850
1737
  import createJITI from "jiti";
1851
1738
  import { createUnimport as createUnimport3 } from "unimport";
1852
1739
  import fs8 from "fs-extra";
1853
- import { resolve as resolve9 } from "node:path";
1740
+ import { relative as relative5, resolve as resolve9 } from "node:path";
1854
1741
 
1855
1742
  // src/core/utils/strings.ts
1856
1743
  function kebabCaseAlphanumeric(str) {
@@ -1872,16 +1759,16 @@ ${noImports}`;
1872
1759
  // src/core/utils/building/import-entrypoint.ts
1873
1760
  import { transformSync } from "esbuild";
1874
1761
  import { fileURLToPath } from "node:url";
1875
- async function importEntrypointFile(path6, config) {
1876
- config.logger.debug("Loading file metadata:", path6);
1877
- const normalPath = normalizePath(path6);
1762
+ async function importEntrypointFile(path7, config) {
1763
+ config.logger.debug("Loading file metadata:", path7);
1764
+ const normalPath = normalizePath(path7);
1878
1765
  const unimport2 = createUnimport3({
1879
1766
  ...getUnimportOptions(config),
1880
1767
  // Only allow specific imports, not all from the project
1881
1768
  dirs: []
1882
1769
  });
1883
1770
  await unimport2.init();
1884
- const text = await fs8.readFile(path6, "utf-8");
1771
+ const text = await fs8.readFile(path7, "utf-8");
1885
1772
  const textNoImports = removeProjectImportStatements(text);
1886
1773
  const { code } = await unimport2.injectImports(textNoImports);
1887
1774
  config.logger.debug(
@@ -1924,11 +1811,19 @@ async function importEntrypointFile(path6, config) {
1924
1811
  }
1925
1812
  );
1926
1813
  try {
1927
- const res = await jiti(path6);
1814
+ const res = await jiti(path7);
1928
1815
  return res.default;
1929
1816
  } catch (err) {
1930
- config.logger.error(err);
1931
- throw err;
1817
+ if (err instanceof ReferenceError) {
1818
+ const variableName = err.message.replace(" is not defined", "");
1819
+ const filePath = relative5(config.root, path7);
1820
+ throw Error(
1821
+ `${filePath}: Cannot use imported variable "${variableName}" outside the main function. See https://wxt.dev/guide/entrypoints.html#side-effects`,
1822
+ { cause: err }
1823
+ );
1824
+ } else {
1825
+ throw err;
1826
+ }
1932
1827
  }
1933
1828
  }
1934
1829
  function getEsbuildOptions(opts) {
@@ -1941,15 +1836,15 @@ function getEsbuildOptions(opts) {
1941
1836
  }
1942
1837
 
1943
1838
  // src/core/utils/building/internal-build.ts
1944
- import pc4 from "picocolors";
1839
+ import pc5 from "picocolors";
1945
1840
  import fs12 from "fs-extra";
1946
1841
 
1947
1842
  // src/core/utils/log/printBuildSummary.ts
1948
1843
  import { resolve as resolve10 } from "path";
1949
1844
 
1950
1845
  // src/core/utils/log/printFileList.ts
1951
- import path3 from "node:path";
1952
- import pc2 from "picocolors";
1846
+ import path4 from "node:path";
1847
+ import pc3 from "picocolors";
1953
1848
  import fs9 from "fs-extra";
1954
1849
  import { filesize } from "filesize";
1955
1850
 
@@ -1986,8 +1881,8 @@ async function printFileList(log, header, baseDir, files) {
1986
1881
  const fileRows = await Promise.all(
1987
1882
  files.map(async (file, i) => {
1988
1883
  const parts = [
1989
- path3.relative(process.cwd(), baseDir) + path3.sep,
1990
- path3.relative(baseDir, file)
1884
+ path4.relative(process.cwd(), baseDir) + path4.sep,
1885
+ path4.relative(baseDir, file)
1991
1886
  ];
1992
1887
  const prefix = i === files.length - 1 ? " \u2514\u2500" : " \u251C\u2500";
1993
1888
  const color = getChunkColor(file);
@@ -1995,25 +1890,25 @@ async function printFileList(log, header, baseDir, files) {
1995
1890
  totalSize += stats.size;
1996
1891
  const size = String(filesize(stats.size));
1997
1892
  return [
1998
- `${pc2.gray(prefix)} ${pc2.dim(parts[0])}${color(parts[1])}`,
1999
- pc2.dim(size)
1893
+ `${pc3.gray(prefix)} ${pc3.dim(parts[0])}${color(parts[1])}`,
1894
+ pc3.dim(size)
2000
1895
  ];
2001
1896
  })
2002
1897
  );
2003
- fileRows.push([`${pc2.cyan("\u03A3 Total size:")} ${String(filesize(totalSize))}`]);
1898
+ fileRows.push([`${pc3.cyan("\u03A3 Total size:")} ${String(filesize(totalSize))}`]);
2004
1899
  printTable(log, header, fileRows);
2005
1900
  }
2006
- var DEFAULT_COLOR = pc2.blue;
1901
+ var DEFAULT_COLOR = pc3.blue;
2007
1902
  var CHUNK_COLORS = {
2008
- ".js.map": pc2.gray,
2009
- ".cjs.map": pc2.gray,
2010
- ".mjs.map": pc2.gray,
2011
- ".html": pc2.green,
2012
- ".css": pc2.magenta,
2013
- ".js": pc2.cyan,
2014
- ".cjs": pc2.cyan,
2015
- ".mjs": pc2.cyan,
2016
- ".zip": pc2.yellow
1903
+ ".js.map": pc3.gray,
1904
+ ".cjs.map": pc3.gray,
1905
+ ".mjs.map": pc3.gray,
1906
+ ".html": pc3.green,
1907
+ ".css": pc3.magenta,
1908
+ ".js": pc3.cyan,
1909
+ ".cjs": pc3.cyan,
1910
+ ".mjs": pc3.cyan,
1911
+ ".zip": pc3.yellow
2017
1912
  };
2018
1913
  function getChunkColor(filename) {
2019
1914
  return Object.entries(CHUNK_COLORS).find(([key]) => filename.endsWith(key))?.[1] ?? DEFAULT_COLOR;
@@ -2050,15 +1945,15 @@ function getChunkSortWeight(filename) {
2050
1945
  }
2051
1946
 
2052
1947
  // src/core/utils/log/printHeader.ts
2053
- import pc3 from "picocolors";
1948
+ import pc4 from "picocolors";
2054
1949
  import { consola as consola2 } from "consola";
2055
1950
  function printHeader() {
2056
1951
  console.log();
2057
- consola2.log(`${pc3.gray("WXT")} ${pc3.gray(pc3.bold(version))}`);
1952
+ consola2.log(`${pc4.gray("WXT")} ${pc4.gray(pc4.bold(version))}`);
2058
1953
  }
2059
1954
 
2060
1955
  // src/core/utils/building/internal-build.ts
2061
- import glob4 from "fast-glob";
1956
+ import glob3 from "fast-glob";
2062
1957
 
2063
1958
  // src/core/utils/manifest.ts
2064
1959
  import fs11 from "fs-extra";
@@ -2633,7 +2528,7 @@ async function internalBuild(config) {
2633
2528
  const verb = config.command === "serve" ? "Pre-rendering" : "Building";
2634
2529
  const target = `${config.browser}-mv${config.manifestVersion}`;
2635
2530
  config.logger.info(
2636
- `${verb} ${pc4.cyan(target)} for ${pc4.cyan(config.mode)} with ${pc4.green(
2531
+ `${verb} ${pc5.cyan(target)} for ${pc5.cyan(config.mode)} with ${pc5.green(
2637
2532
  `${config.builder.name} ${config.builder.version}`
2638
2533
  )}`
2639
2534
  );
@@ -2654,14 +2549,14 @@ async function internalBuild(config) {
2654
2549
  await combineAnalysisStats(config);
2655
2550
  config.logger.info(
2656
2551
  `Analysis complete:
2657
- ${pc4.gray("\u2514\u2500")} ${pc4.yellow("stats.html")}`
2552
+ ${pc5.gray("\u2514\u2500")} ${pc5.yellow("stats.html")}`
2658
2553
  );
2659
2554
  }
2660
2555
  return output;
2661
2556
  }
2662
2557
  async function combineAnalysisStats(config) {
2663
2558
  const { execaCommand } = await import("./execa-4F7CCWCA.js");
2664
- const unixFiles = await glob4(`stats-*.json`, {
2559
+ const unixFiles = await glob3(`stats-*.json`, {
2665
2560
  cwd: config.outDir,
2666
2561
  absolute: true
2667
2562
  });
@@ -2679,11 +2574,11 @@ async function build(config) {
2679
2574
  }
2680
2575
 
2681
2576
  // src/core/clean.ts
2682
- import path4 from "node:path";
2683
- import glob5 from "fast-glob";
2577
+ import path5 from "node:path";
2578
+ import glob4 from "fast-glob";
2684
2579
  import fs13 from "fs-extra";
2685
2580
  import { consola as consola3 } from "consola";
2686
- import pc5 from "picocolors";
2581
+ import pc6 from "picocolors";
2687
2582
  async function clean(root = process.cwd()) {
2688
2583
  consola3.info("Cleaning Project");
2689
2584
  const tempDirs = [
@@ -2692,9 +2587,9 @@ async function clean(root = process.cwd()) {
2692
2587
  "**/.wxt",
2693
2588
  ".output/*"
2694
2589
  ];
2695
- consola3.debug("Looking for:", tempDirs.map(pc5.cyan).join(", "));
2696
- const directories = await glob5(tempDirs, {
2697
- cwd: path4.resolve(root),
2590
+ consola3.debug("Looking for:", tempDirs.map(pc6.cyan).join(", "));
2591
+ const directories = await glob4(tempDirs, {
2592
+ cwd: path5.resolve(root),
2698
2593
  absolute: true,
2699
2594
  onlyDirectories: true,
2700
2595
  deep: 2
@@ -2705,21 +2600,21 @@ async function clean(root = process.cwd()) {
2705
2600
  }
2706
2601
  consola3.debug(
2707
2602
  "Found:",
2708
- directories.map((dir) => pc5.cyan(path4.relative(root, dir))).join(", ")
2603
+ directories.map((dir) => pc6.cyan(path5.relative(root, dir))).join(", ")
2709
2604
  );
2710
2605
  for (const directory of directories) {
2711
2606
  await fs13.rm(directory, { force: true, recursive: true });
2712
- consola3.debug("Deleted " + pc5.cyan(path4.relative(root, directory)));
2607
+ consola3.debug("Deleted " + pc6.cyan(path5.relative(root, directory)));
2713
2608
  }
2714
2609
  }
2715
2610
 
2716
2611
  // src/core/runners/wsl.ts
2717
- import { relative as relative5 } from "node:path";
2612
+ import { relative as relative6 } from "node:path";
2718
2613
  function createWslRunner() {
2719
2614
  return {
2720
2615
  async openBrowser(config) {
2721
2616
  config.logger.warn(
2722
- `Cannot open browser when using WSL. Load "${relative5(
2617
+ `Cannot open browser when using WSL. Load "${relative6(
2723
2618
  process.cwd(),
2724
2619
  config.outDir
2725
2620
  )}" as an unpacked extension manually`
@@ -2791,12 +2686,12 @@ var WARN_LOG_LEVEL = 40;
2791
2686
  var ERROR_LOG_LEVEL = 50;
2792
2687
 
2793
2688
  // src/core/runners/safari.ts
2794
- import { relative as relative6 } from "node:path";
2689
+ import { relative as relative7 } from "node:path";
2795
2690
  function createSafariRunner() {
2796
2691
  return {
2797
2692
  async openBrowser(config) {
2798
2693
  config.logger.warn(
2799
- `Cannot Safari using web-ext. Load "${relative6(
2694
+ `Cannot Safari using web-ext. Load "${relative7(
2800
2695
  process.cwd(),
2801
2696
  config.outDir
2802
2697
  )}" as an unpacked extension manually`
@@ -2808,12 +2703,12 @@ function createSafariRunner() {
2808
2703
  }
2809
2704
 
2810
2705
  // src/core/runners/manual.ts
2811
- import { relative as relative7 } from "node:path";
2706
+ import { relative as relative8 } from "node:path";
2812
2707
  function createManualRunner() {
2813
2708
  return {
2814
2709
  async openBrowser(config) {
2815
2710
  config.logger.info(
2816
- `Load "${relative7(
2711
+ `Load "${relative8(
2817
2712
  process.cwd(),
2818
2713
  config.outDir
2819
2714
  )}" as an unpacked extension manually`
@@ -2844,8 +2739,8 @@ async function createExtensionRunner(config) {
2844
2739
  // src/core/create-server.ts
2845
2740
  import { consola as consola4 } from "consola";
2846
2741
  import { Mutex } from "async-mutex";
2847
- import pc6 from "picocolors";
2848
- import { relative as relative8 } from "node:path";
2742
+ import pc7 from "picocolors";
2743
+ import { relative as relative9 } from "node:path";
2849
2744
  async function createServer(inlineConfig) {
2850
2745
  const port = await getPort();
2851
2746
  const hostname = "localhost";
@@ -2875,8 +2770,8 @@ async function createServer(inlineConfig) {
2875
2770
  reloadContentScript(contentScript) {
2876
2771
  server.ws.send("wxt:reload-content-script", contentScript);
2877
2772
  },
2878
- reloadPage(path6) {
2879
- server.ws.send("wxt:reload-page", path6);
2773
+ reloadPage(path7) {
2774
+ server.ws.send("wxt:reload-page", path7);
2880
2775
  },
2881
2776
  reloadExtension() {
2882
2777
  server.ws.send("wxt:reload-extension");
@@ -2911,12 +2806,12 @@ function createFileReloader(options) {
2911
2806
  const { server, getLatestConfig, updateConfig } = options;
2912
2807
  const fileChangedMutex = new Mutex();
2913
2808
  const changeQueue = [];
2914
- return async (event, path6) => {
2809
+ return async (event, path7) => {
2915
2810
  const config = await getLatestConfig();
2916
2811
  updateConfig(config);
2917
- if (path6.startsWith(config.outBaseDir))
2812
+ if (path7.startsWith(config.outBaseDir))
2918
2813
  return;
2919
- changeQueue.push([event, path6]);
2814
+ changeQueue.push([event, path7]);
2920
2815
  await fileChangedMutex.runExclusive(async () => {
2921
2816
  const fileChanges = changeQueue.splice(0, changeQueue.length);
2922
2817
  if (fileChanges.length === 0)
@@ -2925,13 +2820,13 @@ function createFileReloader(options) {
2925
2820
  if (changes.type === "no-change")
2926
2821
  return;
2927
2822
  config.logger.info(
2928
- `Changed: ${Array.from(new Set(fileChanges.map((change) => change[1]))).map((file) => pc6.dim(relative8(config.root, file))).join(", ")}`
2823
+ `Changed: ${Array.from(new Set(fileChanges.map((change) => change[1]))).map((file) => pc7.dim(relative9(config.root, file))).join(", ")}`
2929
2824
  );
2930
2825
  const rebuiltNames = changes.rebuildGroups.flat().map((entry) => {
2931
- return pc6.cyan(
2932
- relative8(config.outDir, getEntrypointOutputFile(entry, ""))
2826
+ return pc7.cyan(
2827
+ relative9(config.outDir, getEntrypointOutputFile(entry, ""))
2933
2828
  );
2934
- }).join(pc6.dim(", "));
2829
+ }).join(pc7.dim(", "));
2935
2830
  const allEntrypoints = await findEntrypoints(config);
2936
2831
  const { output: newOutput } = await rebuild(
2937
2832
  config,
@@ -2988,8 +2883,8 @@ function reloadContentScripts(steps, config, server) {
2988
2883
  }
2989
2884
  function reloadHtmlPages(groups, server, config) {
2990
2885
  groups.flat().forEach((entry) => {
2991
- const path6 = getEntrypointBundlePath(entry, config.outDir, ".html");
2992
- server.reloadPage(path6);
2886
+ const path7 = getEntrypointBundlePath(entry, config.outDir, ".html");
2887
+ server.reloadPage(path7);
2993
2888
  });
2994
2889
  }
2995
2890
 
@@ -2998,8 +2893,8 @@ import prompts from "prompts";
2998
2893
  import { consola as consola5 } from "consola";
2999
2894
  import { downloadTemplate } from "giget";
3000
2895
  import fs14 from "fs-extra";
3001
- import path5 from "node:path";
3002
- import pc7 from "picocolors";
2896
+ import path6 from "node:path";
2897
+ import pc8 from "picocolors";
3003
2898
  async function initialize(options) {
3004
2899
  consola5.info("Initalizing new project");
3005
2900
  const templates = await listTemplates();
@@ -3028,11 +2923,11 @@ async function initialize(options) {
3028
2923
  type: () => options.packageManager == null ? "select" : void 0,
3029
2924
  message: "Package Manager",
3030
2925
  choices: [
3031
- { title: pc7.red("npm"), value: "npm" },
3032
- { title: pc7.yellow("pnpm"), value: "pnpm" },
3033
- { title: pc7.cyan("yarn"), value: "yarn" },
2926
+ { title: pc8.red("npm"), value: "npm" },
2927
+ { title: pc8.yellow("pnpm"), value: "pnpm" },
2928
+ { title: pc8.cyan("yarn"), value: "yarn" },
3034
2929
  {
3035
- title: `${pc7.magenta("bun")}${pc7.gray(" (experimental)")}`,
2930
+ title: `${pc8.magenta("bun")}${pc8.gray(" (experimental)")}`,
3036
2931
  value: "bun"
3037
2932
  }
3038
2933
  ]
@@ -3046,7 +2941,7 @@ async function initialize(options) {
3046
2941
  input.template ??= defaultTemplate;
3047
2942
  input.packageManager ??= options.packageManager;
3048
2943
  await cloneProject(input);
3049
- const cdPath = path5.relative(process.cwd(), path5.resolve(input.directory));
2944
+ const cdPath = path6.relative(process.cwd(), path6.resolve(input.directory));
3050
2945
  console.log();
3051
2946
  consola5.log(
3052
2947
  `\u2728 WXT project created with the ${TEMPLATE_COLORS[input.template.name]?.(input.template.name) ?? input.template.name} template.`
@@ -3055,8 +2950,8 @@ async function initialize(options) {
3055
2950
  consola5.log("Next steps:");
3056
2951
  let step = 0;
3057
2952
  if (cdPath !== "")
3058
- consola5.log(` ${++step}.`, pc7.cyan(`cd ${cdPath}`));
3059
- consola5.log(` ${++step}.`, pc7.cyan(`${input.packageManager} install`));
2953
+ consola5.log(` ${++step}.`, pc8.cyan(`cd ${cdPath}`));
2954
+ consola5.log(` ${++step}.`, pc8.cyan(`${input.packageManager} install`));
3060
2955
  console.log();
3061
2956
  }
3062
2957
  async function listTemplates() {
@@ -3098,8 +2993,8 @@ async function cloneProject({
3098
2993
  force: true
3099
2994
  });
3100
2995
  await fs14.move(
3101
- path5.join(directory, "_gitignore"),
3102
- path5.join(directory, ".gitignore")
2996
+ path6.join(directory, "_gitignore"),
2997
+ path6.join(directory, ".gitignore")
3103
2998
  ).catch(
3104
2999
  (err) => consola5.warn("Failed to move _gitignore to .gitignore:", err)
3105
3000
  );
@@ -3110,11 +3005,11 @@ async function cloneProject({
3110
3005
  }
3111
3006
  }
3112
3007
  var TEMPLATE_COLORS = {
3113
- vanilla: pc7.blue,
3114
- vue: pc7.green,
3115
- react: pc7.cyan,
3116
- svelte: pc7.red,
3117
- solid: pc7.blue
3008
+ vanilla: pc8.blue,
3009
+ vue: pc8.green,
3010
+ react: pc8.cyan,
3011
+ svelte: pc8.red,
3012
+ solid: pc8.blue
3118
3013
  };
3119
3014
  var TEMPLATE_SORT_WEIGHT = {
3120
3015
  vanilla: 0,
@@ -3132,7 +3027,7 @@ async function prepare(config) {
3132
3027
 
3133
3028
  // src/core/zip.ts
3134
3029
  import zipdir from "zip-dir";
3135
- import { dirname as dirname5, relative as relative9, resolve as resolve13 } from "node:path";
3030
+ import { dirname as dirname5, relative as relative10, resolve as resolve13 } from "node:path";
3136
3031
  import fs15 from "fs-extra";
3137
3032
  import { minimatch as minimatch2 } from "minimatch";
3138
3033
  async function zip(config) {
@@ -3165,8 +3060,8 @@ async function zip(config) {
3165
3060
  );
3166
3061
  await zipdir(internalConfig.zip.sourcesRoot, {
3167
3062
  saveTo: sourcesZipPath,
3168
- filter(path6) {
3169
- const relativePath = relative9(internalConfig.zip.sourcesRoot, path6);
3063
+ filter(path7) {
3064
+ const relativePath = relative10(internalConfig.zip.sourcesRoot, path7);
3170
3065
  const matchedPattern = internalConfig.zip.ignoredSources.find(
3171
3066
  (pattern) => minimatch2(relativePath, pattern)
3172
3067
  );
@@ -3191,7 +3086,13 @@ var cli = cac("wxt");
3191
3086
  cli.help();
3192
3087
  cli.version(version);
3193
3088
  cli.option("--debug", "enable debug mode");
3194
- cli.command("[root]", "start dev server").option("-c, --config <file>", "use specified config file").option("-m, --mode <mode>", "set env mode").option("-b, --browser <browser>", "specify a browser").option("--mv3", "target manifest v3").option("--mv2", "target manifest v2").action(
3089
+ cli.command("[root]", "start dev server").option("-c, --config <file>", "use specified config file").option("-m, --mode <mode>", "set env mode").option("-b, --browser <browser>", "specify a browser").option(
3090
+ "-e, --filter-entrypoint <entrypoint>",
3091
+ "only build specific entrypoints",
3092
+ {
3093
+ type: []
3094
+ }
3095
+ ).option("--mv3", "target manifest v3").option("--mv2", "target manifest v2").action(
3195
3096
  wrapAction(async (root, flags) => {
3196
3097
  const server = await createServer({
3197
3098
  root,
@@ -3199,13 +3100,20 @@ cli.command("[root]", "start dev server").option("-c, --config <file>", "use spe
3199
3100
  browser: flags.browser,
3200
3101
  manifestVersion: flags.mv3 ? 3 : flags.mv2 ? 2 : void 0,
3201
3102
  configFile: flags.config,
3202
- debug: flags.debug
3103
+ debug: flags.debug,
3104
+ filterEntrypoints: getArrayFromFlags(flags, "filterEntrypoint")
3203
3105
  });
3204
3106
  await server.start();
3205
3107
  return { isOngoing: true };
3206
3108
  })
3207
3109
  );
3208
- cli.command("build [root]", "build for production").option("-c, --config <file>", "use specified config file").option("-m, --mode <mode>", "set env mode").option("-b, --browser <browser>", "specify a browser").option("--mv3", "target manifest v3").option("--mv2", "target manifest v2").option("--analyze", "visualize extension bundle").action(
3110
+ cli.command("build [root]", "build for production").option("-c, --config <file>", "use specified config file").option("-m, --mode <mode>", "set env mode").option("-b, --browser <browser>", "specify a browser").option(
3111
+ "-e, --filter-entrypoint <entrypoint>",
3112
+ "only build specific entrypoints",
3113
+ {
3114
+ type: []
3115
+ }
3116
+ ).option("--mv3", "target manifest v3").option("--mv2", "target manifest v2").option("--analyze", "visualize extension bundle").action(
3209
3117
  wrapAction(async (root, flags) => {
3210
3118
  await build({
3211
3119
  root,
@@ -3216,7 +3124,8 @@ cli.command("build [root]", "build for production").option("-c, --config <file>"
3216
3124
  debug: flags.debug,
3217
3125
  analysis: {
3218
3126
  enabled: flags.analyze
3219
- }
3127
+ },
3128
+ filterEntrypoints: getArrayFromFlags(flags, "filterEntrypoint")
3220
3129
  });
3221
3130
  })
3222
3131
  );
@@ -3282,3 +3191,7 @@ function wrapAction(cb, options) {
3282
3191
  }
3283
3192
  };
3284
3193
  }
3194
+ function getArrayFromFlags(flags, name) {
3195
+ const array = [flags[name]].flat();
3196
+ return array.filter((item) => item != null);
3197
+ }