wxt 0.3.1 → 0.4.0

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/index.cjs CHANGED
@@ -49,11 +49,11 @@ var import_node_path2 = __toESM(require("path"), 1);
49
49
  // src/core/utils/paths.ts
50
50
  var import_node_path = __toESM(require("path"), 1);
51
51
  var vite = __toESM(require("vite"), 1);
52
- function normalizePath2(path5) {
53
- return vite.normalizePath(path5);
52
+ function normalizePath2(path6) {
53
+ return vite.normalizePath(path6);
54
54
  }
55
- function unnormalizePath(path5) {
56
- return import_node_path.default.normalize(path5);
55
+ function unnormalizePath(path6) {
56
+ return import_node_path.default.normalize(path6);
57
57
  }
58
58
  var CSS_EXTENSIONS = ["css", "scss", "sass", "less", "styl", "stylus"];
59
59
  var CSS_EXTENSIONS_PATTERN = `+(${CSS_EXTENSIONS.join("|")})`;
@@ -235,7 +235,9 @@ function multipageMove(entrypoints, config) {
235
235
  (entry) => !!normalizePath2(entry.inputPath).endsWith(oldBundlePath)
236
236
  );
237
237
  if (entrypoint == null) {
238
- config.logger.debug("No entrypoint found for", oldBundlePath);
238
+ config.logger.debug(
239
+ `No entrypoint found for ${oldBundlePath}, leaving in chunks directory`
240
+ );
239
241
  continue;
240
242
  }
241
243
  const newBundlePath = getEntrypointBundlePath(
@@ -276,7 +278,7 @@ function getUnimportOptions(config) {
276
278
  imports: [{ name: "defineConfig", from: "wxt" }],
277
279
  presets: [{ package: "wxt/client" }, { package: "wxt/browser" }],
278
280
  warn: config.logger.warn,
279
- dirs: ["./components/*", "./composables/*", "./hooks/*", "./utils/*"]
281
+ dirs: ["components", "composables", "hooks", "utils"]
280
282
  };
281
283
  return (0, import_vite.mergeConfig)(
282
284
  defaultOptions,
@@ -342,12 +344,22 @@ function virtualEntrypoin(type, config) {
342
344
  }
343
345
 
344
346
  // src/core/vite-plugins/tsconfigPaths.ts
345
- var import_vite_tsconfig_paths = __toESM(require("vite-tsconfig-paths"), 1);
346
347
  function tsconfigPaths(config) {
347
- const fn = typeof import_vite_tsconfig_paths.default === "function" ? import_vite_tsconfig_paths.default : import_vite_tsconfig_paths.default.default;
348
- return fn({
349
- root: config.root
350
- });
348
+ return {
349
+ name: "wxt:aliases",
350
+ async config() {
351
+ return {
352
+ resolve: {
353
+ alias: {
354
+ "@@": config.root,
355
+ "~~": config.root,
356
+ "@": config.srcDir,
357
+ "~": config.srcDir
358
+ }
359
+ }
360
+ };
361
+ }
362
+ };
351
363
  }
352
364
 
353
365
  // src/core/vite-plugins/noopBackground.ts
@@ -401,14 +413,14 @@ function createFsCache(wxtDir) {
401
413
  const getPath = (key) => (0, import_path4.resolve)(wxtDir, "cache", encodeURIComponent(key));
402
414
  return {
403
415
  async set(key, value) {
404
- const path5 = getPath(key);
405
- await (0, import_fs_extra3.ensureDir)((0, import_path4.dirname)(path5));
406
- await import_fs_extra3.default.writeFile(path5, value, "utf-8");
416
+ const path6 = getPath(key);
417
+ await (0, import_fs_extra3.ensureDir)((0, import_path4.dirname)(path6));
418
+ await import_fs_extra3.default.writeFile(path6, value, "utf-8");
407
419
  },
408
420
  async get(key) {
409
- const path5 = getPath(key);
421
+ const path6 = getPath(key);
410
422
  try {
411
- return await import_fs_extra3.default.readFile(path5, "utf-8");
423
+ return await import_fs_extra3.default.readFile(path6, "utf-8");
412
424
  } catch {
413
425
  return void 0;
414
426
  }
@@ -472,6 +484,9 @@ async function getInternalConfig(config, command) {
472
484
  const outBaseDir = import_node_path4.default.resolve(root, ".output");
473
485
  const outDir = import_node_path4.default.resolve(outBaseDir, `${browser}-mv${manifestVersion}`);
474
486
  const logger = config.logger ?? import_consola.consola;
487
+ const debug = !!config.debug;
488
+ if (debug)
489
+ logger.level = import_consola.LogLevels.debug;
475
490
  const baseConfig = {
476
491
  root,
477
492
  outDir,
@@ -481,6 +496,7 @@ async function getInternalConfig(config, command) {
481
496
  manifestVersion,
482
497
  mode,
483
498
  command,
499
+ debug,
484
500
  logger,
485
501
  vite: config.vite ?? {},
486
502
  imports: config.imports ?? {},
@@ -513,7 +529,7 @@ async function getInternalConfig(config, command) {
513
529
  userConfig.entrypointsDir ?? "entrypoints"
514
530
  );
515
531
  const publicDir = (0, import_node_path4.resolve)(root, userConfig.publicDir ?? "public");
516
- const wxtDir = (0, import_node_path4.resolve)(srcDir, ".wxt");
532
+ const wxtDir = (0, import_node_path4.resolve)(root, ".wxt");
517
533
  const typesDir = (0, import_node_path4.resolve)(wxtDir, "types");
518
534
  const env = { mode, browser, manifestVersion, command };
519
535
  const userManifest = await resolveManifestConfig(env, userConfig.manifest);
@@ -677,7 +693,7 @@ function findEffectedSteps(changedFile, currentOutput) {
677
693
  // src/index.ts
678
694
  var import_async_mutex = require("async-mutex");
679
695
  var import_consola2 = require("consola");
680
- var import_node_path7 = require("path");
696
+ var import_node_path8 = require("path");
681
697
 
682
698
  // src/core/build/buildEntrypoints.ts
683
699
  var vite3 = __toESM(require("vite"), 1);
@@ -849,16 +865,16 @@ function removeImportStatements(text) {
849
865
  }
850
866
 
851
867
  // src/core/utils/importTsFile.ts
852
- async function importTsFile(path5, config) {
853
- config.logger.debug("Loading file metadata:", path5);
854
- const normalPath = normalizePath2(path5);
868
+ async function importTsFile(path6, config) {
869
+ config.logger.debug("Loading file metadata:", path6);
870
+ const normalPath = normalizePath2(path6);
855
871
  const unimport2 = (0, import_unimport2.createUnimport)({
856
872
  ...getUnimportOptions(config),
857
873
  // Only allow specific imports, not all from the project
858
874
  dirs: []
859
875
  });
860
876
  await unimport2.init();
861
- const text = await import_fs_extra7.default.readFile(path5, "utf-8");
877
+ const text = await import_fs_extra7.default.readFile(path6, "utf-8");
862
878
  const textNoImports = removeImportStatements(text);
863
879
  const { code } = await unimport2.injectImports(textNoImports);
864
880
  config.logger.debug(
@@ -882,7 +898,7 @@ async function importTsFile(path5, config) {
882
898
  }
883
899
  });
884
900
  try {
885
- return await jiti(path5);
901
+ return await jiti(path6);
886
902
  } catch (err) {
887
903
  config.logger.error(err);
888
904
  throw err;
@@ -902,7 +918,7 @@ async function findEntrypoints(config) {
902
918
  let hasBackground = false;
903
919
  await Promise.all(
904
920
  relativePaths.map(async (relativePath) => {
905
- const path5 = (0, import_path8.resolve)(config.entrypointsDir, relativePath);
921
+ const path6 = (0, import_path8.resolve)(config.entrypointsDir, relativePath);
906
922
  const matchingGlob = pathGlobs.find(
907
923
  (glob3) => (0, import_minimatch.minimatch)(relativePath, glob3)
908
924
  );
@@ -922,35 +938,35 @@ ${JSON.stringify(
922
938
  let entrypoint;
923
939
  switch (type) {
924
940
  case "popup":
925
- entrypoint = await getPopupEntrypoint(config, path5);
941
+ entrypoint = await getPopupEntrypoint(config, path6);
926
942
  break;
927
943
  case "options":
928
- entrypoint = await getOptionsEntrypoint(config, path5);
944
+ entrypoint = await getOptionsEntrypoint(config, path6);
929
945
  break;
930
946
  case "background":
931
- entrypoint = await getBackgroundEntrypoint(config, path5);
947
+ entrypoint = await getBackgroundEntrypoint(config, path6);
932
948
  hasBackground = true;
933
949
  break;
934
950
  case "content-script":
935
951
  entrypoint = await getContentScriptEntrypoint(
936
952
  config,
937
- getEntrypointName(config.entrypointsDir, path5),
938
- path5
953
+ getEntrypointName(config.entrypointsDir, path6),
954
+ path6
939
955
  );
940
956
  break;
941
957
  case "content-script-style":
942
958
  entrypoint = {
943
959
  type,
944
- name: getEntrypointName(config.entrypointsDir, path5),
945
- inputPath: path5,
960
+ name: getEntrypointName(config.entrypointsDir, path6),
961
+ inputPath: path6,
946
962
  outputDir: (0, import_path8.resolve)(config.outDir, CONTENT_SCRIPT_OUT_DIR)
947
963
  };
948
964
  break;
949
965
  default:
950
966
  entrypoint = {
951
967
  type,
952
- name: getEntrypointName(config.entrypointsDir, path5),
953
- inputPath: path5,
968
+ name: getEntrypointName(config.entrypointsDir, path6),
969
+ inputPath: path6,
954
970
  outputDir: config.outDir
955
971
  };
956
972
  }
@@ -974,9 +990,9 @@ ${JSON.stringify(
974
990
  }
975
991
  return entrypoints;
976
992
  }
977
- async function getPopupEntrypoint(config, path5) {
993
+ async function getPopupEntrypoint(config, path6) {
978
994
  const options = {};
979
- const content = await import_fs_extra8.default.readFile(path5, "utf-8");
995
+ const content = await import_fs_extra8.default.readFile(path6, "utf-8");
980
996
  const { document } = (0, import_linkedom2.parseHTML)(content);
981
997
  const title = document.querySelector("title");
982
998
  if (title != null)
@@ -1000,13 +1016,13 @@ async function getPopupEntrypoint(config, path5) {
1000
1016
  type: "popup",
1001
1017
  name: "popup",
1002
1018
  options,
1003
- inputPath: path5,
1019
+ inputPath: path6,
1004
1020
  outputDir: config.outDir
1005
1021
  };
1006
1022
  }
1007
- async function getOptionsEntrypoint(config, path5) {
1023
+ async function getOptionsEntrypoint(config, path6) {
1008
1024
  const options = {};
1009
- const content = await import_fs_extra8.default.readFile(path5, "utf-8");
1025
+ const content = await import_fs_extra8.default.readFile(path6, "utf-8");
1010
1026
  const { document } = (0, import_linkedom2.parseHTML)(content);
1011
1027
  const openInTabContent = document.querySelector("meta[name='manifest.open_in_tab']")?.getAttribute("content");
1012
1028
  if (openInTabContent) {
@@ -1024,15 +1040,15 @@ async function getOptionsEntrypoint(config, path5) {
1024
1040
  type: "options",
1025
1041
  name: "options",
1026
1042
  options,
1027
- inputPath: path5,
1043
+ inputPath: path6,
1028
1044
  outputDir: config.outDir
1029
1045
  };
1030
1046
  }
1031
- async function getBackgroundEntrypoint(config, path5) {
1047
+ async function getBackgroundEntrypoint(config, path6) {
1032
1048
  let options = {};
1033
- if (path5 !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
1049
+ if (path6 !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
1034
1050
  const defaultExport = await importTsFile(
1035
- path5,
1051
+ path6,
1036
1052
  config
1037
1053
  );
1038
1054
  if (defaultExport == null) {
@@ -1044,14 +1060,14 @@ async function getBackgroundEntrypoint(config, path5) {
1044
1060
  return {
1045
1061
  type: "background",
1046
1062
  name: "background",
1047
- inputPath: path5,
1063
+ inputPath: path6,
1048
1064
  outputDir: config.outDir,
1049
1065
  options
1050
1066
  };
1051
1067
  }
1052
- async function getContentScriptEntrypoint(config, name, path5) {
1068
+ async function getContentScriptEntrypoint(config, name, path6) {
1053
1069
  const { main: _, ...options } = await importTsFile(
1054
- path5,
1070
+ path6,
1055
1071
  config
1056
1072
  );
1057
1073
  if (options == null) {
@@ -1059,8 +1075,8 @@ async function getContentScriptEntrypoint(config, name, path5) {
1059
1075
  }
1060
1076
  return {
1061
1077
  type: "content-script",
1062
- name: getEntrypointName(config.entrypointsDir, path5),
1063
- inputPath: path5,
1078
+ name: getEntrypointName(config.entrypointsDir, path6),
1079
+ inputPath: path6,
1064
1080
  outputDir: (0, import_path8.resolve)(config.outDir, CONTENT_SCRIPT_OUT_DIR),
1065
1081
  options
1066
1082
  };
@@ -1111,11 +1127,52 @@ var CONTENT_SCRIPT_OUT_DIR = "content-scripts";
1111
1127
  var import_unimport3 = require("unimport");
1112
1128
  var import_fs_extra9 = __toESM(require("fs-extra"), 1);
1113
1129
  var import_path9 = require("path");
1130
+ var import_node_path5 = __toESM(require("path"), 1);
1131
+
1132
+ // src/core/utils/i18n.ts
1133
+ var predefinedMessages = {
1134
+ "@@extension_id": {
1135
+ message: "<browser.runtime.id>",
1136
+ 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."
1137
+ },
1138
+ "@@ui_locale": {
1139
+ message: "<browser.i18n.getUiLocale()>",
1140
+ description: ""
1141
+ },
1142
+ "@@bidi_dir": {
1143
+ message: "<ltr|rtl>",
1144
+ 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.'
1145
+ },
1146
+ "@@bidi_reversed_dir": {
1147
+ message: "<rtl|ltr>",
1148
+ description: `If the @@bidi_dir is "ltr", then this is "rtl"; otherwise, it's "ltr".`
1149
+ },
1150
+ "@@bidi_start_edge": {
1151
+ message: "<left|right>",
1152
+ description: `If the @@bidi_dir is "ltr", then this is "left"; otherwise, it's "right".`
1153
+ },
1154
+ "@@bidi_end_edge": {
1155
+ message: "<right|left>",
1156
+ description: `If the @@bidi_dir is "ltr", then this is "right"; otherwise, it's "left".`
1157
+ }
1158
+ };
1159
+ function parseI18nMessages(messagesJson) {
1160
+ return Object.entries({
1161
+ ...predefinedMessages,
1162
+ ...messagesJson
1163
+ }).map(([name, details]) => ({
1164
+ name,
1165
+ ...details
1166
+ }));
1167
+ }
1168
+
1169
+ // src/core/build/generateTypesDir.ts
1114
1170
  async function generateTypesDir(entrypoints, config) {
1115
1171
  await import_fs_extra9.default.ensureDir(config.typesDir);
1116
1172
  const references = [];
1117
1173
  references.push(await writeImportsDeclarationFile(config));
1118
1174
  references.push(await writePathsDeclarationFile(entrypoints, config));
1175
+ references.push(await writeI18nDeclarationFile(config));
1119
1176
  references.push(await writeGlobalsDeclarationFile(config));
1120
1177
  const mainReference = await writeMainDeclarationFile(references, config);
1121
1178
  await writeTsConfigFile(mainReference, config);
@@ -1140,14 +1197,14 @@ async function writePathsDeclarationFile(entrypoints, config) {
1140
1197
  config.outDir,
1141
1198
  entry.inputPath.endsWith(".html") ? ".html" : ".js"
1142
1199
  )
1143
- ).concat(await getPublicFiles(config)).map(normalizePath2).map((path5) => ` | "/${path5}"`).sort().join("\n");
1200
+ ).concat(await getPublicFiles(config)).map(normalizePath2).map((path6) => ` | "/${path6}"`).sort().join("\n");
1144
1201
  const template = `// Generated by wxt
1145
1202
  import "wxt/browser";
1146
1203
 
1147
1204
  declare module "wxt/browser" {
1148
1205
  type PublicPath =
1149
1206
  {{ union }}
1150
- export interface ProjectRuntime extends Runtime.Static {
1207
+ export interface WxtRuntime extends Runtime.Static {
1151
1208
  getURL(path: PublicPath): string;
1152
1209
  }
1153
1210
  }
@@ -1158,6 +1215,59 @@ declare module "wxt/browser" {
1158
1215
  );
1159
1216
  return filePath;
1160
1217
  }
1218
+ async function writeI18nDeclarationFile(config) {
1219
+ const filePath = (0, import_path9.resolve)(config.typesDir, "i18n.d.ts");
1220
+ const defaultLocale = config.manifest.default_locale;
1221
+ const template = `// Generated by wxt
1222
+ import "wxt/browser";
1223
+
1224
+ declare module "wxt/browser" {
1225
+ /**
1226
+ * See https://developer.chrome.com/docs/extensions/reference/i18n/#method-getMessage
1227
+ */
1228
+ interface GetMessageOptions {
1229
+ /**
1230
+ * See https://developer.chrome.com/docs/extensions/reference/i18n/#method-getMessage
1231
+ */
1232
+ escapeLt?: boolean
1233
+ }
1234
+
1235
+ export interface WxtI18n extends I18n.Static {
1236
+ {{ overrides }}
1237
+ }
1238
+ }
1239
+ `;
1240
+ let messages;
1241
+ if (defaultLocale) {
1242
+ const defaultLocalePath = import_node_path5.default.resolve(
1243
+ config.publicDir,
1244
+ "_locales",
1245
+ defaultLocale,
1246
+ "messages.json"
1247
+ );
1248
+ const content = JSON.parse(await import_fs_extra9.default.readFile(defaultLocalePath, "utf-8"));
1249
+ messages = parseI18nMessages(content);
1250
+ } else {
1251
+ messages = parseI18nMessages({});
1252
+ }
1253
+ const overrides = messages.map((message) => {
1254
+ return ` /**
1255
+ * ${message.description ?? "No message description."}
1256
+ *
1257
+ * "${message.message}"
1258
+ */
1259
+ getMessage(
1260
+ messageName: "${message.name}",
1261
+ substitutions?: string | string[],
1262
+ options?: GetMessageOptions,
1263
+ ): string;`;
1264
+ });
1265
+ await import_fs_extra9.default.writeFile(
1266
+ filePath,
1267
+ template.replace("{{ overrides }}", overrides.join("\n"))
1268
+ );
1269
+ return filePath;
1270
+ }
1161
1271
  async function writeGlobalsDeclarationFile(config) {
1162
1272
  const filePath = (0, import_path9.resolve)(config.typesDir, "globals.d.ts");
1163
1273
  const globals = getGlobals(config);
@@ -1191,6 +1301,8 @@ async function writeMainDeclarationFile(references, config) {
1191
1301
  }
1192
1302
  async function writeTsConfigFile(mainReference, config) {
1193
1303
  const dir = config.wxtDir;
1304
+ const rootPath = normalizePath2((0, import_path9.relative)(dir, config.root));
1305
+ const srcPath = normalizePath2((0, import_path9.relative)(dir, config.srcDir));
1194
1306
  await import_fs_extra9.default.writeFile(
1195
1307
  (0, import_path9.resolve)(dir, "tsconfig.json"),
1196
1308
  `{
@@ -1205,16 +1317,15 @@ async function writeTsConfigFile(mainReference, config) {
1205
1317
  "strict": true,
1206
1318
  "lib": ["DOM", "WebWorker"],
1207
1319
  "skipLibCheck": true,
1208
- "baseUrl": "${normalizePath2((0, import_path9.relative)(dir, config.root))}",
1209
1320
  "paths": {
1210
- "@@": ["."],
1211
- "@@/*": ["./*"],
1212
- "~~": ["."],
1213
- "~~/*": ["./*"],
1214
- "@": ["${normalizePath2((0, import_path9.relative)(config.root, config.srcDir))}"],
1215
- "@/*": ["${normalizePath2((0, import_path9.relative)(config.root, config.srcDir))}/*"],
1216
- "~": ["${normalizePath2((0, import_path9.relative)(config.root, config.srcDir))}"],
1217
- "~/*": ["${normalizePath2((0, import_path9.relative)(config.root, config.srcDir))}/*"]
1321
+ "@@": ["${rootPath}"],
1322
+ "@@/*": ["${rootPath}/*"],
1323
+ "~~": ["${rootPath}"],
1324
+ "~~/*": ["${rootPath}/*"],
1325
+ "@": ["${srcPath}"],
1326
+ "@/*": ["${srcPath}/*"],
1327
+ "~": ["${srcPath}"],
1328
+ "~/*": ["${srcPath}/*"]
1218
1329
  }
1219
1330
  },
1220
1331
  "include": [
@@ -1312,10 +1423,10 @@ function mapWxtOptionsToContentScript(options) {
1312
1423
  }
1313
1424
 
1314
1425
  // src/core/utils/package.ts
1315
- var import_node_path5 = require("path");
1426
+ var import_node_path6 = require("path");
1316
1427
  var import_fs_extra10 = __toESM(require("fs-extra"), 1);
1317
1428
  async function getPackageJson(config) {
1318
- const file = (0, import_node_path5.resolve)(config.root, "package.json");
1429
+ const file = (0, import_node_path6.resolve)(config.root, "package.json");
1319
1430
  try {
1320
1431
  return await import_fs_extra10.default.readJson(file);
1321
1432
  } catch (err) {
@@ -1349,7 +1460,8 @@ async function generateMainfest(entrypoints, buildOutput, config) {
1349
1460
  version: pkg?.version && simplifyVersion(pkg.version),
1350
1461
  // Only add the version name to chromium and if the user hasn't specified a custom version.
1351
1462
  version_name: config.browser !== "firefox" && !config.manifest.version ? pkg?.version : void 0,
1352
- short_name: pkg?.shortName
1463
+ short_name: pkg?.shortName,
1464
+ icons: discoverIcons(buildOutput)
1353
1465
  },
1354
1466
  config.manifest
1355
1467
  );
@@ -1539,7 +1651,7 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
1539
1651
  map.set(hash, [script]);
1540
1652
  return map;
1541
1653
  }, /* @__PURE__ */ new Map());
1542
- manifest.content_scripts = Array.from(hashToEntrypointsMap.entries()).map(
1654
+ const newContentScripts = Array.from(hashToEntrypointsMap.entries()).map(
1543
1655
  ([, scripts]) => ({
1544
1656
  ...mapWxtOptionsToContentScript(scripts[0].options),
1545
1657
  // TOOD: Sorting css and js arrays here so we get consistent test results... but we
@@ -1550,9 +1662,46 @@ function addEntrypoints(manifest, entrypoints, buildOutput, config) {
1550
1662
  ).sort()
1551
1663
  })
1552
1664
  );
1665
+ if (newContentScripts.length >= 0) {
1666
+ manifest.content_scripts ??= [];
1667
+ manifest.content_scripts.push(...newContentScripts);
1668
+ }
1553
1669
  }
1554
1670
  }
1555
1671
  }
1672
+ function discoverIcons(buildOutput) {
1673
+ const icons = [];
1674
+ const iconRegex = [
1675
+ /^icon-([0-9]+)\.(png|bmp|jpeg|jpg|ico|gif)$/,
1676
+ // icon-16.png
1677
+ /^icon-([0-9]+)x[0-9]+\.(png|bmp|jpeg|jpg|ico|gif)$/,
1678
+ // icon-16x16.png
1679
+ /^icon@([0-9]+)w\.(png|bmp|jpeg|jpg|ico|gif)$/,
1680
+ // icon@16w.png
1681
+ /^icon@([0-9]+)h\.(png|bmp|jpeg|jpg|ico|gif)$/,
1682
+ // icon@16h.png
1683
+ /^icon@([0-9]+)\.(png|bmp|jpeg|jpg|ico|gif)$/,
1684
+ // icon@16.png
1685
+ /^icon[\/\\]([0-9]+)\.(png|bmp|jpeg|jpg|ico|gif)$/,
1686
+ // icon/16.png
1687
+ /^icon[\/\\]([0-9]+)x[0-9]+\.(png|bmp|jpeg|jpg|ico|gif)$/
1688
+ // icon/16x16.png
1689
+ ];
1690
+ buildOutput.publicAssets.forEach((asset) => {
1691
+ let size;
1692
+ for (const regex of iconRegex) {
1693
+ const match = asset.fileName.match(regex);
1694
+ if (match?.[1] != null) {
1695
+ size = match[1];
1696
+ break;
1697
+ }
1698
+ }
1699
+ if (size == null)
1700
+ return;
1701
+ icons.push([size, normalizePath2(asset.fileName)]);
1702
+ });
1703
+ return icons.length > 0 ? Object.fromEntries(icons) : void 0;
1704
+ }
1556
1705
  function addDevModeCsp(manifest, config) {
1557
1706
  const permission = `http://${config.server?.hostname ?? ""}/*`;
1558
1707
  const allowedCsp = config.server?.origin ?? "http://localhost:*";
@@ -1665,13 +1814,13 @@ function formatDuration(duration) {
1665
1814
  var import_path11 = require("path");
1666
1815
 
1667
1816
  // src/core/log/printFileList.ts
1668
- var import_node_path6 = __toESM(require("path"), 1);
1817
+ var import_node_path7 = __toESM(require("path"), 1);
1669
1818
  var import_picocolors = __toESM(require("picocolors"), 1);
1670
1819
  var import_fs_extra12 = __toESM(require("fs-extra"), 1);
1671
1820
  var import_filesize = require("filesize");
1672
1821
 
1673
1822
  // src/core/log/printTable.ts
1674
- function printTable(log, rows, gap = 2) {
1823
+ function printTable(log, header, rows, gap = 2) {
1675
1824
  if (rows.length === 0)
1676
1825
  return;
1677
1826
  const columnWidths = rows.reduce(
@@ -1693,17 +1842,18 @@ function printTable(log, rows, gap = 2) {
1693
1842
  if (i !== rows.length - 1)
1694
1843
  str += "\n";
1695
1844
  });
1696
- log(str);
1845
+ log(`${header}
1846
+ ${str}`);
1697
1847
  }
1698
1848
 
1699
1849
  // src/core/log/printFileList.ts
1700
- async function printFileList(log, baseDir, files) {
1850
+ async function printFileList(log, header, baseDir, files) {
1701
1851
  let totalSize = 0;
1702
1852
  const fileRows = await Promise.all(
1703
1853
  files.map(async (file, i) => {
1704
1854
  const parts = [
1705
- import_node_path6.default.relative(process.cwd(), baseDir) + import_node_path6.default.sep,
1706
- import_node_path6.default.relative(baseDir, file)
1855
+ import_node_path7.default.relative(process.cwd(), baseDir) + import_node_path7.default.sep,
1856
+ import_node_path7.default.relative(baseDir, file)
1707
1857
  ];
1708
1858
  const prefix = i === files.length - 1 ? " \u2514\u2500" : " \u251C\u2500";
1709
1859
  const color = getChunkColor(file);
@@ -1716,8 +1866,8 @@ async function printFileList(log, baseDir, files) {
1716
1866
  ];
1717
1867
  })
1718
1868
  );
1719
- printTable(log, fileRows);
1720
- log(`${import_picocolors.default.cyan("\u03A3 Total size:")} ${String((0, import_filesize.filesize)(totalSize))}`);
1869
+ fileRows.push([`${import_picocolors.default.cyan("\u03A3 Total size:")} ${String((0, import_filesize.filesize)(totalSize))}`]);
1870
+ printTable(log, header, fileRows);
1721
1871
  }
1722
1872
  var DEFAULT_COLOR = import_picocolors.default.blue;
1723
1873
  var CHUNK_COLORS = {
@@ -1732,7 +1882,7 @@ function getChunkColor(filename) {
1732
1882
  }
1733
1883
 
1734
1884
  // src/core/log/printBuildSummary.ts
1735
- async function printBuildSummary(output, config) {
1885
+ async function printBuildSummary(log, header, output, config) {
1736
1886
  const chunks = [
1737
1887
  ...output.steps.flatMap((step) => step.chunks),
1738
1888
  ...output.publicAssets
@@ -1745,7 +1895,7 @@ async function printBuildSummary(output, config) {
1745
1895
  return l.fileName.localeCompare(r.fileName);
1746
1896
  });
1747
1897
  const files = chunks.map((chunk) => (0, import_path11.resolve)(config.outDir, chunk.fileName));
1748
- await printFileList(config.logger.log, config.outDir, files);
1898
+ await printFileList(log, header, config.outDir, files);
1749
1899
  }
1750
1900
  var DEFAULT_SORT_WEIGHT = 100;
1751
1901
  var CHUNK_SORT_WEIGHTS = {
@@ -1776,10 +1926,12 @@ async function buildInternal(config) {
1776
1926
  const entrypoints = await findEntrypoints(config);
1777
1927
  const groups = groupEntrypoints(entrypoints);
1778
1928
  const { output } = await rebuild(config, groups, void 0);
1779
- config.logger.success(
1780
- `Built extension in ${formatDuration(Date.now() - startTime)}`
1929
+ await printBuildSummary(
1930
+ config.logger.success,
1931
+ `Built extension in ${formatDuration(Date.now() - startTime)}`,
1932
+ output,
1933
+ config
1781
1934
  );
1782
- await printBuildSummary(output, config);
1783
1935
  return output;
1784
1936
  }
1785
1937
  async function rebuild(config, entrypointGroups, existingOutput = {
@@ -1832,7 +1984,7 @@ function createWebExtRunner() {
1832
1984
  config.logger.warn("Cannot open safari automatically.");
1833
1985
  return;
1834
1986
  }
1835
- const webExtLogger = await import("web-ext/util/logger");
1987
+ const webExtLogger = await import("web-ext-run/util/logger");
1836
1988
  webExtLogger.consoleStream.write = ({ level, msg, name }) => {
1837
1989
  if (level >= ERROR_LOG_LEVEL)
1838
1990
  config.logger.error(name, msg);
@@ -1869,7 +2021,7 @@ function createWebExtRunner() {
1869
2021
  };
1870
2022
  config.logger.debug("web-ext config:", finalConfig);
1871
2023
  config.logger.debug("web-ext options:", options);
1872
- const webExt = await import("web-ext");
2024
+ const webExt = await import("web-ext-run");
1873
2025
  runner = await webExt.default.cmd.run(finalConfig, options);
1874
2026
  },
1875
2027
  async closeBrowser() {
@@ -1914,8 +2066,8 @@ async function setupServer(serverInfo, config) {
1914
2066
  const reloadExtension = () => {
1915
2067
  viteServer.ws.send("wxt:reload-extension");
1916
2068
  };
1917
- const reloadPage = (path5) => {
1918
- viteServer.ws.send("wxt:reload-page", path5);
2069
+ const reloadPage = (path6) => {
2070
+ viteServer.ws.send("wxt:reload-page", path6);
1919
2071
  };
1920
2072
  const reloadContentScript = (contentScript) => {
1921
2073
  viteServer.ws.send("wxt:reload-content-script", contentScript);
@@ -1961,13 +2113,13 @@ function reloadContentScripts(steps, config, server) {
1961
2113
  }
1962
2114
  function reloadHtmlPages(groups, server, config) {
1963
2115
  groups.flat().forEach((entry) => {
1964
- const path5 = getEntrypointBundlePath(entry, config.outDir, ".html");
1965
- server.reloadPage(path5);
2116
+ const path6 = getEntrypointBundlePath(entry, config.outDir, ".html");
2117
+ server.reloadPage(path6);
1966
2118
  });
1967
2119
  }
1968
2120
 
1969
2121
  // package.json
1970
- var version2 = "0.3.1";
2122
+ var version2 = "0.4.0";
1971
2123
 
1972
2124
  // src/core/utils/defineConfig.ts
1973
2125
  function defineConfig(config) {
@@ -2001,10 +2153,10 @@ async function createServer2(config) {
2001
2153
  server.ws.on("wxt:background-initialized", () => {
2002
2154
  reloadContentScripts(server.currentOutput.steps, internalConfig, server);
2003
2155
  });
2004
- server.watcher.on("all", async (event, path5, _stats) => {
2005
- if (path5.startsWith(internalConfig.outBaseDir))
2156
+ server.watcher.on("all", async (event, path6, _stats) => {
2157
+ if (path6.startsWith(internalConfig.outBaseDir))
2006
2158
  return;
2007
- changeQueue.push([event, path5]);
2159
+ changeQueue.push([event, path6]);
2008
2160
  await fileChangedMutex.runExclusive(async () => {
2009
2161
  const fileChanges = changeQueue.splice(0, changeQueue.length);
2010
2162
  if (fileChanges.length === 0)
@@ -2013,11 +2165,11 @@ async function createServer2(config) {
2013
2165
  if (changes.type === "no-change")
2014
2166
  return;
2015
2167
  internalConfig.logger.info(
2016
- `Changed: ${Array.from(new Set(fileChanges.map((change) => change[1]))).map((file) => import_picocolors3.default.dim((0, import_node_path7.relative)(internalConfig.root, file))).join(", ")}`
2168
+ `Changed: ${Array.from(new Set(fileChanges.map((change) => change[1]))).map((file) => import_picocolors3.default.dim((0, import_node_path8.relative)(internalConfig.root, file))).join(", ")}`
2017
2169
  );
2018
2170
  const rebuiltNames = changes.rebuildGroups.flat().map((entry) => {
2019
2171
  return import_picocolors3.default.cyan(
2020
- (0, import_node_path7.relative)(internalConfig.outDir, getEntrypointOutputFile(entry, ""))
2172
+ (0, import_node_path8.relative)(internalConfig.outDir, getEntrypointOutputFile(entry, ""))
2021
2173
  );
2022
2174
  }).join(import_picocolors3.default.dim(", "));
2023
2175
  internalConfig = await getLatestInternalConfig();