wxt 0.14.0 → 0.14.2-alpha2

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.0";
7
+ var version = "0.14.2-alpha2";
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(path7) {
17
- return normalize(path7);
16
+ function normalizePath(path6) {
17
+ return normalize(path6);
18
18
  }
19
- function unnormalizePath(path7) {
20
- return systemPath.normalize(path7);
19
+ function unnormalizePath(path6) {
20
+ return systemPath.normalize(path6);
21
21
  }
22
22
  var CSS_EXTENSIONS = ["css", "scss", "sass", "less", "styl", "stylus"];
23
23
  var CSS_EXTENSIONS_PATTERN = `+(${CSS_EXTENSIONS.join("|")})`;
@@ -38,8 +38,145 @@ 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 } from "path";
41
+ import { dirname, resolve, extname } from "node: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
43
180
  async function buildEntrypoints(groups, config, spinner) {
44
181
  const steps = [];
45
182
  for (let i = 0; i < groups.length; i++) {
@@ -48,7 +185,10 @@ async function buildEntrypoints(groups, config, spinner) {
48
185
  spinner.text = pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNames}`;
49
186
  steps.push(await config.builder.build(group));
50
187
  }
51
- const publicAssets = await copyPublicDirectory(config);
188
+ const publicAssets = (await Promise.all([
189
+ copyPublicDirectory(config),
190
+ copyLocalesDirectory(config)
191
+ ])).flat();
52
192
  return { publicAssets, steps };
53
193
  }
54
194
  async function copyPublicDirectory(config) {
@@ -68,6 +208,28 @@ async function copyPublicDirectory(config) {
68
208
  }
69
209
  return publicAssets;
70
210
  }
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
+ }
71
233
 
72
234
  // src/core/utils/arrays.ts
73
235
  function every(array, predicate) {
@@ -166,7 +328,7 @@ import { relative as relative2, resolve as resolve3 } from "path";
166
328
  import fs3 from "fs-extra";
167
329
  import { minimatch } from "minimatch";
168
330
  import { parseHTML } from "linkedom";
169
- import JSON5 from "json5";
331
+ import JSON52 from "json5";
170
332
  import glob2 from "fast-glob";
171
333
 
172
334
  // src/core/utils/entrypoints.ts
@@ -204,7 +366,7 @@ async function findEntrypoints(config) {
204
366
  const inputPath = resolve3(config.entrypointsDir, relativePath);
205
367
  const name = getEntrypointName(config.entrypointsDir, inputPath);
206
368
  const matchingGlob = pathGlobs.find(
207
- (glob5) => minimatch(relativePath, glob5)
369
+ (glob6) => minimatch(relativePath, glob6)
208
370
  );
209
371
  if (matchingGlob) {
210
372
  const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
@@ -323,11 +485,11 @@ function getHtmlBaseOptions(document) {
323
485
  const options = {};
324
486
  const includeContent = document.querySelector("meta[name='manifest.include']")?.getAttribute("content");
325
487
  if (includeContent) {
326
- options.include = JSON5.parse(includeContent);
488
+ options.include = JSON52.parse(includeContent);
327
489
  }
328
490
  const excludeContent = document.querySelector("meta[name='manifest.exclude']")?.getAttribute("content");
329
491
  if (excludeContent) {
330
- options.exclude = JSON5.parse(excludeContent);
492
+ options.exclude = JSON52.parse(excludeContent);
331
493
  }
332
494
  return options;
333
495
  }
@@ -341,7 +503,7 @@ async function getPopupEntrypoint(config, { inputPath, name }) {
341
503
  const defaultIconContent = document.querySelector("meta[name='manifest.default_icon']")?.getAttribute("content");
342
504
  if (defaultIconContent) {
343
505
  try {
344
- options.defaultIcon = JSON5.parse(defaultIconContent);
506
+ options.defaultIcon = JSON52.parse(defaultIconContent);
345
507
  } catch (err) {
346
508
  config.logger.fatal(
347
509
  `Failed to parse default_icon meta tag content as JSON5. content=${defaultIconContent}`,
@@ -517,7 +679,8 @@ function getUnimportOptions(config) {
517
679
  debugLog: config.logger.debug,
518
680
  imports: [
519
681
  { name: "defineConfig", from: "wxt" },
520
- { name: "fakeBrowser", from: "wxt/testing" }
682
+ { name: "fakeBrowser", from: "wxt/testing" },
683
+ { name: "i18n", from: "wxt/i18n" }
521
684
  ],
522
685
  presets: [
523
686
  { package: "wxt/client" },
@@ -590,46 +753,7 @@ function surroundInUnderscore(name) {
590
753
  }
591
754
 
592
755
  // src/core/utils/building/generate-wxt-dir.ts
593
- import path2 from "node:path";
594
-
595
- // src/core/utils/i18n.ts
596
- var predefinedMessages = {
597
- "@@extension_id": {
598
- message: "<browser.runtime.id>",
599
- 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."
600
- },
601
- "@@ui_locale": {
602
- message: "<browser.i18n.getUiLocale()>",
603
- description: ""
604
- },
605
- "@@bidi_dir": {
606
- message: "<ltr|rtl>",
607
- 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.'
608
- },
609
- "@@bidi_reversed_dir": {
610
- message: "<rtl|ltr>",
611
- description: `If the @@bidi_dir is "ltr", then this is "rtl"; otherwise, it's "ltr".`
612
- },
613
- "@@bidi_start_edge": {
614
- message: "<left|right>",
615
- description: `If the @@bidi_dir is "ltr", then this is "left"; otherwise, it's "right".`
616
- },
617
- "@@bidi_end_edge": {
618
- message: "<right|left>",
619
- description: `If the @@bidi_dir is "ltr", then this is "right"; otherwise, it's "left".`
620
- }
621
- };
622
- function parseI18nMessages(messagesJson) {
623
- return Object.entries({
624
- ...predefinedMessages,
625
- ...messagesJson
626
- }).map(([name, details]) => ({
627
- name,
628
- ...details
629
- }));
630
- }
631
-
632
- // src/core/utils/building/generate-wxt-dir.ts
756
+ import glob3 from "fast-glob";
633
757
  async function generateTypesDir(entrypoints, config) {
634
758
  await fs4.ensureDir(config.typesDir);
635
759
  const references = [];
@@ -663,7 +787,7 @@ async function writePathsDeclarationFile(entrypoints, config) {
663
787
  config.outDir,
664
788
  entry.inputPath.endsWith(".html") ? ".html" : ".js"
665
789
  )
666
- ).concat(await getPublicFiles(config)).map(normalizePath).map((path7) => ` | "/${path7}"`).sort().join("\n");
790
+ ).concat(await getPublicFiles(config)).map(normalizePath).map((path6) => ` | "/${path6}"`).sort().join("\n");
667
791
  const template = `// Generated by wxt
668
792
  import "wxt/browser";
669
793
 
@@ -699,28 +823,36 @@ declare module "wxt/browser" {
699
823
  }
700
824
 
701
825
  export interface WxtI18n extends I18n.Static {
702
- {{ overrides }}
826
+ {{ browserOverrides }}
827
+ }
828
+ }
829
+
830
+ declare module "wxt/i18n" {
831
+ export interface WxtMessageSchema {
832
+ t: {
833
+ {{ translationTOverrides }}
834
+ };
835
+ tp: {
836
+ {{ translationTpOverrides }}
837
+ };
703
838
  }
704
839
  }
705
840
  `;
