wxt 0.11.1 → 0.12.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/bin/wxt.mjs ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/cli.js';
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.11.1";
2
+ var version = "0.12.0";
3
3
 
4
4
  // src/core/utils/arrays.ts
5
5
  function every(array, predicate) {
@@ -1029,7 +1029,8 @@ async function craeteViteBuilder(inlineConfig, userConfig, wxtConfig) {
1029
1029
  devHtmlPrerender(wxtConfig),
1030
1030
  unimport(wxtConfig),
1031
1031
  virtualEntrypoint("background", wxtConfig),
1032
- virtualEntrypoint("content-script", wxtConfig),
1032
+ virtualEntrypoint("content-script-isolated-world", wxtConfig),
1033
+ virtualEntrypoint("content-script-main-world", wxtConfig),
1033
1034
  virtualEntrypoint("unlisted-script", wxtConfig),
1034
1035
  devServerGlobals(wxtConfig),
1035
1036
  tsconfigPaths(wxtConfig),
@@ -1043,12 +1044,17 @@ async function craeteViteBuilder(inlineConfig, userConfig, wxtConfig) {
1043
1044
  return config;
1044
1045
  };
1045
1046
  const getLibModeConfig = (entrypoint) => {
1046
- const isVirtual = [
1047
- "background",
1048
- "content-script",
1049
- "unlisted-script"
1050
- ].includes(entrypoint.type);
1051
- const entry = isVirtual ? `virtual:wxt-${entrypoint.type}?${entrypoint.inputPath}` : entrypoint.inputPath;
1047
+ let virtualEntrypointType;
1048
+ switch (entrypoint.type) {
1049
+ case "background":
1050
+ case "unlisted-script":
1051
+ virtualEntrypointType = entrypoint.type;
1052
+ break;
1053
+ case "content-script":
1054
+ virtualEntrypointType = entrypoint.options.world === "MAIN" ? "content-script-main-world" : "content-script-isolated-world";
1055
+ break;
1056
+ }
1057
+ const entry = virtualEntrypointType ? `virtual:wxt-${virtualEntrypointType}?${entrypoint.inputPath}` : entrypoint.inputPath;
1052
1058
  const plugins = [
1053
1059
  entrypointGroupGlobals(entrypoint)
1054
1060
  ];
@@ -1209,7 +1215,10 @@ async function getInternalConfig(inlineConfig, command, server) {
1209
1215
  const { config: loadedConfig, ...metadata } = await loadConfig({
1210
1216
  name: "wxt",
1211
1217
  cwd: inlineConfig.root ?? process.cwd(),
1212
- rcFile: false
1218
+ rcFile: false,
1219
+ jitiOptions: {
1220
+ esmResolve: true
1221
+ }
1213
1222
  });
1214
1223
  userConfig = loadedConfig ?? {};
1215
1224
  userConfigMetadata = metadata;
@@ -1418,7 +1427,7 @@ var ENTRY_TYPE_TO_GROUP_MAP = {
1418
1427
  import createJITI from "jiti";
1419
1428
  import { createUnimport as createUnimport3 } from "unimport";
1420
1429
  import fs7 from "fs-extra";
1421
- import { resolve as resolve8 } from "path";
1430
+ import { resolve as resolve8 } from "node:path";
1422
1431
 
1423
1432
  // src/core/utils/strings.ts
1424
1433
  function kebabCaseAlphanumeric(str) {
@@ -1432,14 +1441,14 @@ function removeImportStatements(text) {
1432
1441
  }
1433
1442
  function removeProjectImportStatements(text) {
1434
1443
  const noImports = removeImportStatements(text);
1435
- return `import { defineContentScript, defineBackground } from 'wxt/client';
1436
- import { defineUnlistedScript } from 'wxt/sandbox';
1444
+ return `import { defineUnlistedScript, defineContentScript, defineBackground } from 'wxt/sandbox';
1437
1445
 
1438
1446
  ${noImports}`;
1439
1447
  }
1440
1448
 
1441
1449
  // src/core/utils/building/import-entrypoint.ts
1442
1450
  import { transformSync } from "esbuild";
1451
+ import { fileURLToPath } from "node:url";
1443
1452
  async function importEntrypointFile(path6, config) {
1444
1453
  config.logger.debug("Loading file metadata:", path6);
1445
1454
  const normalPath = normalizePath(path6);
@@ -1455,30 +1464,42 @@ async function importEntrypointFile(path6, config) {
1455
1464
  config.logger.debug(
1456
1465
  ["Text:", text, "No imports:", textNoImports, "Code:", code].join("\n")
1457
1466
  );
1458
- const jiti = createJITI(__filename, {
1459
- cache: false,
1460
- debug: config.debug,
1461
- esmResolve: true,
1462
- alias: {
1463
- "webextension-polyfill": resolve8(
1464
- config.root,
1465
- "node_modules/wxt/dist/virtual/mock-browser.js"
1466
- )
1467
- },
1468
- // Continue using node to load TS files even if `bun run --bun` is detected. Jiti does not
1469
- // respect the custom transform function when using it's native bun option.
1470
- experimentalBun: false,
1471
- // List of extensions to transform with esbuild
1472
- extensions: [".ts", ".cts", ".mts", ".tsx", ".js", ".cjs", ".mjs", ".jsx"],
1473
- transform(opts) {
1474
- const isEntrypoint = opts.filename === normalPath;
1475
- return transformSync(
1476
- // Use modified source code for entrypoints
1477
- isEntrypoint ? code : opts.source,
1478
- getEsbuildOptions(opts)
1479
- );
1467
+ const jiti = createJITI(
1468
+ typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url),
1469
+ {
1470
+ cache: false,
1471
+ debug: config.debug,
1472
+ esmResolve: true,
1473
+ alias: {
1474
+ "webextension-polyfill": resolve8(
1475
+ config.root,
1476
+ "node_modules/wxt/dist/virtual/mock-browser.js"
1477
+ )
1478
+ },
1479
+ // Continue using node to load TS files even if `bun run --bun` is detected. Jiti does not
1480
+ // respect the custom transform function when using it's native bun option.
1481
+ experimentalBun: false,
1482
+ // List of extensions to transform with esbuild
1483
+ extensions: [
1484
+ ".ts",
1485
+ ".cts",
1486
+ ".mts",
1487
+ ".tsx",
1488
+ ".js",
1489
+ ".cjs",
1490
+ ".mjs",
1491
+ ".jsx"
1492
+ ],
1493
+ transform(opts) {
1494
+ const isEntrypoint = opts.filename === normalPath;
1495
+ return transformSync(
1496
+ // Use modified source code for entrypoints
1497
+ isEntrypoint ? code : opts.source,
1498
+ getEsbuildOptions(opts)
1499
+ );
1500
+ }
1480
1501
  }
1481
- });
1502
+ );
1482
1503
  try {
1483
1504
  const res = await jiti(path6);
1484
1505
  return res.default;
@@ -2203,51 +2224,47 @@ async function combineAnalysisStats(config) {
2203
2224
  // src/core/utils/building/find-entrypoints.ts
2204
2225
  import glob3 from "fast-glob";
2205
2226
  async function findEntrypoints(config) {
2206
- const relativePaths = await glob3("**/*", {
2227
+ const relativePaths = await glob3(Object.keys(PATH_GLOB_TO_TYPE_MAP), {
2207
2228
  cwd: config.entrypointsDir
2208
2229
  });
2209
2230
  relativePaths.sort();
2210
2231
  const pathGlobs = Object.keys(PATH_GLOB_TO_TYPE_MAP);
2211
- let hasBackground = false;
2212
- const possibleEntrypoints = await Promise.all(
2213
- relativePaths.map(async (relativePath) => {
2214
- const path6 = resolve12(config.entrypointsDir, relativePath);
2215
- const matchingGlob = pathGlobs.find(
2216
- (glob4) => minimatch(relativePath, glob4)
2217
- );
2218
- if (matchingGlob == null) {
2219
- config.logger.warn(
2220
- `${relativePath} does not match any known entrypoint. Known entrypoints:
2221
- ${JSON.stringify(
2222
- PATH_GLOB_TO_TYPE_MAP,
2223
- null,
2224
- 2
2225
- )}`
2226
- );
2227
- return;
2228
- }
2232
+ const entrypointInfos = relativePaths.reduce((results, relativePath) => {
2233
+ const inputPath = resolve12(config.entrypointsDir, relativePath);
2234
+ const name = getEntrypointName(config.entrypointsDir, inputPath);
2235
+ const matchingGlob = pathGlobs.find(
2236
+ (glob4) => minimatch(relativePath, glob4)
2237
+ );
2238
+ if (matchingGlob) {
2229
2239
  const type = PATH_GLOB_TO_TYPE_MAP[matchingGlob];
2230
- if (type === "ignored")
2231
- return;
2240
+ results.push({ name, inputPath, type });
2241
+ }
2242
+ return results;
2243
+ }, []);
2244
+ preventNoEntrypoints(config, entrypointInfos);
2245
+ preventDuplicateEntrypointNames(config, entrypointInfos);
2246
+ let hasBackground = false;
2247
+ const entrypoints = await Promise.all(
2248
+ entrypointInfos.map(async (info) => {
2249
+ const { type } = info;
2232
2250
  switch (type) {
2233
2251
  case "popup":
2234
- return await getPopupEntrypoint(config, path6);
2252
+ return await getPopupEntrypoint(config, info);
2235
2253
  case "options":
2236
- return await getOptionsEntrypoint(config, path6);
2254
+ return await getOptionsEntrypoint(config, info);
2237
2255
  case "background":
2238
2256
  hasBackground = true;
2239
- return await getBackgroundEntrypoint(config, path6);
2257
+ return await getBackgroundEntrypoint(config, info);
2240
2258
  case "content-script":
2241
- return await getContentScriptEntrypoint(config, path6);
2259
+ return await getContentScriptEntrypoint(config, info);
2242
2260
  case "unlisted-page":
2243
- return await getUnlistedPageEntrypoint(config, path6);
2261
+ return await getUnlistedPageEntrypoint(config, info);
2244
2262
  case "unlisted-script":
2245
- return await getUnlistedScriptEntrypoint(config, path6);
2263
+ return await getUnlistedScriptEntrypoint(config, info);
2246
2264
  case "content-script-style":
2247
2265
  return {
2266
+ ...info,
2248
2267
  type,
2249
- name: getEntrypointName(config.entrypointsDir, path6),
2250
- inputPath: path6,
2251
2268
  outputDir: resolve12(config.outDir, CONTENT_SCRIPT_OUT_DIR),
2252
2269
  options: {
2253
2270
  include: void 0,
@@ -2256,9 +2273,8 @@ ${JSON.stringify(
2256
2273
  };
2257
2274
  default:
2258
2275
  return {
2276
+ ...info,
2259
2277
  type,
2260
- name: getEntrypointName(config.entrypointsDir, path6),
2261
- inputPath: path6,
2262
2278
  outputDir: config.outDir,
2263
2279
  options: {
2264
2280
  include: void 0,
@@ -2268,25 +2284,13 @@ ${JSON.stringify(
2268
2284
  }
2269
2285
  })
2270
2286
  );
2271
- const entrypoints = possibleEntrypoints.filter(
2272
- (entry) => !!entry
2273
- );
2274
- const existingNames = {};
2275
- entrypoints.forEach((entrypoint) => {
2276
- const withSameName = existingNames[entrypoint.name];
2277
- if (withSameName) {
2278
- throw Error(
2279
- `Multiple entrypoints with the name "${entrypoint.name}" detected, but only one is allowed: ${[
2280
- relative4(config.root, withSameName.inputPath),
2281
- relative4(config.root, entrypoint.inputPath)
2282
- ].join(", ")}`
2283
- );
2284
- }
2285
- existingNames[entrypoint.name] = entrypoint;
2286
- });
2287
2287
  if (config.command === "serve" && !hasBackground) {
2288
2288
  entrypoints.push(
2289
- await getBackgroundEntrypoint(config, VIRTUAL_NOOP_BACKGROUND_MODULE_ID)
2289
+ await getBackgroundEntrypoint(config, {
2290
+ inputPath: VIRTUAL_NOOP_BACKGROUND_MODULE_ID,
2291
+ name: "background",
2292
+ type: "background"
2293
+ })
2290
2294
  );
2291
2295
  }
2292
2296
  config.logger.debug("All entrypoints:", entrypoints);
@@ -2309,6 +2313,41 @@ ${JSON.stringify(
2309
2313
  config.logger.debug(`${config.browser} entrypoints:`, targetEntrypoints);
2310
2314
  return targetEntrypoints;
2311
2315
  }
2316
+ function preventDuplicateEntrypointNames(config, files) {
2317
+ const namesToPaths = files.reduce(
2318
+ (map, { name, inputPath }) => {
2319
+ map[name] ??= [];
2320
+ map[name].push(inputPath);
2321
+ return map;
2322
+ },
2323
+ {}
2324
+ );
2325
+ const errorLines = Object.entries(namesToPaths).reduce(
2326
+ (lines, [name, absolutePaths]) => {
2327
+ if (absolutePaths.length > 1) {
2328
+ lines.push(`- ${name}`);
2329
+ absolutePaths.forEach((absolutePath) => {
2330
+ lines.push(` - ${relative4(config.root, absolutePath)}`);
2331
+ });
2332
+ }
2333
+ return lines;
2334
+ },
2335
+ []
2336
+ );
2337
+ if (errorLines.length > 0) {
2338
+ const errorContent = errorLines.join("\n");
2339
+ throw Error(
2340
+ `Multiple entrypoints with the same name detected, only one entrypoint for each name is allowed.
2341
+
2342
+ ${errorContent}`
2343
+ );
2344
+ }
2345
+ }
2346
+ function preventNoEntrypoints(config, files) {
2347
+ if (files.length === 0) {
2348
+ throw Error(`No entrypoints found in ${config.entrypointsDir}`);
2349
+ }
2350
+ }
2312
2351
  function getHtmlBaseOptions(document) {
2313
2352
  const options = {};
2314
2353
  const includeContent = document.querySelector("meta[name='manifest.include']")?.getAttribute("content");
@@ -2321,8 +2360,8 @@ function getHtmlBaseOptions(document) {
2321
2360
  }
2322
2361
  return options;
2323
2362
  }
2324
- async function getPopupEntrypoint(config, path6) {
2325
- const content = await fs12.readFile(path6, "utf-8");
2363
+ async function getPopupEntrypoint(config, { inputPath, name }) {
2364
+ const content = await fs12.readFile(inputPath, "utf-8");
2326
2365
  const { document } = parseHTML2(content);
2327
2366
  const options = getHtmlBaseOptions(document);
2328
2367
  const title = document.querySelector("title");
@@ -2351,12 +2390,12 @@ async function getPopupEntrypoint(config, path6) {
2351
2390
  type: "popup",
2352
2391
  name: "popup",
2353
2392
  options,
2354
- inputPath: path6,
2393
+ inputPath,
2355
2394
  outputDir: config.outDir
2356
2395
  };
2357
2396
  }
2358
- async function getOptionsEntrypoint(config, path6) {
2359
- const content = await fs12.readFile(path6, "utf-8");
2397
+ async function getOptionsEntrypoint(config, { inputPath, name }) {
2398
+ const content = await fs12.readFile(inputPath, "utf-8");
2360
2399
  const { document } = parseHTML2(content);
2361
2400
  const options = getHtmlBaseOptions(document);
2362
2401
  const openInTabContent = document.querySelector("meta[name='manifest.open_in_tab']")?.getAttribute("content");
@@ -2375,25 +2414,24 @@ async function getOptionsEntrypoint(config, path6) {
2375
2414
  type: "options",
2376
2415
  name: "options",
2377
2416
  options,
2378
- inputPath: path6,
2417
+ inputPath,
2379
2418
  outputDir: config.outDir
2380
2419
  };
2381
2420
  }
2382
- async function getUnlistedPageEntrypoint(config, path6) {
2383
- const content = await fs12.readFile(path6, "utf-8");
2421
+ async function getUnlistedPageEntrypoint(config, { inputPath, name }) {
2422
+ const content = await fs12.readFile(inputPath, "utf-8");
2384
2423
  const { document } = parseHTML2(content);
2385
2424
  return {
2386
2425
  type: "unlisted-page",
2387
- name: getEntrypointName(config.entrypointsDir, path6),
2388
- inputPath: path6,
2426
+ name: getEntrypointName(config.entrypointsDir, inputPath),
2427
+ inputPath,
2389
2428
  outputDir: config.outDir,
2390
2429
  options: getHtmlBaseOptions(document)
2391
2430
  };
2392
2431
  }
2393
- async function getUnlistedScriptEntrypoint(config, path6) {
2394
- const name = getEntrypointName(config.entrypointsDir, path6);
2432
+ async function getUnlistedScriptEntrypoint(config, { inputPath, name }) {
2395
2433
  const defaultExport = await importEntrypointFile(
2396
- path6,
2434
+ inputPath,
2397
2435
  config
2398
2436
  );
2399
2437
  if (defaultExport == null) {
@@ -2406,17 +2444,16 @@ async function getUnlistedScriptEntrypoint(config, path6) {
2406
2444
  return {
2407
2445
  type: "unlisted-script",
2408
2446
  name,
2409
- inputPath: path6,
2447
+ inputPath,
2410
2448
  outputDir: config.outDir,
2411
2449
  options
2412
2450
  };
2413
2451
  }
2414
- async function getBackgroundEntrypoint(config, path6) {
2415
- const name = "background";
2452
+ async function getBackgroundEntrypoint(config, { inputPath, name }) {
2416
2453
  let options = {};
2417
- if (path6 !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
2454
+ if (inputPath !== VIRTUAL_NOOP_BACKGROUND_MODULE_ID) {
2418
2455
  const defaultExport = await importEntrypointFile(
2419
- path6,
2456
+ inputPath,
2420
2457
  config
2421
2458
  );
2422
2459
  if (defaultExport == null) {
@@ -2430,7 +2467,7 @@ async function getBackgroundEntrypoint(config, path6) {
2430
2467
  return {
2431
2468
  type: "background",
2432
2469
  name,
2433
- inputPath: path6,
2470
+ inputPath,
2434
2471
  outputDir: config.outDir,
2435
2472
  options: {
2436
2473
  ...options,
@@ -2439,9 +2476,8 @@ async function getBackgroundEntrypoint(config, path6) {
2439
2476
  }
2440
2477
  };
2441
2478
  }
2442
- async function getContentScriptEntrypoint(config, path6) {
2443
- const name = getEntrypointName(config.entrypointsDir, path6);
2444
- const { main: _, ...options } = await importEntrypointFile(path6, config);
2479
+ async function getContentScriptEntrypoint(config, { inputPath, name }) {
2480
+ const { main: _, ...options } = await importEntrypointFile(inputPath, config);
2445
2481
  if (options == null) {
2446
2482
  throw Error(
2447
2483
  `${name}: Default export not found, did you forget to call "export default defineContentScript(...)"?`
@@ -2450,7 +2486,7 @@ async function getContentScriptEntrypoint(config, path6) {
2450
2486
  return {
2451
2487
  type: "content-script",
2452
2488
  name,
2453
- inputPath: path6,
2489
+ inputPath,
2454
2490
  outputDir: resolve12(config.outDir, CONTENT_SCRIPT_OUT_DIR),
2455
2491
  options
2456
2492
  };
@@ -2489,12 +2525,10 @@ var PATH_GLOB_TO_TYPE_MAP = {
2489
2525
  "options/index.html": "options",
2490
2526
  "*.html": "unlisted-page",
2491
2527
  "*/index.html": "unlisted-page",
2492
- "*.[jt]s": "unlisted-script",
2493
- "*/index.ts": "unlisted-script",
2528
+ "*.[jt]s?(x)": "unlisted-script",
2529
+ "*/index.[jt]s?(x)": "unlisted-script",
2494
2530
  [`*.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style",
2495
- [`*/index.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style",
2496
- // Don't warn about any files in subdirectories, like CSS or JS entrypoints for HTML files or tests
2497
- "*/**": "ignored"
2531
+ [`*/index.${CSS_EXTENSIONS_PATTERN}`]: "unlisted-style"
2498
2532
  };
2499
2533
  var CONTENT_SCRIPT_OUT_DIR = "content-scripts";
2500
2534