wxt 0.16.8 → 0.16.9

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
@@ -229,6 +229,14 @@ function resolvePerBrowserOption(option, browser) {
229
229
  return option[browser];
230
230
  return option;
231
231
  }
232
+ function resolvePerBrowserOptions(options, browser) {
233
+ return Object.fromEntries(
234
+ Object.entries(options).map(([key, value]) => [
235
+ key,
236
+ key === "defaultIcon" ? value : resolvePerBrowserOption(value, browser)
237
+ ])
238
+ );
239
+ }
232
240
 
233
241
  // src/core/utils/constants.ts
234
242
  var VIRTUAL_NOOP_BACKGROUND_MODULE_ID = "virtual:user-background";
@@ -267,6 +275,8 @@ async function findEntrypoints() {
267
275
  switch (type) {
268
276
  case "popup":
269
277
  return await getPopupEntrypoint(info);
278
+ case "sidepanel":
279
+ return await getSidepanelEntrypoint(info);
270
280
  case "options":
271
281
  return await getOptionsEntrypoint(info);
272
282
  case "background":
@@ -377,100 +387,66 @@ function preventNoEntrypoints(files) {
377
387
  throw Error(`No entrypoints found in ${wxt.config.entrypointsDir}`);
378
388
  }
379
389
  }
380
- function getHtmlBaseOptions(document) {
381
- const options = {};
382
- const includeContent = document.querySelector("meta[name='manifest.include']")?.getAttribute("content");
383
- if (includeContent) {
384
- options.include = JSON5.parse(includeContent);
385
- }
386
- const excludeContent = document.querySelector("meta[name='manifest.exclude']")?.getAttribute("content");
387
- if (excludeContent) {
388
- options.exclude = JSON5.parse(excludeContent);
389
- }
390
- return options;
391
- }
392
- async function getPopupEntrypoint({
393
- inputPath,
394
- name,
395
- skipped
396
- }) {
397
- const content = await fs3.readFile(inputPath, "utf-8");
398
- const { document } = parseHTML(content);
399
- const options = getHtmlBaseOptions(document);
400
- const title = document.querySelector("title");
401
- if (title != null)
402
- options.defaultTitle = title.textContent ?? void 0;
403
- const defaultIconContent = document.querySelector("meta[name='manifest.default_icon']")?.getAttribute("content");
404
- if (defaultIconContent) {
405
- try {
406
- options.defaultIcon = JSON5.parse(defaultIconContent);
407
- } catch (err) {
408
- wxt.logger.fatal(
409
- `Failed to parse default_icon meta tag content as JSON5. content=${defaultIconContent}`,
410
- err
411
- );
390
+ async function getPopupEntrypoint(info) {
391
+ const options = await getHtmlEntrypointOptions(
392
+ info,
393
+ {
394
+ browserStyle: "browse_style",
395
+ exclude: "exclude",
396
+ include: "include",
397
+ defaultIcon: "default_icon",
398
+ defaultTitle: "default_title",
399
+ mv2Key: "type"
400
+ },
401
+ {
402
+ defaultTitle: (document) => document.querySelector("title")?.textContent || void 0
403
+ },
404
+ {
405
+ defaultTitle: (content) => content,
406
+ mv2Key: (content) => content === "page_action" ? "page_action" : "browser_action"
412
407
  }
413
- }
414
- const mv2TypeContent = document.querySelector("meta[name='manifest.type']")?.getAttribute("content");
415
- if (mv2TypeContent) {
416
- options.mv2Key = mv2TypeContent === "page_action" ? "page_action" : "browser_action";
417
- }
418
- const browserStyleContent = document.querySelector("meta[name='manifest.browser_style']")?.getAttribute("content");
419
- if (browserStyleContent) {
420
- options.browserStyle = browserStyleContent === "true";
421
- }
408
+ );
422
409
  return {
423
410
  type: "popup",
424
411
  name: "popup",
425
- options,
426
- inputPath,
412
+ options: resolvePerBrowserOptions(options, wxt.config.browser),
413
+ inputPath: info.inputPath,
427
414
  outputDir: wxt.config.outDir,
428
- skipped
415
+ skipped: info.skipped
429
416
  };
430
417
  }
431
- async function getOptionsEntrypoint({
432
- inputPath,
433
- name,
434
- skipped
435
- }) {
436
- const content = await fs3.readFile(inputPath, "utf-8");
437
- const { document } = parseHTML(content);
438
- const options = getHtmlBaseOptions(document);
439
- const openInTabContent = document.querySelector("meta[name='manifest.open_in_tab']")?.getAttribute("content");
440
- if (openInTabContent) {
441
- options.openInTab = openInTabContent === "true";
442
- }
443
- const chromeStyleContent = document.querySelector("meta[name='manifest.chrome_style']")?.getAttribute("content");
444
- if (chromeStyleContent) {
445
- options.chromeStyle = chromeStyleContent === "true";
446
- }
447
- const browserStyleContent = document.querySelector("meta[name='manifest.browser_style']")?.getAttribute("content");
448
- if (browserStyleContent) {
449
- options.browserStyle = browserStyleContent === "true";
450
- }
418
+ async function getOptionsEntrypoint(info) {
419
+ const options = await getHtmlEntrypointOptions(
420
+ info,
421
+ {
422
+ browserStyle: "browse_style",
423
+ chromeStyle: "chrome_style",
424
+ exclude: "exclude",
425
+ include: "include",
426
+ openInTab: "open_in_tab"
427
+ }
428
+ );
451
429
  return {
452
430
  type: "options",
453
431
  name: "options",
454
- options,
455
- inputPath,
432
+ options: resolvePerBrowserOptions(options, wxt.config.browser),
433
+ inputPath: info.inputPath,
456
434
  outputDir: wxt.config.outDir,
457
- skipped
435
+ skipped: info.skipped
458
436
  };
459
437
  }
460
- async function getUnlistedPageEntrypoint({
461
- inputPath,
462
- name,
463
- skipped
464
- }) {
465
- const content = await fs3.readFile(inputPath, "utf-8");
466
- const { document } = parseHTML(content);
438
+ async function getUnlistedPageEntrypoint(info) {
439
+ const options = await getHtmlEntrypointOptions(info, {
440
+ exclude: "exclude",
441
+ include: "include"
442
+ });
467
443
  return {
468
444
  type: "unlisted-page",
469
- name: getEntrypointName(wxt.config.entrypointsDir, inputPath),
470
- inputPath,
445
+ name: info.name,
446
+ inputPath: info.inputPath,
471
447
  outputDir: wxt.config.outDir,
472
- options: getHtmlBaseOptions(document),
473
- skipped
448
+ options,
449
+ skipped: info.skipped
474
450
  };
475
451
  }
476
452
  async function getUnlistedScriptEntrypoint({
@@ -484,14 +460,13 @@ async function getUnlistedScriptEntrypoint({
484
460
  `${name}: Default export not found, did you forget to call "export default defineUnlistedScript(...)"?`
485
461
  );
486
462
  }
487
- const { main: _, ...moduleOptions } = defaultExport;
488
- const options = moduleOptions;
463
+ const { main: _, ...options } = defaultExport;
489
464
  return {
490
465
  type: "unlisted-script",
491
466
  name,
492
467
  inputPath,
493
468
  outputDir: wxt.config.outDir,
494
- options,
469
+ options: resolvePerBrowserOptions(options, wxt.config.browser),
495
470
  skipped
496
471
  };
497
472
  }
@@ -519,14 +494,7 @@ async function getBackgroundEntrypoint({
519
494
  name,
520
495
  inputPath,
521
496
  outputDir: wxt.config.outDir,
522
- options: {
523
- ...options,
524
- type: resolvePerBrowserOption(options.type, wxt.config.browser),
525
- persistent: resolvePerBrowserOption(
526
- options.persistent,
527
- wxt.config.browser
528
- )
529
- },
497
+ options: resolvePerBrowserOptions(options, wxt.config.browser),
530
498
  skipped
531
499
  };
532
500
  }
@@ -546,10 +514,58 @@ async function getContentScriptEntrypoint({
546
514
  name,
547
515
  inputPath,
548
516
  outputDir: resolve3(wxt.config.outDir, CONTENT_SCRIPT_OUT_DIR),
549
- options,
517
+ options: resolvePerBrowserOptions(options, wxt.config.browser),
550
518
  skipped
551
519
  };
552
520
  }
521
+ async function getSidepanelEntrypoint(info) {
522
+ const options = await getHtmlEntrypointOptions(
523
+ info,
524
+ {
525
+ browserStyle: "browse_style",
526
+ exclude: "exclude",
527
+ include: "include",
528
+ defaultIcon: "default_icon",
529
+ defaultTitle: "default_title",
530
+ openAtInstall: "open_at_install"
531
+ },
532
+ {
533
+ defaultTitle: (document) => document.querySelector("title")?.textContent || void 0
534
+ },
535
+ {
536
+ defaultTitle: (content) => content
537
+ }
538
+ );
539
+ return {
540
+ type: "sidepanel",
541
+ name: info.name,
542
+ options: resolvePerBrowserOptions(options, wxt.config.browser),
543
+ inputPath: info.inputPath,
544
+ outputDir: wxt.config.outDir,
545
+ skipped: info.skipped
546
+ };
547
+ }
548
+ async function getHtmlEntrypointOptions(info, keyMap, queries, parsers) {
549
+ const content = await fs3.readFile(info.inputPath, "utf-8");
550
+ const { document } = parseHTML(content);
551
+ const options = {};
552
+ const defaultQuery = (manifestKey) => document.querySelector(`meta[name='manifest.${manifestKey}']`)?.getAttribute("content");
553
+ Object.entries(keyMap).forEach(([_key, manifestKey]) => {
554
+ const key = _key;
555
+ const content2 = queries?.[key] ? queries[key](document, manifestKey) : defaultQuery(manifestKey);
556
+ if (content2) {
557
+ try {
558
+ options[key] = (parsers?.[key] ?? JSON5.parse)(content2);
559
+ } catch (err) {
560
+ wxt.logger.fatal(
561
+ `Failed to parse meta tag content. Usually this means you have invalid JSON5 content (content=${content2})`,
562
+ err
563
+ );
564
+ }
565
+ }
566
+ });
567
+ return options;
568
+ }
553
569
  var PATH_GLOB_TO_TYPE_MAP = {
554
570
  "sandbox.html": "sandbox",
555
571
  "sandbox/index.html": "sandbox",
@@ -2152,7 +2168,7 @@ function getChunkSortWeight(filename) {
2152
2168
  import pc4 from "picocolors";
2153
2169
 
2154
2170
  // package.json
2155
- var version = "0.16.8";
2171
+ var version = "0.16.9";
2156
2172
 
2157
2173
  // src/core/utils/log/printHeader.ts
2158
2174
  import { consola as consola2 } from "consola";
@@ -2213,7 +2229,11 @@ var ContentSecurityPolicy = class _ContentSecurityPolicy {
2213
2229
 
2214
2230
  // src/core/utils/content-scripts.ts
2215
2231
  function hashContentScriptOptions(options) {
2216
- const simplifiedOptions = mapWxtOptionsToContentScript(options);
2232
+ const simplifiedOptions = mapWxtOptionsToContentScript(
2233
+ options,
2234
+ void 0,
2235
+ void 0
2236
+ );
2217
2237
  Object.keys(simplifiedOptions).forEach((key) => {
2218
2238
  if (simplifiedOptions[key] == null)
2219
2239
  delete simplifiedOptions[key];
@@ -2239,32 +2259,31 @@ function hashContentScriptOptions(options) {
2239
2259
  }).sort((l, r) => l[0].localeCompare(r[0]))
2240
2260
  );
2241
2261
  }
2242
- function mapWxtOptionsToContentScript(options) {
2262
+ function mapWxtOptionsToContentScript(options, js, css) {
2243
2263
  return {
2244
- matches: resolvePerBrowserOption(options.matches, wxt.config.browser),
2245
- all_frames: resolvePerBrowserOption(options.allFrames, wxt.config.browser),
2246
- match_about_blank: resolvePerBrowserOption(
2247
- options.matchAboutBlank,
2248
- wxt.config.browser
2249
- ),
2250
- exclude_globs: resolvePerBrowserOption(
2251
- options.excludeGlobs,
2252
- wxt.config.browser
2253
- ),
2254
- exclude_matches: resolvePerBrowserOption(
2255
- options.excludeMatches,
2256
- wxt.config.browser
2257
- ),
2258
- include_globs: resolvePerBrowserOption(
2259
- options.includeGlobs,
2260
- wxt.config.browser
2261
- ),
2262
- run_at: resolvePerBrowserOption(options.runAt, wxt.config.browser),
2264
+ matches: options.matches,
2265
+ all_frames: options.allFrames,
2266
+ match_about_blank: options.matchAboutBlank,
2267
+ exclude_globs: options.excludeGlobs,
2268
+ exclude_matches: options.excludeMatches,
2269
+ include_globs: options.includeGlobs,
2270
+ run_at: options.runAt,
2271
+ css,
2272
+ js,
2263
2273
  // @ts-expect-error: untyped chrome options
2264
- match_origin_as_fallback: resolvePerBrowserOption(
2265
- options.matchOriginAsFallback,
2266
- wxt.config.browser
2267
- ),
2274
+ match_origin_as_fallback: options.matchOriginAsFallback,
2275
+ world: options.world
2276
+ };
2277
+ }
2278
+ function mapWxtOptionsToRegisteredContentScript(options, js, css) {
2279
+ return {
2280
+ allFrames: options.allFrames,
2281
+ excludeMatches: options.excludeMatches,
2282
+ matches: options.matches,
2283
+ runAt: options.runAt,
2284
+ js,
2285
+ css,
2286
+ // @ts-expect-error: Chrome accepts this, not typed in webextension-polyfill (https://developer.chrome.com/docs/extensions/reference/scripting/#type-RegisteredContentScript)
2268
2287
  world: options.world
2269
2288
  };
2270
2289
  }
@@ -2499,9 +2518,11 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
2499
2518
  );
2500
2519
  if (wxt.config.browser === "firefox") {
2501
2520
  manifest.sidebar_action = {
2502
- // TODO: Add options to side panel
2503
- // ...defaultSidepanel.options,
2504
- default_panel: page
2521
+ default_panel: page,
2522
+ browser_style: defaultSidepanel.options.browserStyle,
2523
+ default_icon: defaultSidepanel.options.defaultIcon,
2524
+ default_title: defaultSidepanel.options.defaultTitle,
2525
+ open_at_install: defaultSidepanel.options.openAtInstall
2505
2526
  };
2506
2527
  } else if (wxt.config.manifestVersion === 3) {
2507
2528
  manifest.side_panel = {
@@ -2518,11 +2539,7 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
2518
2539
  if (wxt.config.command === "serve" && wxt.config.manifestVersion === 3) {
2519
2540
  const hostPermissions = new Set(manifest.host_permissions ?? []);
2520
2541
  contentScripts.forEach((script) => {
2521
- const matches = resolvePerBrowserOption(
2522
- script.options.matches,
2523
- wxt.config.browser
2524
- );
2525
- matches.forEach((matchPattern) => {
2542
+ script.options.matches.forEach((matchPattern) => {
2526
2543
  hostPermissions.add(matchPattern);
2527
2544
  });
2528
2545
  });
@@ -2539,13 +2556,13 @@ function addEntrypoints(manifest, entrypoints, buildOutput) {
2539
2556
  return map;
2540
2557
  }, /* @__PURE__ */ new Map());
2541
2558
  const newContentScripts = Array.from(hashToEntrypointsMap.entries()).map(
2542
- ([, scripts]) => ({
2543
- ...mapWxtOptionsToContentScript(scripts[0].options),
2544
- css: getContentScriptCssFiles(scripts, cssMap),
2545
- js: scripts.map(
2559
+ ([, scripts]) => mapWxtOptionsToContentScript(
2560
+ scripts[0].options,
2561
+ scripts.map(
2546
2562
  (entry) => getEntrypointBundlePath(entry, wxt.config.outDir, ".js")
2547
- )
2548
- })
2563
+ ),
2564
+ getContentScriptCssFiles(scripts, cssMap)
2565
+ )
2549
2566
  );
2550
2567
  if (newContentScripts.length >= 0) {
2551
2568
  manifest.content_scripts ??= [];
@@ -2649,10 +2666,9 @@ function getContentScriptCssWebAccessibleResources(contentScripts, contentScript
2649
2666
  return;
2650
2667
  resources.push({
2651
2668
  resources: [cssFile],
2652
- matches: resolvePerBrowserOption(
2653
- script.options.matches,
2654
- wxt.config.browser
2655
- ).map((matchPattern) => stripPathFromMatchPattern(matchPattern))
2669
+ matches: script.options.matches.map(
2670
+ (matchPattern) => stripPathFromMatchPattern(matchPattern)
2671
+ )
2656
2672
  });
2657
2673
  });
2658
2674
  return resources;
@@ -3266,25 +3282,9 @@ function reloadContentScripts(steps, server) {
3266
3282
  const js = [getEntrypointBundlePath(entry, wxt.config.outDir, ".js")];
3267
3283
  const cssMap = getContentScriptsCssMap(server.currentOutput, [entry]);
3268
3284
  const css = getContentScriptCssFiles([entry], cssMap);
3269
- server.reloadContentScript({
3270
- allFrames: resolvePerBrowserOption(
3271
- entry.options.allFrames,
3272
- wxt.config.browser
3273
- ),
3274
- excludeMatches: resolvePerBrowserOption(
3275
- entry.options.excludeMatches,
3276
- wxt.config.browser
3277
- ),
3278
- matches: resolvePerBrowserOption(
3279
- entry.options.matches,
3280
- wxt.config.browser
3281
- ),
3282
- runAt: resolvePerBrowserOption(entry.options.runAt, wxt.config.browser),
3283
- // @ts-expect-error: Chrome accepts this, not typed in webextension-polyfill (https://developer.chrome.com/docs/extensions/reference/scripting/#type-RegisteredContentScript)
3284
- world: resolvePerBrowserOption(entry.options.world, wxt.config.browser),
3285
- js,
3286
- css
3287
- });
3285
+ server.reloadContentScript(
3286
+ mapWxtOptionsToRegisteredContentScript(entry.options, js, css)
3287
+ );
3288
3288
  });
3289
3289
  } else {
3290
3290
  server.reloadExtension();
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as ContentScriptContext } from './index-TYmXqKVq.js';
1
+ import { a as ContentScriptContext } from './index-nSEE-7AX.js';
2
2
  import 'webextension-polyfill';
3
3
 
4
4
  interface IntegratedContentScriptUi<TMounted> extends ContentScriptUi<TMounted> {
package/dist/client.js CHANGED
@@ -299,13 +299,13 @@ async function createShadowRootUi(ctx, options) {
299
299
  shadowHost.setAttribute("data-wxt-shadow-root", "");
300
300
  let mounted;
301
301
  const mount = () => {
302
- mounted = options.onMount(uiContainer, shadow, shadowHost);
303
302
  mountUi(shadowHost, options);
304
303
  applyPosition(shadowHost, shadow.querySelector("html"), options);
304
+ mounted = options.onMount(uiContainer, shadow, shadowHost);
305
305
  };
306
306
  const remove = () => {
307
- shadowHost.remove();
308
307
  options.onRemove?.(mounted);
308
+ shadowHost.remove();
309
309
  while (uiContainer.lastChild)
310
310
  uiContainer.removeChild(uiContainer.lastChild);
311
311
  };