706
841
  let messages;
707
842
  if (defaultLocale) {
708
- const defaultLocalePath = path2.resolve(
709
- config.publicDir,
710
- "_locales",
711
- defaultLocale,
712
- "messages.json"
713
- );
714
- const content = JSON.parse(await fs4.readFile(defaultLocalePath, "utf-8"));
715
- messages = parseI18nMessages(content);
843
+ const [defaultLocalePath] = await glob3(`${defaultLocale}.*`, {
844
+ cwd: config.localesDir,
845
+ absolute: true
846
+ });
847
+ messages = await readMessagesFile(defaultLocalePath);
716
848
  } else {
717
- messages = parseI18nMessages({});
849
+ messages = PREDEFINED_MESSAGES;
718
850
  }
719
851
  const overrides = messages.map((message) => {
720
852
  return ` /**
721
- * ${message.description ?? "No message description."}
853
+ * ${message.entry.description ?? "No message description."}
722
854
  *
723
- * "${message.message}"
855
+ * "${message.entry.message}"
724
856
  */
725
857
  getMessage(
726
858
  messageName: "${message.name}",
@@ -730,7 +862,13 @@ declare module "wxt/browser" {
730
862
  });
731
863
  await writeFileIfDifferent(
732
864
  filePath,
733
- template.replace("{{ overrides }}", overrides.join("\n"))
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
+ )
734
872
  );
735
873
  return filePath;
736
874
  }
@@ -766,7 +904,7 @@ async function writeMainDeclarationFile(references, config) {
766
904
  }
767
905
  async function writeTsConfigFile(mainReference, config) {
768
906
  const dir = config.wxtDir;
769
- const getTsconfigPath = (path7) => normalizePath(relative3(dir, path7));
907
+ const getTsconfigPath = (path6) => normalizePath(relative3(dir, path6));
770
908
  const paths = Object.entries(config.alias).flatMap(([alias, absolutePath]) => {
771
909
  const aliasPath = getTsconfigPath(absolutePath);
772
910
  return [
@@ -802,7 +940,7 @@ ${paths}
802
940
 
803
941
  // src/core/utils/building/get-internal-config.ts
804
942
  import { loadConfig } from "c12";
805
- import path3 from "node:path";
943
+ import path2 from "node:path";
806
944
 
807
945
  // src/core/utils/cache.ts
808
946
  import fs5, { ensureDir } from "fs-extra";
@@ -811,14 +949,14 @@ function createFsCache(wxtDir) {
811
949
  const getPath = (key) => resolve5(wxtDir, "cache", encodeURIComponent(key));
812
950
  return {
813
951
  async set(key, value) {
814
- const path7 = getPath(key);
815
- await ensureDir(dirname2(path7));
816
- await writeFileIfDifferent(path7, value);
952
+ const path6 = getPath(key);
953
+ await ensureDir(dirname2(path6));
954
+ await writeFileIfDifferent(path6, value);
817
955
  },
818
956
  async get(key) {
819
- const path7 = getPath(key);
957
+ const path6 = getPath(key);
820
958
  try {
821
- return await fs5.readFile(path7, "utf-8");
959
+ return await fs5.readFile(path6, "utf-8");
822
960
  } catch {
823
961
  return void 0;
824
962
  }
@@ -1040,7 +1178,7 @@ function download(config) {
1040
1178
  }
1041
1179
 
1042
1180
  // src/core/builders/vite/plugins/multipageMove.ts
1043
- import { dirname as dirname4, extname, resolve as resolve7, join } from "node:path";
1181
+ import { dirname as dirname4, extname as extname2, resolve as resolve7, join } from "node:path";
1044
1182
  import fs6, { ensureDir as ensureDir2 } from "fs-extra";
1045
1183
  function multipageMove(entrypoints, config) {
1046
1184
  return {
@@ -1059,7 +1197,7 @@ function multipageMove(entrypoints, config) {
1059
1197
  const newBundlePath = getEntrypointBundlePath(
1060
1198
  entrypoint,
1061
1199
  config.outDir,
1062
- extname(oldBundlePath)
1200
+ extname2(oldBundlePath)
1063
1201
  );
1064
1202
  if (newBundlePath === oldBundlePath) {
1065
1203
  config.logger.debug(
@@ -1100,7 +1238,7 @@ async function removeEmptyDirs(dir) {
1100
1238
 
1101
1239
  // src/core/builders/vite/plugins/unimport.ts
1102
1240
  import { createUnimport as createUnimport2 } from "unimport";
1103
- import { extname as extname2 } from "path";
1241
+ import { extname as extname3 } from "path";
1104
1242
  var ENABLED_EXTENSIONS = /* @__PURE__ */ new Set([
1105
1243
  ".js",
1106
1244
  ".jsx",
@@ -1122,7 +1260,7 @@ function unimport(config) {
1122
1260
  async transform(code, id) {
1123
1261
  if (id.includes("node_modules"))
1124
1262
  return;
1125
- if (!ENABLED_EXTENSIONS.has(extname2(id)))
1263
+ if (!ENABLED_EXTENSIONS.has(extname3(id)))
1126
1264
  return;
1127
1265
  return unimport2.injectImports(code, id);
1128
1266
  }
@@ -1286,7 +1424,7 @@ function entrypointGroupGlobals(entrypointGroup) {
1286
1424
  }
1287
1425
 
1288
1426
  // src/core/builders/vite/index.ts
1289
- async function craeteViteBuilder(inlineConfig, userConfig, wxtConfig) {
1427
+ async function createViteBuilder(inlineConfig, userConfig, wxtConfig) {
1290
1428
  const vite = await import("vite");
1291
1429
  const getBaseConfig = async () => {
1292
1430
  const resolvedInlineConfig = await inlineConfig.vite?.(wxtConfig.env) ?? {};
@@ -1514,19 +1652,20 @@ async function getInternalConfig(inlineConfig, command, server) {
1514
1652
  const manifestVersion = mergedConfig.manifestVersion ?? (browser === "firefox" || browser === "safari" ? 2 : 3);
1515
1653
  const mode = mergedConfig.mode ?? (command === "build" ? "production" : "development");
1516
1654
  const env = { browser, command, manifestVersion, mode };
1517
- const root = path3.resolve(
1655
+ const root = path2.resolve(
1518
1656
  inlineConfig.root ?? userConfig.root ?? process.cwd()
1519
1657
  );
1520
- const wxtDir = path3.resolve(root, ".wxt");
1521
- const srcDir = path3.resolve(root, mergedConfig.srcDir ?? root);
1522
- const entrypointsDir = path3.resolve(
1658
+ const wxtDir = path2.resolve(root, ".wxt");
1659
+ const srcDir = path2.resolve(root, mergedConfig.srcDir ?? root);
1660
+ const entrypointsDir = path2.resolve(
1523
1661
  srcDir,
1524
1662
  mergedConfig.entrypointsDir ?? "entrypoints"
1525
1663
  );
1526
- const publicDir = path3.resolve(srcDir, mergedConfig.publicDir ?? "public");
1527
- const typesDir = path3.resolve(wxtDir, "types");
1528
- const outBaseDir = path3.resolve(root, mergedConfig.outDir ?? ".output");
1529
- const outDir = path3.resolve(outBaseDir, `${browser}-mv${manifestVersion}`);
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}`);
1530
1669
  const runnerConfig = await loadConfig({
1531
1670
  name: "web-ext",
1532
1671
  cwd: root,
@@ -1542,7 +1681,7 @@ async function getInternalConfig(inlineConfig, command, server) {
1542
1681
  "~": srcDir,
1543
1682
  "@@": root,
1544
1683
  "~~": root
1545
- }).map(([key, value]) => [key, path3.resolve(root, value)])
1684
+ }).map(([key, value]) => [key, path2.resolve(root, value)])
1546
1685
  );
