wxt 0.14.2-alpha2 → 0.14.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,5 @@
1
1
  // package.json
2
- var version = "0.14.2-alpha2";
2
+ var version = "0.14.3";
3
3
 
4
4
  // src/core/utils/arrays.ts
5
5
  function every(array, predicate) {
@@ -12,11 +12,11 @@ function every(array, predicate) {
12
12
  // src/core/utils/paths.ts
13
13
  import systemPath from "node:path";
14
14
  import normalize from "normalize-path";
15
- function normalizePath(path5) {
16
- return normalize(path5);
15
+ function normalizePath(path6) {
16
+ return normalize(path6);
17
17
  }
18
- function unnormalizePath(path5) {
19
- return systemPath.normalize(path5);
18
+ function unnormalizePath(path6) {
19
+ return systemPath.normalize(path6);
20
20
  }
21
21
  var CSS_EXTENSIONS = ["css", "scss", "sass", "less", "styl", "stylus"];
22
22
  var CSS_EXTENSIONS_PATTERN = `+(${CSS_EXTENSIONS.join("|")})`;
@@ -127,11 +127,11 @@ function resolvePerBrowserOption(option, browser) {
127
127
  }
128
128
 
129
129
  // src/core/utils/building/find-entrypoints.ts
130
- import { relative as relative4, resolve as resolve12 } from "path";
130
+ import { relative as relative5, resolve as resolve12 } from "path";
131
131
  import fs12 from "fs-extra";
132
132
  import { minimatch } from "minimatch";
133
133
  import { parseHTML as parseHTML2 } from "linkedom";
134
- import JSON52 from "json5";
134
+ import JSON5 from "json5";
135
135
 
136
136
  // src/core/utils/fs.ts
137
137
  import fs from "fs-extra";
@@ -151,145 +151,8 @@ async function getPublicFiles(config) {
151
151
 
152
152
  // src/core/utils/building/build-entrypoints.ts
153
153
  import fs2 from "fs-extra";
154
- import { dirname, resolve as resolve2, extname } from "node:path";
154
+ import { dirname, resolve as resolve2 } from "path";
155
155
  import pc from "picocolors";
156
-
157
- // src/i18n/node.ts
158
- import { readFile } from "node:fs/promises";
159
- import JSON5 from "json5";
160
- import YAML from "yaml";
161
- async function readMessagesFile(file) {
162
- const text = await readFile(file, "utf-8");
163
- return readMessagesText(text);
164
- }
165
- function readMessagesText(text) {
166
- const parsers = [
167
- JSON.parse,
168
- JSON5.parse,
169
- YAML.parse
170
- ];
171
- for (const parse of parsers) {
172
- try {
173
- const result = parse(text);
174
- if (typeof result === "object") {
175
- return readMessagesObject(result);
176
- }
177
- } catch {
178
- continue;
179
- }
180
- }
181
- throw Error("I18n messages text is not valid JSON, JSON5, or YAML");
182
- }
183
- function readMessagesObject(input) {
184
- const messagesFromInput = findEntries([], input);
185
- return [...messagesFromInput, ...PREDEFINED_MESSAGES];
186
- }
187
- function convertMessagesToManifest(messages) {
188
- return messages.filter((message) => !message.isBuiltin).reduce((schema, { name, entry }) => {
189
- schema[name] = entry;
190
- return schema;
191
- }, {});
192
- }
193
- function findEntries(keyPath, input) {
194
- const name = keyPath.join("_");
195
- if (isBasicEntry(input))
196
- return [
197
- {
198
- name,
199
- entry: { message: input }
200
- }
201
- ];
202
- if (isManifestEntry(input))
203
- return [
204
- {
205
- name,
206
- entry: input
207
- }
208
- ];
209
- if (isPluralEntry(input))
210
- return [
211
- {
212
- name,
213
- entry: {
214
- message: Object.values(input).join(" | ")
215
- },
216
- isPlural: true
217
- }
218
- ];
219
- return Object.entries(input).reduce((items, [key, child]) => {
220
- const nestedEntries = findEntries(keyPath.concat(key), child);
221
- return [...items, ...nestedEntries];
222
- }, []);
223
- }
224
- function isBasicEntry(entry) {
225
- return typeof entry === "string";
226
- }
227
- function isManifestEntry(entry) {
228
- const keys = Object.keys(entry);
229
- if (keys.length < 1 || keys.length > 3)
230
- return false;
231
- const knownKeys = /* @__PURE__ */ new Set(["message", "placeholders", "description"]);
232
- const unknownKeys = keys.filter((key) => !knownKeys.has(key));
233
- return unknownKeys.length === 0;
234
- }
235
- function isPluralEntry(entry) {
236
- const keys = Object.keys(entry);
237
- if (keys.length === 0)
238
- return false;
239
- const invalidKeys = keys.filter((key) => key !== "n" && isNaN(Number(key)));
240
- return invalidKeys.length === 0;
241
- }
242
- var PREDEFINED_MESSAGES = [
243
- {
244
- name: "@@extension_id",
245
- isBuiltin: true,
246
- entry: {
247
- message: "<browser.runtime.id>",
248
- 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."
249
- }
250
- },
251
- {
252
- name: "@@ui_locale",
253
- isBuiltin: true,
254
- entry: {
255
- message: "<browser.i18n.getUiLocale()>"
256
- }
257
- },
258
- {
259
- name: "@@bidi_dir",
260
- isBuiltin: true,
261
- entry: {
262
- message: "<ltr|rtl>",
263
- 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.'
264
- }
265
- },
266
- {
267
- name: "@@bidi_reversed_dir",
268
- isBuiltin: true,
269
- entry: {
270
- message: "<rtl|ltr>",
271
- description: `If the @@bidi_dir is "ltr", then this is "rtl"; otherwise, it's "ltr".`
272
- }
273
- },
274
- {
275
- name: "@@bidi_start_edge",
276
- isBuiltin: true,
277
- entry: {
278
- message: "<left|right>",
279
- description: `If the @@bidi_dir is "ltr", then this is "left"; otherwise, it's "right".`
280
- }
281
- },
282
- {
283
- name: "@@bidi_end_edge",
284
- isBuiltin: true,
285
- entry: {
286
- message: "<right|left>",
287
- description: `If the @@bidi_dir is "ltr", then this is "right"; otherwise, it's "left".`
288
- }
289
- }
290
- ];
291
-
292
- // src/core/utils/building/build-entrypoints.ts
293
156
  async function buildEntrypoints(groups, config, spinner) {
294
157
  const steps = [];
295
158
  for (let i = 0; i < groups.length; i++) {
@@ -298,10 +161,7 @@ async function buildEntrypoints(groups, config, spinner) {
298
161
  spinner.text = pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNames}`;
299
162
  steps.push(await config.builder.build(group));
300
163
  }
301
- const publicAssets = (await Promise.all([
302
- copyPublicDirectory(config),
303
- copyLocalesDirectory(config)
304
- ])).flat();
164
+ const publicAssets = await copyPublicDirectory(config);
305
165
  return { publicAssets, steps };
306
166
  }
307
167
  async function copyPublicDirectory(config) {
@@ -321,28 +181,6 @@ async function copyPublicDirectory(config) {
321
181
  }
322
182
  return publicAssets;
323
183
  }
324
- async function copyLocalesDirectory(config) {
325
- const localesExist = await fs2.exists(config.localesDir);
326
- if (!localesExist || config.manifest.default_locale == null)
327
- return [];
328
- const files = await fs2.readdir(config.localesDir);
329
- return await Promise.all(
330
- files.map(async (file) => {
331
- const locale = file.replace(extname(file), "");
332
- const fileName = unnormalizePath(`_locales/${locale}/messages.json`);
333
- const srcPath = resolve2(config.localesDir, file);
334
- const outPath = resolve2(config.outDir, fileName);
335
- const messages = await readMessagesFile(srcPath);
336
- const json = convertMessagesToManifest(messages);
337
- await fs2.ensureDir(dirname(outPath));
338
- await fs2.writeJson(outPath, json);
339
- return {
340
- fileName,
341
- type: "asset"
342
- };
343
- })
344
- );
345
- }
346
184
 
347
185
  // src/core/utils/building/generate-wxt-dir.ts
348
186
  import { createUnimport } from "unimport";
@@ -358,8 +196,7 @@ function getUnimportOptions(config) {
358
196
  debugLog: config.logger.debug,
359
197
  imports: [
360
198
  { name: "defineConfig", from: "wxt" },
361
- { name: "fakeBrowser", from: "wxt/testing" },
362
- { name: "i18n", from: "wxt/i18n" }
199
+ { name: "fakeBrowser", from: "wxt/testing" }
363
200
  ],
364
201
  presets: [
365
202
  { package: "wxt/client" },
@@ -432,7 +269,46 @@ function surroundInUnderscore(name) {
432
269
  }
433
270
 
434
271
  // src/core/utils/building/generate-wxt-dir.ts
435
- import glob2 from "fast-glob";
272
+ import path2 from "node:path";
273
+
274
+ // src/core/utils/i18n.ts
275
+ var predefinedMessages = {
276
+ "@@extension_id": {
277
+ message: "<browser.runtime.id>",
278
+ 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."
279
+ },
280
+ "@@ui_locale": {
281
+ message: "<browser.i18n.getUiLocale()>",
282
+ description: ""
283
+ },
284
+ "@@bidi_dir": {
285
+ message: "<ltr|rtl>",
286
+ 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.'
287
+ },
288
+ "@@bidi_reversed_dir": {
289
+ message: "<rtl|ltr>",
290
+ description: `If the @@bidi_dir is "ltr", then this is "rtl"; otherwise, it's "ltr".`
291
+ },
292
+ "@@bidi_start_edge": {
293
+ message: "<left|right>",
294
+ description: `If the @@bidi_dir is "ltr", then this is "left"; otherwise, it's "right".`
295
+ },
296
+ "@@bidi_end_edge": {
297
+ message: "<right|left>",
298
+ description: `If the @@bidi_dir is "ltr", then this is "right"; otherwise, it's "left".`
299
+ }
300
+ };
301
+ function parseI18nMessages(messagesJson) {
302
+ return Object.entries({
303
+ ...predefinedMessages,
304
+ ...messagesJson
305
+ }).map(([name, details]) => ({
306
+ name,
307
+ ...details
308
+ }));
309
+ }
310
+
311
+ // src/core/utils/building/generate-wxt-dir.ts
436
312
  async function generateTypesDir(entrypoints, config) {
437
313
  await fs3.ensureDir(config.typesDir);
438
314
  const references = [];
@@ -466,15 +342,17 @@ async function writePathsDeclarationFile(entrypoints, config) {
466
342
  config.outDir,
467
343
  entry.inputPath.endsWith(".html") ? ".html" : ".js"
468
344
  )
469
- ).concat(await getPublicFiles(config)).map(normalizePath).map((path5) => ` | "/${path5}"`).sort().join("\n");
345
+ ).concat(await getPublicFiles(config)).map(normalizePath).map((path6) => ` | "/${path6}"`).sort().join("\n");
470
346
  const template = `// Generated by wxt
471
347
  import "wxt/browser";
472
348
 
473
349
  declare module "wxt/browser" {
474
350
  export type PublicPath =
475
351
  {{ union }}
352
+ type HtmlPublicPath = Extract<PublicPath, \`\${string}.html\`>
476
353
  export interface WxtRuntime extends Runtime.Static {
477
354
  getURL(path: PublicPath): string;
355
+ getURL(path: \`\${HtmlPublicPath}\${string}\`): string;
478
356
  }
479
357
  }
480
358
  `;
@@ -502,36 +380,28 @@ declare module "wxt/browser" {
502
380
  }
503
381
 
504
382
  export interface WxtI18n extends I18n.Static {
505
- {{ browserOverrides }}
506
- }
507
- }
508
-
509
- declare module "wxt/i18n" {
510
- export interface WxtMessageSchema {
511
- t: {
512
- {{ translationTOverrides }}
513
- };
514
- tp: {
515
- {{ translationTpOverrides }}
516
- };
383
+ {{ overrides }}
517
384
  }
518
385
  }
519
386
  `;
520
387
  let messages;
521
388
  if (defaultLocale) {
522
- const [defaultLocalePath] = await glob2(`${defaultLocale}.*`, {
523
- cwd: config.localesDir,
524
- absolute: true
525
- });
526
- messages = await readMessagesFile(defaultLocalePath);
389
+ const defaultLocalePath = path2.resolve(
390
+ config.publicDir,
391
+ "_locales",
392
+ defaultLocale,
393
+ "messages.json"
394
+ );
395
+ const content = JSON.parse(await fs3.readFile(defaultLocalePath, "utf-8"));
396
+ messages = parseI18nMessages(content);
527
397
  } else {
528
- messages = PREDEFINED_MESSAGES;
398
+ messages = parseI18nMessages({});
529
399
  }
530
400
  const overrides = messages.map((message) => {
531
401
  return ` /**
532
- * ${message.entry.description ?? "No message description."}
402
+ * ${message.description ?? "No message description."}
533
403
  *
534
- * "${message.entry.message}"
404
+ * "${message.message}"
535
405
  */
536
406
  getMessage(
537
407
  messageName: "${message.name}",
@@ -541,13 +411,7 @@ declare module "wxt/i18n" {
541
411
  });
542
412
  await writeFileIfDifferent(
543
413
  filePath,
544
- template.replace("{{ browserOverrides }}", overrides.join("\n")).replace(
545
- "{{ translationTOverrides }}",
546
- messages.filter((message) => !message.isPlural).map((message) => ` "${message.name}": any;`).join("\n")
547
- ).replace(
548
- "{{ translationTpOverrides }}",
549
- messages.filter((message) => message.isPlural).map((message) => ` "${message.name}": any;`).join("\n")
550
- )
414
+ template.replace("{{ overrides }}", overrides.join("\n"))
551
415
  );
552
416
  return filePath;
553
417
  }
@@ -583,7 +447,7 @@ async function writeMainDeclarationFile(references, config) {
583
447
  }
584
448
  async function writeTsConfigFile(mainReference, config) {
585
449
  const dir = config.wxtDir;
586
- const getTsconfigPath = (path5) => normalizePath(relative2(dir, path5));
450
+ const getTsconfigPath = (path6) => normalizePath(relative2(dir, path6));
587
451
  const paths = Object.entries(config.alias).flatMap(([alias, absolutePath]) => {
588
452
  const aliasPath = getTsconfigPath(absolutePath);
589
453
  return [
@@ -619,7 +483,7 @@ ${paths}
619
483
 
620
484
  // src/core/utils/building/get-internal-config.ts
621
485
  import { loadConfig } from "c12";
622
- import path3 from "node:path";
486
+ import path4 from "node:path";
623
487
 
624
488
  // src/core/utils/cache.ts
625
489
  import fs4, { ensureDir } from "fs-extra";
@@ -628,14 +492,14 @@ function createFsCache(wxtDir) {
628
492
  const getPath = (key) => resolve4(wxtDir, "cache", encodeURIComponent(key));
629
493
  return {
630
494
  async set(key, value) {
631
- const path5 = getPath(key);
632
- await ensureDir(dirname2(path5));
633
- await writeFileIfDifferent(path5, value);
495
+ const path6 = getPath(key);
496
+ await ensureDir(dirname2(path6));
497
+ await writeFileIfDifferent(path6, value);
634
498
  },
635
499
  async get(key) {
636
- const path5 = getPath(key);
500
+ const path6 = getPath(key);
637
501
  try {
638
- return await fs4.readFile(path5, "utf-8");
502
+ return await fs4.readFile(path6, "utf-8");
639
503
  } catch {
640
504
  return void 0;
641
505
  }
@@ -857,7 +721,7 @@ function download(config) {
857
721
  }
858
722
 
859
723
  // src/core/builders/vite/plugins/multipageMove.ts
860
- import { dirname as dirname4, extname as extname2, resolve as resolve6, join } from "node:path";
724
+ import { dirname as dirname4, extname, resolve as resolve6, join } from "node:path";
861
725
  import fs5, { ensureDir as ensureDir2 } from "fs-extra";
862
726
  function multipageMove(entrypoints, config) {
863
727
  return {
@@ -876,7 +740,7 @@ function multipageMove(entrypoints, config) {
876
740
  const newBundlePath = getEntrypointBundlePath(
877
741
  entrypoint,
878
742
  config.outDir,
879
- extname2(oldBundlePath)
743
+ extname(oldBundlePath)
880
744
  );
881
745
  if (newBundlePath === oldBundlePath) {
882
746
  config.logger.debug(
@@ -917,7 +781,7 @@ async function removeEmptyDirs(dir) {
917
781
 
918
782
  // src/core/builders/vite/plugins/unimport.ts
919
783
  import { createUnimport as createUnimport2 } from "unimport";
920
- import { extname as extname3 } from "path";
784
+ import { extname as extname2 } from "path";
921
785
  var ENABLED_EXTENSIONS = /* @__PURE__ */ new Set([
922
786
  ".js",
923
787
  ".jsx",
@@ -939,7 +803,7 @@ function unimport(config) {
939
803
  async transform(code, id) {
940
804
  if (id.includes("node_modules"))
941
805
  return;
942
- if (!ENABLED_EXTENSIONS.has(extname3(id)))
806
+ if (!ENABLED_EXTENSIONS.has(extname2(id)))
943
807
  return;
944
808
  return unimport2.injectImports(code, id);
945
809
  }
@@ -1065,7 +929,7 @@ function globals(config) {
1065
929
  }
1066
930
 
1067
931
  // src/core/builders/vite/plugins/webextensionPolyfillMock.ts
1068
- import path2 from "node:path";
932
+ import path3 from "node:path";
1069
933
  function webextensionPolyfillMock(config) {
1070
934
  return {
1071
935
  name: "wxt:testing-inline-deps",
@@ -1074,7 +938,7 @@ function webextensionPolyfillMock(config) {
1074
938
  resolve: {
1075
939
  alias: {
1076
940
  // Alias to use a mocked version of the polyfill
1077
- "webextension-polyfill": path2.resolve(
941
+ "webextension-polyfill": path3.resolve(
1078
942
  config.root,
1079
943
  "node_modules/wxt/dist/virtual/mock-browser"
1080
944
  )
@@ -1359,20 +1223,20 @@ async function getInternalConfig(inlineConfig, command, server) {
1359
1223
  const manifestVersion = mergedConfig.manifestVersion ?? (browser === "firefox" || browser === "safari" ? 2 : 3);
1360
1224
  const mode = mergedConfig.mode ?? (command === "build" ? "production" : "development");
1361
1225
  const env = { browser, command, manifestVersion, mode };
1362
- const root = path3.resolve(
1226
+ const root = path4.resolve(
1363
1227
  inlineConfig.root ?? userConfig.root ?? process.cwd()
1364
1228
  );
1365
- const wxtDir = path3.resolve(root, ".wxt");
1366
- const srcDir = path3.resolve(root, mergedConfig.srcDir ?? root);
1367
- const entrypointsDir = path3.resolve(
1229
+ const wxtDir = path4.resolve(root, ".wxt");
1230
+ const srcDir = path4.resolve(root, mergedConfig.srcDir ?? root);
1231
+ const entrypointsDir = path4.resolve(
1368
1232
  srcDir,
1369
1233
  mergedConfig.entrypointsDir ?? "entrypoints"
1370
1234
  );
1371
- const publicDir = path3.resolve(srcDir, mergedConfig.publicDir ?? "public");
1372
- const localesDir = path3.resolve(srcDir, mergedConfig.localesDir ?? "locales");
1373
- const typesDir = path3.resolve(wxtDir, "types");
1374
- const outBaseDir = path3.resolve(root, mergedConfig.outDir ?? ".output");
1375
- const outDir = path3.resolve(outBaseDir, `${browser}-mv${manifestVersion}`);
1235
+ const filterEntrypoints = !!mergedConfig.filterEntrypoints?.length ? new Set(mergedConfig.filterEntrypoints) : void 0;
1236
+ const publicDir = path4.resolve(srcDir, mergedConfig.publicDir ?? "public");
1237
+ const typesDir = path4.resolve(wxtDir, "types");
1238
+ const outBaseDir = path4.resolve(root, mergedConfig.outDir ?? ".output");
1239
+ const outDir = path4.resolve(outBaseDir, `${browser}-mv${manifestVersion}`);
1376
1240
  const runnerConfig = await loadConfig({
1377
1241
  name: "web-ext",
1378
1242
  cwd: root,
@@ -1388,13 +1252,14 @@ async function getInternalConfig(inlineConfig, command, server) {
1388
1252
  "~": srcDir,
1389
1253
  "@@": root,
1390
1254
  "~~": root
1391
- }).map(([key, value]) => [key, path3.resolve(root, value)])
1255
+ }).map(([key, value]) => [key, path4.resolve(root, value)])
1392
1256
  );
1393
1257
  const finalConfig = {
1394
1258
  browser,
1395
1259
  command,
1396
1260
  debug,
1397
1261
  entrypointsDir,
1262
+ filterEntrypoints,
1398
1263
  env,
1399
1264
  fsCache: createFsCache(wxtDir),
1400
1265
  imports: mergedConfig.imports ?? {},
@@ -1405,7 +1270,6 @@ async function getInternalConfig(inlineConfig, command, server) {
1405
1270
  outBaseDir,
1406
1271
  outDir,
1407
1272
  publicDir,
1408
- localesDir,
1409
1273
  root,
1410
1274
  runnerConfig,
1411
1275
  srcDir,
@@ -1469,12 +1333,12 @@ function mergeInlineConfig(inlineConfig, userConfig) {
1469
1333
  configFile: inlineConfig.configFile,
1470
1334
  debug: inlineConfig.debug ?? userConfig.debug,
1471
1335
  entrypointsDir: inlineConfig.entrypointsDir ?? userConfig.entrypointsDir,
1336
+ filterEntrypoints: inlineConfig.filterEntrypoints ?? userConfig.filterEntrypoints,
1472
1337
  imports,
1473
1338
  logger: inlineConfig.logger ?? userConfig.logger,
1474
1339
  manifest,
1475
1340
  mode: inlineConfig.mode ?? userConfig.mode,
1476
1341
  publicDir: inlineConfig.publicDir ?? userConfig.publicDir,
1477
- localesDir: inlineConfig.localesDir ?? userConfig.localesDir,
1478
1342
  runner,
1479
1343
  srcDir: inlineConfig.srcDir ?? userConfig.srcDir,
1480
1344
  outDir: inlineConfig.outDir ?? userConfig.outDir,
@@ -1557,7 +1421,7 @@ var ENTRY_TYPE_TO_GROUP_MAP = {
1557
1421
  import createJITI from "jiti";
1558
1422
  import { createUnimport as createUnimport3 } from "unimport";
1559
1423
  import fs7 from "fs-extra";
1560
- import { resolve as resolve8 } from "node:path";
1424
+ import { relative as relative4, resolve as resolve8 } from "node:path";
1561
1425
 
1562
1426
  // src/core/utils/strings.ts
1563
1427
  function kebabCaseAlphanumeric(str) {
@@ -1579,16 +1443,16 @@ ${noImports}`;
1579
1443
  // src/core/utils/building/import-entrypoint.ts
1580
1444
  import { transformSync } from "esbuild";
1581
1445
  import { fileURLToPath } from "node:url";
1582
- async function importEntrypointFile(path5, config) {
1583
- config.logger.debug("Loading file metadata:", path5);
1584
- const normalPath = normalizePath(path5);
1446
+ async function importEntrypointFile(path6, config) {
1447
+ config.logger.debug("Loading file metadata:", path6);
1448
+ const normalPath = normalizePath(path6);
1585
1449
  const unimport2 = createUnimport3({
1586
1450
  ...getUnimportOptions(config),
1587
1451
  // Only allow specific imports, not all from the project
1588
1452
  dirs: []
1589
1453
  });
1590
1454
  await unimport2.init();
1591
- const text = await fs7.readFile(path5, "utf-8");
1455
+ const text = await fs7.readFile(path6, "utf-8");
1592
1456
  const textNoImports = removeProjectImportStatements(text);
1593
1457
  const { code } = await unimport2.injectImports(textNoImports);
1594
1458
  config.logger.debug(
@@ -1631,11 +1495,19 @@ async function importEntrypointFile(path5, config) {
1631
1495
  }
1632
1496
  );
1633
1497
  try {
1634
- const res = await jiti(path5);
1498
+ const res = await jiti(path6);
1635
1499
  return res.default;
1636
1500
  } catch (err) {
1637
- config.logger.error(err);
1638
- throw err;
1501
+ if (err instanceof ReferenceError) {
1502
+ const variableName = err.message.replace(" is not defined", "");
1503
+ const filePath = relative4(config.root, path6);
1504
+ throw Error(
1505
+ `${filePath}: Cannot use imported variable "${variableName}" outside the main function. See https://wxt.dev/guide/entrypoints.html#side-effects`,
1506
+ { cause: err }
1507
+ );
1508
+ } else {
1509
+ throw err;
1510
+ }
1639
1511
  }
1640
1512
  }
1641
1513
  function getEsbuildOptions(opts) {
@@ -1655,7 +1527,7 @@ import fs11 from "fs-extra";
1655
1527
  import { resolve as resolve9 } from "path";
1656
1528
 
1657
1529
  // src/core/utils/log/printFileList.ts
1658
- import path4 from "node:path";
1530
+ import path5 from "node:path";
1659
1531
  import pc2 from "picocolors";
1660
1532
  import fs8 from "fs-extra";
1661
1533
  import { filesize } from "filesize";
@@ -1693,8 +1565,8 @@ async function printFileList(log, header, baseDir, files) {
1693
1565
  const fileRows = await Promise.all(
1694
1566
  files.map(async (file, i) => {
1695
1567
  const parts = [
1696
- path4.relative(process.cwd(), baseDir) + path4.sep,
1697
- path4.relative(baseDir, file)
1568
+ path5.relative(process.cwd(), baseDir) + path5.sep,
1569
+ path5.relative(baseDir, file)
1698
1570
  ];
1699
1571
  const prefix = i === files.length - 1 ? " \u2514\u2500" : " \u251C\u2500";
1700
1572
  const color = getChunkColor(file);
@@ -1761,7 +1633,7 @@ import pc3 from "picocolors";
1761
1633
  import { consola as consola2 } from "consola";
1762
1634
 
1763
1635
  // src/core/utils/building/internal-build.ts
1764
- import glob3 from "fast-glob";
1636
+ import glob2 from "fast-glob";
1765
1637
 
1766
1638
  // src/core/utils/manifest.ts
1767
1639
  import fs10 from "fs-extra";
@@ -2364,7 +2236,7 @@ async function internalBuild(config) {
2364
2236
  }
2365
2237
  async function combineAnalysisStats(config) {
2366
2238
  const { execaCommand } = await import("./execa-4F7CCWCA.js");
2367
- const unixFiles = await glob3(`stats-*.json`, {
2239
+ const unixFiles = await glob2(`stats-*.json`, {
2368
2240
  cwd: config.outDir,
2369
2241
  absolute: true
2370
2242
  });
@@ -2376,9 +2248,10 @@ async function combineAnalysisStats(config) {
2376
2248
  }
2377
2249
 
2378
2250
  // src/core/utils/building/find-entrypoints.ts
2379
- import glob4 from "fast-glob";
2251
+ import glob3 from "fast-glob";
2252
+ import pc5 from "picocolors";
2380
2253
  async function findEntrypoints(config) {
2381
- const relativePaths = await glob4(Object.keys(PATH_GLOB_TO_TYPE_MAP), {
2254
+ const relativePaths = await glob3(Object.keys(PATH_GLOB_TO_TYPE_MAP), {
2382
2255
  cwd: config.entrypointsDir
2383
2256
  });
2384
2257
  relativePaths.sort();
@@ -2387,11 +2260,16 @@ async function findEntrypoints(config) {
2387
2260
  const inputPath = resolve12(config.entrypointsDir, relativePath);
2388
2261
  const name = getEntrypointName(config.entrypointsDir, inputPath);
2389
2262
  const matchingGlob = pathGlobs.find(
2390
- (glob5) => minimatch(relativePath, glob5)
2263
+ (glob4) => minimatch(relativePath, glob4)
2391
2264
  );
2392
2265
  if (matchingGlob) {
2393
2266
  const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
2394
- results.push({ name, inputPath, type });
2267
+ results.push({
2268
+ name,
2269
+ inputPath,
2270
+ type,
2271
+ skipped: config.filterEntrypoints != null && !config.filterEntrypoints.has(name)
2272
+ });
2395
2273
  }
2396
2274
  return results;
2397
2275
  }, []);
@@ -2443,11 +2321,19 @@ async function findEntrypoints(config) {
2443
2321
  await getBackgroundEntrypoint(config, {
2444
2322
  inputPath: VIRTUAL_NOOP_BACKGROUND_MODULE_ID,
2445
2323
  name: "background",
2446
- type: "background"
2324
+ type: "background",
2325
+ skipped: false
2447
2326
  })
2448
2327
  );
2449
2328
  }
2450
2329
  config.logger.debug("All entrypoints:", entrypoints);
2330
+ const skippedEntrypointNames = entrypointInfos.filter((item) => item.skipped).map((item) => item.name);
2331
+ if (skippedEntrypointNames.length) {
2332
+ config.logger.warn(
2333
+ `Filter excluded the following entrypoints:
2334
+ ${skippedEntrypointNames.map((item) => `${pc5.dim("-")} ${pc5.cyan(item)}`).join("\n")}`
2335
+ );
2336
+ }
2451
2337
  const targetEntrypoints = entrypoints.filter((entry) => {
2452
2338
  const { include, exclude } = entry.options;
2453
2339
  if (include?.length && exclude?.length) {
@@ -2462,6 +2348,9 @@ async function findEntrypoints(config) {
2462
2348
  if (include?.length && !exclude?.length) {
2463
2349
  return include.includes(config.browser);
2464
2350
  }
2351
+ if (skippedEntrypointNames.includes(entry.name)) {
2352
+ return false;
2353
+ }
2465
2354
  return true;
2466
2355
  });
2467
2356
  config.logger.debug(`${config.browser} entrypoints:`, targetEntrypoints);
@@ -2481,7 +2370,7 @@ function preventDuplicateEntrypointNames(config, files) {
2481
2370
  if (absolutePaths.length > 1) {
2482
2371
  lines.push(`- ${name}`);
2483
2372
  absolutePaths.forEach((absolutePath) => {
2484
- lines.push(` - ${relative4(config.root, absolutePath)}`);
2373
+ lines.push(` - ${relative5(config.root, absolutePath)}`);
2485
2374
  });
2486
2375
  }
2487
2376
  return lines;
@@ -2506,15 +2395,15 @@ function getHtmlBaseOptions(document) {
2506
2395
  const options = {};
2507
2396
  const includeContent = document.querySelector("meta[name='manifest.include']")?.getAttribute("content");
2508
2397
  if (includeContent) {
2509
- options.include = JSON52.parse(includeContent);
2398
+ options.include = JSON5.parse(includeContent);
2510
2399
  }
2511
2400
  const excludeContent = document.querySelector("meta[name='manifest.exclude']")?.getAttribute("content");
2512
2401
  if (excludeContent) {
2513
- options.exclude = JSON52.parse(excludeContent);
2402
+ options.exclude = JSON5.parse(excludeContent);
2514
2403
  }
2515
2404
  return options;
2516
2405
  }
2517
- async function getPopupEntrypoint(config, { inputPath, name }) {
2406
+ async function getPopupEntrypoint(config, { inputPath, name, skipped }) {
2518
2407
  const content = await fs12.readFile(inputPath, "utf-8");
2519
2408
  const { document } = parseHTML2(content);
2520
2409
  const options = getHtmlBaseOptions(document);
@@ -2524,7 +2413,7 @@ async function getPopupEntrypoint(config, { inputPath, name }) {
2524
2413
  const defaultIconContent = document.querySelector("meta[name='manifest.default_icon']")?.getAttribute("content");
2525
2414
  if (defaultIconContent) {
2526
2415
  try {
2527
- options.defaultIcon = JSON52.parse(defaultIconContent);
2416
+ options.defaultIcon = JSON5.parse(defaultIconContent);
2528
2417
  } catch (err) {
2529
2418
  config.logger.fatal(
2530
2419
  `Failed to parse default_icon meta tag content as JSON5. content=${defaultIconContent}`,
@@ -2545,10 +2434,11 @@ async function getPopupEntrypoint(config, { inputPath, name }) {
2545
2434
  name: "popup",
2546
2435
  options,
2547
2436
  inputPath,
2548
- outputDir: config.outDir
2437
+ outputDir: config.outDir,
2438
+ skipped
2549
2439
  };
2550
2440
  }
2551
- async function getOptionsEntrypoint(config, { inputPath, name }) {
2441
+ async function getOptionsEntrypoint(config, { inputPath, name, skipped }) {
2552
2442
  const content = await fs12.readFile(inputPath, "utf-8");
2553
2443
  const { document } = parseHTML2(content);
2554
2444
  const options = getHtmlBaseOptions(document);
@@ -2569,10 +2459,11 @@ async function getOptionsEntrypoint(config, { inputPath, name }) {
2569
2459
  name: "options",
2570
2460
  options,
2571
2461
  inputPath,
2572
- outputDir: config.outDir
2462
+ outputDir: config.outDir,
2463
+ skipped
2573
2464
  };
2574
2465
  }
2575
- async function getUnlistedPageEntrypoint(config, { inputPath, name }) {
2466
+ async function getUnlistedPageEntrypoint(config, { inputPath, name, skipped }) {
2576
2467
  const content = await fs12.readFile(inputPath, "utf-8");
2577
2468
  const { document } = parseHTML2(content);
2578
2469
  return {
@@ -2580,10 +2471,11 @@ async function getUnlistedPageEntrypoint(config, { inputPath, name }) {
2580
2471
  name: getEntrypointName(config.entrypointsDir, inputPath),
2581
2472
  inputPath,
2582
2473
  outputDir: config.outDir,
2583
- options: getHtmlBaseOptions(document)
2474
+ options: getHtmlBaseOptions(document),
2475
+ skipped
2584
2476
  };
2585
2477
  }
2586
- async function getUnlistedScriptEntrypoint(config, { inputPath, name }) {
2478
+ async function getUnlistedScriptEntrypoint(config, { inputPath, name, skipped }) {
2587
2479
  const defaultExport = await importEntrypointFile(
2588
2480
  inputPath,
2589
2481
  config
@@ -2600,10 +2492,11 @@ async function getUnlistedScriptEntrypoint(config, { inputPath, name }) {
2600
2492
  name,
2601
2493
  inputPath,
2602
2494
  outputDir: config.outDir,
2603
- options
2495
+ options,
2496
+ skipped
2604
2497
  };
2605
2498
  }
2606
- async function getBackgroundEntrypoint(config, { inputPath, name }) {
2499
+ async function getBackgroundEntrypoint(config, { inputPath, name, skipped }) {
2607
2500
  let options = {};
2608
2501
  if (inputPath !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
2609
2502
  const defaultExport = await importEntrypointFile(
@@ -2627,10 +2520,11 @@ async function getBackgroundEntrypoint(config, { inputPath, name }) {
2627
2520
  ...options,
2628
2521
  type: resolvePerBrowserOption(options.type, config.browser),
2629
2522
  persistent: resolvePerBrowserOption(options.persistent, config.browser)
2630
- }
2523
+ },
2524
+ skipped
2631
2525
  };
2632
2526
  }
2633
- async function getContentScriptEntrypoint(config, { inputPath, name }) {
2527
+ async function getContentScriptEntrypoint(config, { inputPath, name, skipped }) {
2634
2528
  const { main: _, ...options } = await importEntrypointFile(inputPath, config);
2635
2529
  if (options == null) {
2636
2530
  throw Error(
@@ -2642,7 +2536,8 @@ async function getContentScriptEntrypoint(config, { inputPath, name }) {
2642
2536
  name,
2643
2537
  inputPath,
2644
2538
  outputDir: resolve12(config.outDir, CONTENT_SCRIPT_OUT_DIR),
2645
- options
2539
+ options,
2540
+ skipped
2646
2541
  };
2647
2542
  }
2648
2543
  var PATH_GLOB_TO_TYPE_MAP = {