diff --git a/packages/wxt/src/client-types.ts b/packages/wxt/src/client-types.ts new file mode 100644 index 000000000..8fb541426 --- /dev/null +++ b/packages/wxt/src/client-types.ts @@ -0,0 +1,55 @@ +import type { + BackgroundEntrypointOptions, + BaseEntrypointOptions, + IsolatedWorldContentScriptEntrypointOptions, + MainWorldContentScriptEntrypointOptions, +} from './option-types'; +import type { ContentScriptContext } from './utils/content-script-context'; + +export type WxtPlugin = () => void; + +export interface IsolatedWorldContentScriptDefinition + extends IsolatedWorldContentScriptEntrypointOptions { + /** + * Main function executed when the content script is loaded. + * + * When running a content script with `browser.scripting.executeScript`, + * values returned from this function will be returned in the `executeScript` + * result as well. Otherwise returning a value does nothing. + */ + main(ctx: ContentScriptContext): any | Promise; +} + +export interface MainWorldContentScriptDefinition + extends MainWorldContentScriptEntrypointOptions { + /** + * Main function executed when the content script is loaded. + * + * When running a content script with `browser.scripting.executeScript`, + * values returned from this function will be returned in the `executeScript` + * result as well. Otherwise returning a value does nothing. + */ + main(): any | Promise; +} + +export type ContentScriptDefinition = + | IsolatedWorldContentScriptDefinition + | MainWorldContentScriptDefinition; + +export interface BackgroundDefinition extends BackgroundEntrypointOptions { + /** + * Main function executed when the background script is started. Cannot be async. + */ + main(): void; +} + +export interface UnlistedScriptDefinition extends BaseEntrypointOptions { + /** + * Main function executed when the unlisted script is ran. + * + * When running a content script with `browser.scripting.executeScript`, + * values returned from this function will be returned in the `executeScript` + * result as well. Otherwise returning a value does nothing. + */ + main(): any | Promise; +} diff --git a/packages/wxt/src/core/resolve-config.ts b/packages/wxt/src/core/resolve-config.ts index c062aa960..7fff5ccc7 100644 --- a/packages/wxt/src/core/resolve-config.ts +++ b/packages/wxt/src/core/resolve-config.ts @@ -361,7 +361,6 @@ async function getUnimportOptions( ]; const defaultOptions: WxtResolvedUnimportOptions = { - imports: [{ name: 'fakeBrowser', from: 'wxt/testing' }], presets: [ { from: 'wxt/browser', diff --git a/packages/wxt/src/option-types.ts b/packages/wxt/src/option-types.ts new file mode 100644 index 000000000..42dc272bf --- /dev/null +++ b/packages/wxt/src/option-types.ts @@ -0,0 +1,155 @@ +import type { ManifestContentScript } from "./core/utils/types"; +import type { Browser } from '@wxt-dev/browser'; + +export type TargetBrowser = string; + +/** + * Either a single value or a map of different browsers to the value for that browser. + */ +export type PerBrowserOption = T | PerBrowserMap; +export type PerBrowserMap = { [browser: TargetBrowser]: T }; + +export interface BaseEntrypointOptions { + /** + * List of target browsers to include this entrypoint in. Defaults to being included in all + * builds. Cannot be used with `exclude`. You must choose one of the two options. + * + * @default undefined + */ + include?: TargetBrowser[]; + /** + * List of target browsers to exclude this entrypoint from. Cannot be used with `include`. You + * must choose one of the two options. + * + * @default undefined + */ + exclude?: TargetBrowser[]; +} + +export interface BackgroundEntrypointOptions extends BaseEntrypointOptions { + persistent?: PerBrowserOption; + /** + * Set to `"module"` to output the background entrypoint as ESM. ESM outputs can share chunks and + * reduce the overall size of the bundled extension. + * + * When `undefined`, the background is bundled individually into an IIFE format. + * + * @default undefined + */ + type?: PerBrowserOption<'module'>; +} + +export interface BaseContentScriptEntrypointOptions + extends BaseEntrypointOptions { + matches?: PerBrowserOption>; + /** + * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ + * @default "documentIdle" + */ + runAt?: PerBrowserOption; + /** + * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ + * @default false + */ + matchAboutBlank?: PerBrowserOption< + ManifestContentScript['match_about_blank'] + >; + /** + * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ + * @default [] + */ + excludeMatches?: PerBrowserOption; + /** + * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ + * @default [] + */ + includeGlobs?: PerBrowserOption; + /** + * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ + * @default [] + */ + excludeGlobs?: PerBrowserOption; + /** + * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ + * @default false + */ + allFrames?: PerBrowserOption; + /** + * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ + * @default false + */ + matchOriginAsFallback?: PerBrowserOption; + /** + * Customize how imported/generated styles are injected with the content script. Regardless of the + * mode selected, CSS will always be built and included in the output directory. + * + * - `"manifest"` - Include the CSS in the manifest, under the content script's `css` array. + * - `"manual"` - Exclude the CSS from the manifest. You are responsible for manually loading it + * onto the page. Use `browser.runtime.getURL("content-scripts/.css")` to get the file's + * URL + * - `"ui"` - Exclude the CSS from the manifest. CSS will be automatically added to your UI when + * calling `createShadowRootUi` + * + * @default "manifest" + */ + cssInjectionMode?: PerBrowserOption<'manifest' | 'manual' | 'ui'>; + /** + * Specify how the content script is registered. + * + * - `"manifest"`: The content script will be added to the `content_scripts` entry in the + * manifest. This is the normal and most well known way of registering a content script. + * - `"runtime"`: The content script's `matches` is added to `host_permissions` and you are + * responsible for using the scripting API to register/execute the content script + * dynamically at runtime. + * + * @default "manifest" + */ + registration?: PerBrowserOption<'manifest' | 'runtime'>; +} + +export interface MainWorldContentScriptEntrypointOptions + extends BaseContentScriptEntrypointOptions { + /** + * See https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts#isolated_world + */ + world: 'MAIN'; +} + +export interface IsolatedWorldContentScriptEntrypointOptions + extends BaseContentScriptEntrypointOptions { + /** + * See https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts#isolated_world + * @default "ISOLATED" + */ + world?: 'ISOLATED'; +} + +export interface PopupEntrypointOptions extends BaseEntrypointOptions { + /** + * Defaults to "browser_action" to be equivalent to MV3's "action" key + */ + mv2Key?: PerBrowserOption<'browser_action' | 'page_action'>; + defaultIcon?: Record; + defaultTitle?: PerBrowserOption; + browserStyle?: PerBrowserOption; +} + +export interface OptionsEntrypointOptions extends BaseEntrypointOptions { + openInTab?: PerBrowserOption; + browserStyle?: PerBrowserOption; + chromeStyle?: PerBrowserOption; +} + +export interface SidepanelEntrypointOptions extends BaseEntrypointOptions { + /** + * Firefox only. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/sidebar_action#syntax + * @default false + */ + openAtInstall?: PerBrowserOption; + /** + * @deprecated See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/sidebar_action#syntax + */ + browserStyle?: PerBrowserOption; + defaultIcon?: string | Record; + defaultTitle?: PerBrowserOption; +} \ No newline at end of file diff --git a/packages/wxt/src/types.ts b/packages/wxt/src/types.ts index c4c3cbc6f..985c90361 100644 --- a/packages/wxt/src/types.ts +++ b/packages/wxt/src/types.ts @@ -1,13 +1,26 @@ import type * as vite from 'vite'; import { UnimportOptions, Import } from 'unimport'; import { LogLevel } from 'consola'; -import type { ContentScriptContext } from './utils/content-script-context'; import type { PluginVisualizerOptions } from '@aklinker1/rollup-plugin-visualizer'; import { ResolvedConfig as C12ResolvedConfig } from 'c12'; import { Hookable, NestedHooks } from 'hookable'; import type * as Nypm from 'nypm'; -import { ManifestContentScript } from './core/utils/types'; import type { Browser } from '@wxt-dev/browser'; +import { + BackgroundEntrypointOptions, + BaseContentScriptEntrypointOptions, + BaseEntrypointOptions, + IsolatedWorldContentScriptEntrypointOptions, + MainWorldContentScriptEntrypointOptions, + OptionsEntrypointOptions, + PerBrowserOption, + PopupEntrypointOptions, + SidepanelEntrypointOptions, + TargetBrowser, +} from './option-types'; + +export type * from './client-types'; +export type * from './option-types'; export interface InlineConfig { /** @@ -513,7 +526,6 @@ export interface ReloadContentScriptPayload { contentScript: Omit; } -export type TargetBrowser = string; export type TargetManifestVersion = 2 | 3; export type UserConfig = Omit; @@ -529,151 +541,6 @@ export interface Logger { level: LogLevel; } -export interface BaseEntrypointOptions { - /** - * List of target browsers to include this entrypoint in. Defaults to being included in all - * builds. Cannot be used with `exclude`. You must choose one of the two options. - * - * @default undefined - */ - include?: TargetBrowser[]; - /** - * List of target browsers to exclude this entrypoint from. Cannot be used with `include`. You - * must choose one of the two options. - * - * @default undefined - */ - exclude?: TargetBrowser[]; -} - -export interface BackgroundEntrypointOptions extends BaseEntrypointOptions { - persistent?: PerBrowserOption; - /** - * Set to `"module"` to output the background entrypoint as ESM. ESM outputs can share chunks and - * reduce the overall size of the bundled extension. - * - * When `undefined`, the background is bundled individually into an IIFE format. - * - * @default undefined - */ - type?: PerBrowserOption<'module'>; -} - -export interface BaseContentScriptEntrypointOptions - extends BaseEntrypointOptions { - matches?: PerBrowserOption>; - /** - * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ - * @default "documentIdle" - */ - runAt?: PerBrowserOption; - /** - * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ - * @default false - */ - matchAboutBlank?: PerBrowserOption< - ManifestContentScript['match_about_blank'] - >; - /** - * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ - * @default [] - */ - excludeMatches?: PerBrowserOption; - /** - * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ - * @default [] - */ - includeGlobs?: PerBrowserOption; - /** - * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ - * @default [] - */ - excludeGlobs?: PerBrowserOption; - /** - * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ - * @default false - */ - allFrames?: PerBrowserOption; - /** - * See https://developer.chrome.com/docs/extensions/mv3/content_scripts/ - * @default false - */ - matchOriginAsFallback?: PerBrowserOption; - /** - * Customize how imported/generated styles are injected with the content script. Regardless of the - * mode selected, CSS will always be built and included in the output directory. - * - * - `"manifest"` - Include the CSS in the manifest, under the content script's `css` array. - * - `"manual"` - Exclude the CSS from the manifest. You are responsible for manually loading it - * onto the page. Use `browser.runtime.getURL("content-scripts/.css")` to get the file's - * URL - * - `"ui"` - Exclude the CSS from the manifest. CSS will be automatically added to your UI when - * calling `createShadowRootUi` - * - * @default "manifest" - */ - cssInjectionMode?: PerBrowserOption<'manifest' | 'manual' | 'ui'>; - /** - * Specify how the content script is registered. - * - * - `"manifest"`: The content script will be added to the `content_scripts` entry in the - * manifest. This is the normal and most well known way of registering a content script. - * - `"runtime"`: The content script's `matches` is added to `host_permissions` and you are - * responsible for using the scripting API to register/execute the content script - * dynamically at runtime. - * - * @default "manifest" - */ - registration?: PerBrowserOption<'manifest' | 'runtime'>; -} - -export interface MainWorldContentScriptEntrypointOptions - extends BaseContentScriptEntrypointOptions { - /** - * See https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts#isolated_world - */ - world: 'MAIN'; -} - -export interface IsolatedWorldContentScriptEntrypointOptions - extends BaseContentScriptEntrypointOptions { - /** - * See https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts#isolated_world - * @default "ISOLATED" - */ - world?: 'ISOLATED'; -} - -export interface PopupEntrypointOptions extends BaseEntrypointOptions { - /** - * Defaults to "browser_action" to be equivalent to MV3's "action" key - */ - mv2Key?: PerBrowserOption<'browser_action' | 'page_action'>; - defaultIcon?: Record; - defaultTitle?: PerBrowserOption; - browserStyle?: PerBrowserOption; -} - -export interface OptionsEntrypointOptions extends BaseEntrypointOptions { - openInTab?: PerBrowserOption; - browserStyle?: PerBrowserOption; - chromeStyle?: PerBrowserOption; -} - -export interface SidepanelEntrypointOptions extends BaseEntrypointOptions { - /** - * Firefox only. See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/sidebar_action#syntax - * @default false - */ - openAtInstall?: PerBrowserOption; - /** - * @deprecated See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/sidebar_action#syntax - */ - browserStyle?: PerBrowserOption; - defaultIcon?: string | Record; - defaultTitle?: PerBrowserOption; -} - export interface BaseEntrypoint { /** * The entrypoint's name. This is the filename or dirname without the type suffix. @@ -772,58 +639,6 @@ export type EntrypointGroup = Entrypoint | Entrypoint[]; export type OnContentScriptStopped = (cb: () => void) => void; -export interface IsolatedWorldContentScriptDefinition - extends IsolatedWorldContentScriptEntrypointOptions { - /** - * Main function executed when the content script is loaded. - * - * When running a content script with `browser.scripting.executeScript`, - * values returned from this function will be returned in the `executeScript` - * result as well. Otherwise returning a value does nothing. - */ - main(ctx: ContentScriptContext): any | Promise; -} - -export interface MainWorldContentScriptDefinition - extends MainWorldContentScriptEntrypointOptions { - /** - * Main function executed when the content script is loaded. - * - * When running a content script with `browser.scripting.executeScript`, - * values returned from this function will be returned in the `executeScript` - * result as well. Otherwise returning a value does nothing. - */ - main(): any | Promise; -} - -export type ContentScriptDefinition = - | IsolatedWorldContentScriptDefinition - | MainWorldContentScriptDefinition; - -export interface BackgroundDefinition extends BackgroundEntrypointOptions { - /** - * Main function executed when the background script is started. Cannot be async. - */ - main(): void; -} - -export interface UnlistedScriptDefinition extends BaseEntrypointOptions { - /** - * Main function executed when the unlisted script is ran. - * - * When running a content script with `browser.scripting.executeScript`, - * values returned from this function will be returned in the `executeScript` - * result as well. Otherwise returning a value does nothing. - */ - main(): any | Promise; -} - -/** - * Either a single value or a map of different browsers to the value for that browser. - */ -export type PerBrowserOption = T | PerBrowserMap; -export type PerBrowserMap = { [browser: TargetBrowser]: T }; - /** * Convert `{ key: PerBrowserOption }` to just `{ key: T }`, stripping away the * `PerBrowserOption` type for all fields inside the object. @@ -913,7 +728,7 @@ export interface ConfigEnv { * [the guide](https://wxt.dev/guide/key-concepts/multiple-browsers.html#target-manifest-version) for more * details. */ - manifestVersion: 2 | 3; + manifestVersion: TargetManifestVersion; } export type WxtCommand = 'build' | 'serve'; @@ -1568,8 +1383,6 @@ export interface GeneratedPublicFile extends ResolvedBasePublicFile { contents: string; } -export type WxtPlugin = () => void; - export type WxtDirEntry = WxtDirTypeReferenceEntry | WxtDirFileEntry; /** diff --git a/packages/wxt/src/utils/content-script-context.ts b/packages/wxt/src/utils/content-script-context.ts index 5a4880197..d795444ac 100644 --- a/packages/wxt/src/utils/content-script-context.ts +++ b/packages/wxt/src/utils/content-script-context.ts @@ -1,5 +1,5 @@ /** @module wxt/utils/content-script-context */ -import { ContentScriptDefinition } from '../types'; +import { ContentScriptDefinition } from '../client-types'; import { browser } from 'wxt/browser'; import { logger } from '../utils/internal/logger'; import { diff --git a/packages/wxt/src/utils/define-background.ts b/packages/wxt/src/utils/define-background.ts index 18a8c92ee..34d57a54d 100644 --- a/packages/wxt/src/utils/define-background.ts +++ b/packages/wxt/src/utils/define-background.ts @@ -1,5 +1,5 @@ /** @module wxt/utils/define-background */ -import type { BackgroundDefinition } from '../types'; +import type { BackgroundDefinition } from '../client-types'; export function defineBackground(main: () => void): BackgroundDefinition; export function defineBackground( diff --git a/packages/wxt/src/utils/define-content-script.ts b/packages/wxt/src/utils/define-content-script.ts index 4d250cc53..e6c549096 100644 --- a/packages/wxt/src/utils/define-content-script.ts +++ b/packages/wxt/src/utils/define-content-script.ts @@ -1,5 +1,5 @@ /** @module wxt/utils/define-content-script */ -import type { ContentScriptDefinition } from '../types'; +import type { ContentScriptDefinition } from '../client-types'; export function defineContentScript( definition: ContentScriptDefinition, diff --git a/packages/wxt/src/utils/define-unlisted-script.ts b/packages/wxt/src/utils/define-unlisted-script.ts index 6ee1dbba4..e2680126d 100644 --- a/packages/wxt/src/utils/define-unlisted-script.ts +++ b/packages/wxt/src/utils/define-unlisted-script.ts @@ -1,5 +1,5 @@ /** @module wxt/utils/define-unlisted-script */ -import type { UnlistedScriptDefinition } from '../types'; +import type { UnlistedScriptDefinition } from '../client-types'; export function defineUnlistedScript( main: () => void, diff --git a/packages/wxt/src/utils/define-wxt-plugin.ts b/packages/wxt/src/utils/define-wxt-plugin.ts index ed487271a..d0e83c750 100644 --- a/packages/wxt/src/utils/define-wxt-plugin.ts +++ b/packages/wxt/src/utils/define-wxt-plugin.ts @@ -1,5 +1,5 @@ /** @module wxt/utils/define-wxt-plugin */ -import type { WxtPlugin } from '../types'; +import type { WxtPlugin } from '../client-types'; export function defineWxtPlugin(plugin: WxtPlugin): WxtPlugin { return plugin;