1547
1686
  const finalConfig = {
1548
1687
  browser,
@@ -1559,6 +1698,7 @@ async function getInternalConfig(inlineConfig, command, server) {
1559
1698
  outBaseDir,
1560
1699
  outDir,
1561
1700
  publicDir,
1701
+ localesDir,
1562
1702
  root,
1563
1703
  runnerConfig,
1564
1704
  srcDir,
@@ -1580,7 +1720,7 @@ async function getInternalConfig(inlineConfig, command, server) {
1580
1720
  },
1581
1721
  server
1582
1722
  };
1583
- const builder = await craeteViteBuilder(
1723
+ const builder = await createViteBuilder(
1584
1724
  inlineConfig,
1585
1725
  userConfig,
1586
1726
  finalConfig
@@ -1627,6 +1767,7 @@ function mergeInlineConfig(inlineConfig, userConfig) {
1627
1767
  manifest,
1628
1768
  mode: inlineConfig.mode ?? userConfig.mode,
1629
1769
  publicDir: inlineConfig.publicDir ?? userConfig.publicDir,
1770
+ localesDir: inlineConfig.localesDir ?? userConfig.localesDir,
1630
1771
  runner,
1631
1772
  srcDir: inlineConfig.srcDir ?? userConfig.srcDir,
1632
1773
  outDir: inlineConfig.outDir ?? userConfig.outDir,
@@ -1731,16 +1872,16 @@ ${noImports}`;
1731
1872
  // src/core/utils/building/import-entrypoint.ts
1732
1873
  import { transformSync } from "esbuild";
1733
1874
  import { fileURLToPath } from "node:url";
1734
- async function importEntrypointFile(path7, config) {
1735
- config.logger.debug("Loading file metadata:", path7);
1736
- const normalPath = normalizePath(path7);
1875
+ async function importEntrypointFile(path6, config) {
1876
+ config.logger.debug("Loading file metadata:", path6);
1877
+ const normalPath = normalizePath(path6);
1737
1878
  const unimport2 = createUnimport3({
1738
1879
  ...getUnimportOptions(config),
1739
1880
  // Only allow specific imports, not all from the project
1740
1881
  dirs: []
1741
1882
  });
1742
1883
  await unimport2.init();
1743
- const text = await fs8.readFile(path7, "utf-8");
1884
+ const text = await fs8.readFile(path6, "utf-8");
1744
1885
  const textNoImports = removeProjectImportStatements(text);
1745
1886
  const { code } = await unimport2.injectImports(textNoImports);
1746
1887
  config.logger.debug(
@@ -1783,7 +1924,7 @@ async function importEntrypointFile(path7, config) {
1783
1924
  }
1784
1925
  );
1785
1926
  try {
1786
- const res = await jiti(path7);
1927
+ const res = await jiti(path6);
1787
1928
  return res.default;
1788
1929
  } catch (err) {
1789
1930
  config.logger.error(err);
@@ -1807,7 +1948,7 @@ import fs12 from "fs-extra";
1807
1948
  import { resolve as resolve10 } from "path";
1808
1949
 
1809
1950
  // src/core/utils/log/printFileList.ts
1810
- import path4 from "node:path";
1951
+ import path3 from "node:path";
1811
1952
  import pc2 from "picocolors";
1812
1953
  import fs9 from "fs-extra";
1813
1954
  import { filesize } from "filesize";
@@ -1845,8 +1986,8 @@ async function printFileList(log, header, baseDir, files) {
1845
1986
  const fileRows = await Promise.all(
1846
1987
  files.map(async (file, i) => {
1847
1988
  const parts = [
1848
- path4.relative(process.cwd(), baseDir) + path4.sep,
1849
- path4.relative(baseDir, file)
1989
+ path3.relative(process.cwd(), baseDir) + path3.sep,
1990
+ path3.relative(baseDir, file)
1850
1991
  ];
1851
1992
  const prefix = i === files.length - 1 ? " \u2514\u2500" : " \u251C\u2500";
1852
1993
  const color = getChunkColor(file);
@@ -1917,7 +2058,7 @@ function printHeader() {
1917
2058
  }
1918
2059
 
1919
2060
  // src/core/utils/building/internal-build.ts
1920
- import glob3 from "fast-glob";
2061
+ import glob4 from "fast-glob";
1921
2062
 
1922
2063
  // src/core/utils/manifest.ts
1923
2064
  import fs11 from "fs-extra";
@@ -2074,7 +2215,7 @@ async function generateManifest(entrypoints, buildOutput, config) {
2074
2215
  "wxt:reload-extension": {
2075
2216
  description: "Reload the extension during development",
2076
2217
  suggested_key: {
2077
- default: "Ctrl+E"
2218
+ default: "Alt+R"
2078
2219
  }
2079
2220
  }
2080
2221
  };
@@ -2447,13 +2588,12 @@ function stripPathFromMatchPattern(pattern) {
2447
2588
  }
2448
2589
 
2449
2590
  // src/core/utils/building/rebuild.ts
2450
- async function rebuild(config, entrypointGroups, existingOutput = {
2591
+ async function rebuild(config, allEntrypoints, entrypointGroups, existingOutput = {
2451
2592
  steps: [],
2452
2593
  publicAssets: []
2453
2594
  }) {
2454
2595
  const { default: ora } = await import("ora");
2455
2596
  const spinner = ora(`Preparing...`).start();
2456
- const allEntrypoints = await findEntrypoints(config);
2457
2597
  await generateTypesDir(allEntrypoints, config).catch((err) => {
2458
2598
  config.logger.warn("Failed to update .wxt directory:", err);
2459
2599
  if (config.command === "build")
@@ -2503,7 +2643,7 @@ async function internalBuild(config) {
2503
2643
  const entrypoints = await findEntrypoints(config);
2504
2644
  config.logger.debug("Detected entrypoints:", entrypoints);
2505
2645
  const groups = groupEntrypoints(entrypoints);
2506
- const { output } = await rebuild(config, groups, void 0);
2646
+ const { output } = await rebuild(config, entrypoints, groups, void 0);
2507
2647
  await printBuildSummary(
2508
2648
  config.logger.success,
2509
2649
  `Built extension in ${formatDuration(Date.now() - startTime)}`,
@@ -2521,7 +2661,7 @@ async function internalBuild(config) {
2521
2661
  }
2522
2662
  async function combineAnalysisStats(config) {
2523
2663
  const { execaCommand } = await import("./execa-4F7CCWCA.js");
2524
- const unixFiles = await glob3(`stats-*.json`, {
2664
+ const unixFiles = await glob4(`stats-*.json`, {
2525
2665
  cwd: config.outDir,
2526
2666
  absolute: true
2527
2667
  });
@@ -2539,8 +2679,8 @@ async function build(config) {
2539
2679
  }
2540
2680
 
2541
2681
  // src/core/clean.ts
2542
- import path5 from "node:path";
2543
- import glob4 from "fast-glob";
2682
+ import path4 from "node:path";
2683
+ import glob5 from "fast-glob";
2544
2684
  import fs13 from "fs-extra";
2545
2685
  import { consola as consola3 } from "consola";
2546
2686
  import pc5 from "picocolors";
@@ -2553,8 +2693,8 @@ async function clean(root = process.cwd()) {
2553
2693
  ".output/*"
2554
2694
  ];
2555
2695
  consola3.debug("Looking for:", tempDirs.map(pc5.cyan).join(", "));
2556
- const directories = await glob4(tempDirs, {
2557
- cwd: path5.resolve(root),
2696
+ const directories = await glob5(tempDirs, {
2697
+ cwd: path4.resolve(root),
2558
2698
  absolute: true,
2559
2699
  onlyDirectories: true,
2560
2700
  deep: 2
@@ -2565,11 +2705,11 @@ async function clean(root = process.cwd()) {
2565
2705
  }
2566
2706
  consola3.debug(
2567
2707
  "Found:",
2568
- directories.map((dir) => pc5.cyan(path5.relative(root, dir))).join(", ")
2708
+ directories.map((dir) => pc5.cyan(path4.relative(root, dir))).join(", ")
2569
2709
  );
2570
2710
  for (const directory of directories) {
2571
2711
  await fs13.rm(directory, { force: true, recursive: true });
2572
- consola3.debug("Deleted " + pc5.cyan(path5.relative(root, directory)));
2712
+ consola3.debug("Deleted " + pc5.cyan(path4.relative(root, directory)));
2573
2713
  }
2574
2714
  }
2575
2715
 
@@ -2735,8 +2875,8 @@ async function createServer(inlineConfig) {
2735
2875
  reloadContentScript(contentScript) {
2736
2876
  server.ws.send("wxt:reload-content-script", contentScript);
2737
2877
  },
2738
- reloadPage(path7) {
2739
- server.ws.send("wxt:reload-page", path7);
2878
+ reloadPage(path6) {
2879
+ server.ws.send("wxt:reload-page", path6);
2740
2880
  },
2741
2881
  reloadExtension() {
2742
2882
  server.ws.send("wxt:reload-extension");
@@ -2771,12 +2911,12 @@ function createFileReloader(options) {
2771
2911
  const { server, getLatestConfig, updateConfig } = options;
2772
2912
  const fileChangedMutex = new Mutex();
2773
2913
  const changeQueue = [];
2774
- return async (event, path7) => {
2914
+ return async (event, path6) => {
2775
2915
  const config = await getLatestConfig();
2776
2916
  updateConfig(config);
2777
- if (path7.startsWith(config.outBaseDir))
2917
+ if (path6.startsWith(config.outBaseDir))
2778
2918
  return;
2779
- changeQueue.push([event, path7]);
2919
+ changeQueue.push([event, path6]);
2780
2920
  await fileChangedMutex.runExclusive(async () => {
2781
2921
  const fileChanges = changeQueue.splice(0, changeQueue.length);
2782
2922
  if (fileChanges.length === 0)
@@ -2792,8 +2932,10 @@ function createFileReloader(options) {
2792
2932
  relative8(config.outDir, getEntrypointOutputFile(entry, ""))
2793
2933
  );
2794
2934
  }).join(pc6.dim(", "));
2935
+ const allEntrypoints = await findEntrypoints(config);
2795
2936
  const { output: newOutput } = await rebuild(
2796
2937
  config,
2938
+ allEntrypoints,
2797
2939
  // TODO: this excludes new entrypoints, so they're not built until the dev command is restarted
2798
2940
  changes.rebuildGroups,
2799
2941
  changes.cachedOutput
@@ -2846,8 +2988,8 @@ function reloadContentScripts(steps, config, server) {
2846
2988
  }
2847
2989
  function reloadHtmlPages(groups, server, config) {
2848
2990
  groups.flat().forEach((entry) => {
2849
- const path7 = getEntrypointBundlePath(entry, config.outDir, ".html");
2850
- server.reloadPage(path7);
2991
+ const path6 = getEntrypointBundlePath(entry, config.outDir, ".html");
2992
+ server.reloadPage(path6);
2851
2993
  });
2852
2994
  }
2853
2995
 
@@ -2856,7 +2998,7 @@ import prompts from "prompts";
2856
2998
  import { consola as consola5 } from "consola";
2857
2999
  import { downloadTemplate } from "giget";
2858
3000
  import fs14 from "fs-extra";
2859
- import path6 from "node:path";
3001
+ import path5 from "node:path";
2860
3002
  import pc7 from "picocolors";
2861
3003
  async function initialize(options) {
2862
3004
  consola5.info("Initalizing new project");
@@ -2904,7 +3046,7 @@ async function initialize(options) {
2904
3046
  input.template ??= defaultTemplate;
2905
3047
  input.packageManager ??= options.packageManager;
2906
3048
  await cloneProject(input);
2907
- const cdPath = path6.relative(process.cwd(), path6.resolve(input.directory));
3049
+ const cdPath = path5.relative(process.cwd(), path5.resolve(input.directory));
2908
3050
  console.log();
2909
3051
  consola5.log(
2910
3052
  `\u2728 WXT project created with the ${TEMPLATE_COLORS[input.template.name]?.(input.template.name) ?? input.template.name} template.`
@@ -2956,8 +3098,8 @@ async function cloneProject({
2956
3098
  force: true
2957
3099
  });
2958
3100
  await fs14.move(
2959
- path6.join(directory, "_gitignore"),
2960
- path6.join(directory, ".gitignore")
3101
+ path5.join(directory, "_gitignore"),
3102
+ path5.join(directory, ".gitignore")
2961
3103
  ).catch(
2962
3104
  (err) => consola5.warn("Failed to move _gitignore to .gitignore:", err)
2963
3105
  );
@@ -3023,8 +3165,8 @@ async function zip(config) {
3023
3165
  );
3024
3166
  await zipdir(internalConfig.zip.sourcesRoot, {
3025
3167
  saveTo: sourcesZipPath,
3026
- filter(path7) {
3027
- const relativePath = relative9(internalConfig.zip.sourcesRoot, path7);
3168
+ filter(path6) {
3169
+ const relativePath = relative9(internalConfig.zip.sourcesRoot, path6);
3028
3170
  const matchedPattern = internalConfig.zip.ignoredSources.find(
3029
3171
  (pattern) => minimatch2(relativePath, pattern)
3030
3172
  );