UNPKG

@crxjs/vite-plugin

Version:

Build Chrome Extensions with this Vite plugin.

384 lines (376 loc) 13.2 kB
import { ConfigEnv, Plugin, PluginOption } from 'vite'; import { Options } from 'fast-glob'; import { PluginContext, OutputBundle } from 'rollup'; interface DeclarativeNetRequestResource { id: string; enabled: boolean; path: string; } interface WebAccessibleResourceByMatch { matches: string[]; resources: string[]; use_dynamic_url?: boolean; } interface WebAccessibleResourceById { extension_ids: string[]; resources: string[]; use_dynamic_url?: boolean; } interface ChromeManifestBackground { service_worker: string; type?: 'module' | (string & {}); } interface FirefoxManifestBackground { scripts: string[]; persistent?: false; } interface ManifestV3 { manifest_version: number; name: string; version: string; default_locale?: string | undefined; description?: string | undefined; icons?: chrome.runtime.ManifestIcons | undefined; action?: chrome.runtime.ManifestAction | undefined; /** * @see https://developer.chrome.com/docs/extensions/reference/manifest/author */ author?: { email: string; } | undefined; background?: ChromeManifestBackground | FirefoxManifestBackground | undefined; chrome_settings_overrides?: { homepage?: string | undefined; search_provider?: chrome.runtime.SearchProvider | undefined; startup_pages?: string[] | undefined; } | undefined; chrome_ui_overrides?: { bookmarks_ui?: { remove_bookmark_shortcut?: boolean | undefined; remove_button?: boolean | undefined; } | undefined; } | undefined; chrome_url_overrides?: { bookmarks?: string | undefined; history?: string | undefined; newtab?: string | undefined; } | undefined; commands?: { [name: string]: { suggested_key?: { default?: string | undefined; windows?: string | undefined; mac?: string | undefined; chromeos?: string | undefined; linux?: string | undefined; } | undefined; description?: string | undefined; global?: boolean | undefined; }; } | undefined; content_capabilities?: { matches?: string[] | undefined; permissions?: string[] | undefined; } | undefined; content_scripts?: { matches?: string[] | undefined; exclude_matches?: string[] | undefined; css?: string[] | undefined; js?: string[] | undefined; run_at?: string | undefined; all_frames?: boolean | undefined; match_about_blank?: boolean | undefined; include_globs?: string[] | undefined; exclude_globs?: string[] | undefined; }[] | undefined; content_security_policy?: { extension_pages?: string; sandbox?: string; }; converted_from_user_script?: boolean | undefined; current_locale?: string | undefined; declarative_net_request?: { rule_resources: DeclarativeNetRequestResource[]; }; devtools_page?: string | undefined; event_rules?: { event?: string | undefined; actions?: { type: string; }[] | undefined; conditions?: chrome.declarativeContent.PageStateMatcherProperties[] | undefined; }[] | undefined; externally_connectable?: { ids?: string[] | undefined; matches?: string[] | undefined; accepts_tls_channel_id?: boolean | undefined; } | undefined; file_browser_handlers?: { id?: string | undefined; default_title?: string | undefined; file_filters?: string[] | undefined; }[] | undefined; file_system_provider_capabilities?: { configurable?: boolean | undefined; watchable?: boolean | undefined; multiple_mounts?: boolean | undefined; source?: string | undefined; } | undefined; homepage_url?: string | undefined; host_permissions?: string[] | undefined; import?: { id: string; minimum_version?: string | undefined; }[] | undefined; export?: { whitelist?: string[] | undefined; } | undefined; incognito?: string | undefined; input_components?: { name: string; id?: string | undefined; language?: string | string[] | undefined; layouts?: string | string[] | undefined; input_view?: string | undefined; options_page?: string | undefined; }[] | undefined; key?: string | undefined; minimum_chrome_version?: string | undefined; nacl_modules?: { path: string; mime_type: string; }[] | undefined; oauth2?: { client_id: string; scopes?: string[] | undefined; } | undefined; offline_enabled?: boolean | undefined; omnibox?: { keyword: string; } | undefined; optional_host_permissions?: string[] | undefined; optional_permissions?: chrome.runtime.ManifestPermissions[] | string[] | undefined; options_page?: string | undefined; options_ui?: { page?: string | undefined; chrome_style?: boolean | undefined; open_in_tab?: boolean | undefined; } | undefined; permissions?: chrome.runtime.ManifestPermissions[] | string[] | undefined; platforms?: { nacl_arch?: string | undefined; sub_package_path: string; }[] | undefined; plugins?: { path: string; }[] | undefined; requirements?: { '3D'?: { features?: string[] | undefined; } | undefined; plugins?: { npapi?: boolean | undefined; } | undefined; } | undefined; sandbox?: { pages: string[]; content_security_policy?: string | undefined; } | undefined; side_panel?: { default_path?: string | undefined; } | undefined; short_name?: string | undefined; spellcheck?: { dictionary_language?: string | undefined; dictionary_locale?: string | undefined; dictionary_format?: string | undefined; dictionary_path?: string | undefined; } | undefined; storage?: { managed_schema: string; } | undefined; tts_engine?: { voices: { voice_name: string; lang?: string | undefined; gender?: string | undefined; event_types?: string[] | undefined; }[]; } | undefined; update_url?: string | undefined; version_name?: string | undefined; web_accessible_resources?: (WebAccessibleResourceById | WebAccessibleResourceByMatch)[] | undefined; } type ManifestV3Fn = (env: ConfigEnv) => ManifestV3 | Promise<ManifestV3>; type ManifestV3Export = ManifestV3 | Promise<ManifestV3> | ManifestV3Fn; type Code = '.' | '/' | '\\'; type ManifestFilePath<T extends string> = T extends `${Code}${string}` ? never : T extends `${string}.${infer Ext}` ? Ext extends '' ? never : T : never; interface ManifestIcons<T extends string> { [size: number]: ManifestFilePath<T>; } type FilePathFields<T extends string> = { icons?: ManifestIcons<T>; action?: { /** * - Relative to Vite project root (where vite.config.js is) * - Format: "subdir/icon.png" (no leading ./ or /) * * @example "assets/icon.png" */ default_icon?: ManifestIcons<T>; default_title?: string; /** * - Relative to Vite project root (where vite.config.js is) * - Format: "subdir/index.html" (no leading ./ or /) * * @example "src/popup.html" */ default_popup?: ManifestFilePath<T>; }; background?: { /** * - Relative to Vite project root (where vite.config.js is) * - Format: "subdir/index.js" (no leading ./ or /) * * @example "src/background.js" */ service_worker: ManifestFilePath<T>; type?: 'module' | (string & {}); } | FirefoxManifestBackground; content_scripts?: { matches?: string[]; exclude_matches?: string[]; /** * - Relative to Vite project root (where vite.config.js is) * - Format: "subdir/content.css" (no leading ./ or /) * * @example "src/content.css" */ css?: ManifestFilePath<T>[]; /** * - Relative to Vite project root (where vite.config.js is) * - Format: "subdir/content.js" (no leading ./ or /) * * @example "src/content.js" */ js?: ManifestFilePath<T>[]; run_at?: string; all_frames?: boolean; match_about_blank?: boolean; include_globs?: string[]; exclude_globs?: string[]; }[]; input_components?: { name: string; id?: string; language?: string | string[]; layouts?: string | string[]; input_view?: string; /** * - Relative to Vite project root (where vite.config.js is) * - Format: "subdir/options.html" (no leading ./ or /) * * @example "src/options.html" */ options_page?: ManifestFilePath<T>; }[]; /** * - Relative to Vite project root (where vite.config.js is) * - Format: "subdir/options.html" (no leading ./ or /) * * @example "src/options.html" */ options_page?: ManifestFilePath<T>; /** * - Relative to Vite project root (where vite.config.js is) * - Format: "subdir/devtools.html" (no leading ./ or /) * * @example "src/devtools.html" */ devtools_page?: ManifestFilePath<T>; }; type ManifestOptions<T extends string> = Omit<ManifestV3, keyof FilePathFields<string>> & FilePathFields<T>; type ManifestV3Options<T extends string = string> = ManifestOptions<T> | Promise<ManifestOptions<T>> | ManifestV3Define<T>; type ManifestV3Define<T extends string> = (env: ConfigEnv) => ManifestOptions<T> | Promise<ManifestOptions<T>>; declare const defineManifest: <T extends string>(manifest: ManifestV3Options<T>) => ManifestV3Export; /** * Content script resources like CSS and image files must be declared in the * manifest under `web_accessible_resources`. Manifest V3 uses a match pattern * to narrow the origins that can access a Chrome CRX resource. * * Content script resources use the same match pattern as the content script for * web accessible resources. * * You don't need to define a match pattern for dynamic content script * resources, but if you want to do so, you can use the helper function * `defineDynamicResource` to define your web accessible resources in a * TypeScript file: * * ```typescript * import { crx, defineManifest, defineDynamicResource } * const manifest = defineManifest({ * "web_accessible_resources": [ * defineDynamicResource({ * matches: ["https://example.com/*", "file:///*.mp3", "..."] * use_dynamic_url?: true * }) * ] * }) * ``` */ declare const defineDynamicResource: ({ matches, use_dynamic_url, }: Omit<WebAccessibleResourceByMatch, 'resources'>) => WebAccessibleResourceByMatch; type CrxDevAssetId = { id: string; type: 'asset'; source?: string | Uint8Array; }; type CrxDevScriptId = { id: string; type: 'module' | 'iife'; }; interface CrxPlugin extends Plugin { /** * Runs during the transform hook for the manifest. Filenames use input * filenames. */ transformCrxManifest?: (this: PluginContext, manifest: ManifestV3) => Promise<ManifestV3 | null | undefined> | ManifestV3 | null | undefined; /** * Runs during generateBundle, before manifest output. Filenames use output * filenames. */ renderCrxManifest?: (this: PluginContext, manifest: ManifestV3, bundle: OutputBundle) => Promise<ManifestV3 | null | undefined> | ManifestV3 | null | undefined; /** * Runs in the file writer on content scripts during development. `script.id` * is Vite URL format. */ renderCrxDevScript?: (code: string, script: CrxDevScriptId) => Promise<string | null | undefined> | string | null | undefined; } interface CrxOptions { contentScripts?: { preambleCode?: string | false; hmrTimeout?: number; injectCss?: boolean; }; fastGlobOptions?: Options; /** * The browser that this extension is targeting, can be "firefox" or "chrome". * Default is "chrome". */ browser?: Browser; } type Browser = 'firefox' | 'chrome'; /** Resolves when all existing files in scriptFiles are written. */ declare function allFilesReady(): Promise<void>; type FileWriterId = { type: CrxDevAssetId['type'] | CrxDevScriptId['type'] | 'loader'; id: string; }; /** Resolves when file and dependencies are written. */ declare function fileReady(script: FileWriterId): Promise<void>; declare const crx: (options: { manifest: ManifestV3Export; } & CrxOptions) => PluginOption[]; declare const chromeExtension: (options: { manifest: ManifestV3Export; } & CrxOptions) => PluginOption[]; export { CrxPlugin, ManifestV3Export, allFilesReady, chromeExtension, crx, defineDynamicResource, defineManifest, fileReady as filesReady };