feat!: Individual exports and introduce the #imports module (#1258)
This commit is contained in:
@@ -11,19 +11,7 @@ export default defineConfig({
|
||||
});
|
||||
```
|
||||
|
||||
By default, WXT sets up auto-imports for all of it's own APIs:
|
||||
|
||||
- [`browser`](/api/reference/wxt/browser/variables/browser) from `wxt/browser`
|
||||
- [`defineContentScript`](/api/reference/wxt/sandbox/functions/defineContentScript) from `wxt/sandbox`
|
||||
- [`defineBackground`](/api/reference/wxt/sandbox/functions/defineBackground) from `wxt/sandbox`
|
||||
- [`defineUnlistedScript`](/api/reference/wxt/sandbox/functions/defineUnlistedScript) from `wxt/sandbox`
|
||||
- [`createIntegratedUi`](/api/reference/wxt/client/functions/createIntegratedUi) from `wxt/client`
|
||||
- [`createShadowRootUi`](/api/reference/wxt/client/functions/createShadowRootUi) from `wxt/client`
|
||||
- [`createIframeUi`](/api/reference/wxt/client/functions/createIframeUi) from `wxt/client`
|
||||
- [`fakeBrowser`](/api/reference/wxt/testing/variables/fakeBrowser) from `wxt/testing`
|
||||
- And more!
|
||||
|
||||
WXT also adds some project directories as auto-import sources automatically:
|
||||
By default, WXT automatically sets up auto-imports for all of it's own APIs and some of your project directories:
|
||||
|
||||
- `<srcDir>/components/*`
|
||||
- `<srcDir>/composables/*`
|
||||
@@ -32,6 +20,8 @@ WXT also adds some project directories as auto-import sources automatically:
|
||||
|
||||
All named and default exports from files in these directories are available everywhere else in your project without having to import them.
|
||||
|
||||
To see the complete list of auto-imported APIs, run [`wxt prepare`](/api/cli/wxt-prepare) and look at your project's `.wxt/types/imports-module.d.ts` file.
|
||||
|
||||
## TypeScript
|
||||
|
||||
For TypeScript and your editor to recognize auto-imported variables, you need to run the [`wxt prepare` command](/api/cli/wxt-prepare).
|
||||
@@ -110,3 +100,19 @@ export default defineConfig({
|
||||
imports: false, // [!code ++]
|
||||
});
|
||||
```
|
||||
|
||||
## Explicit Imports (`#imports`)
|
||||
|
||||
You can manually import all of WXT's APIs via the `#imports` module:
|
||||
|
||||
```ts
|
||||
import {
|
||||
createShadowRootUi,
|
||||
ContentScriptContext,
|
||||
MatchPattern,
|
||||
} from '#imports';
|
||||
```
|
||||
|
||||
To learn more about how the `#imports` module works, read the [related blog post](/blog/2024-12-06-using-imports-module).
|
||||
|
||||
If you've disabled auto-imports, you can use `#imports` to import all of WXT's APIs from a single place.
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
Define runtime configuration in a single place, `<srcDir>/app.config.ts`:
|
||||
|
||||
```ts
|
||||
import { defineAppConfig } from 'wxt/sandbox';
|
||||
import { defineAppConfig } from '#imports';
|
||||
|
||||
// Define types for your config
|
||||
declare module 'wxt/sandbox' {
|
||||
declare module 'wxt/utils/define-app-config' {
|
||||
export interface WxtAppConfig {
|
||||
theme?: 'light' | 'dark';
|
||||
}
|
||||
@@ -26,7 +26,7 @@ This file is committed to the repo, so don't put any secrets here. Instead, use
|
||||
To access runtime config, WXT provides the `useAppConfig` function:
|
||||
|
||||
```ts
|
||||
import { useAppConfig } from 'wxt/sandbox';
|
||||
import { useAppConfig } from '#imports';
|
||||
|
||||
console.log(useAppConfig()); // { theme: "dark" }
|
||||
```
|
||||
@@ -36,7 +36,7 @@ console.log(useAppConfig()); // { theme: "dark" }
|
||||
You can use environment variables in the `app.config.ts` file.
|
||||
|
||||
```ts
|
||||
declare module 'wxt/sandbox' {
|
||||
declare module 'wxt/utils/define-app-config' {
|
||||
export interface WxtAppConfig {
|
||||
apiKey?: string;
|
||||
skipWelcome: boolean;
|
||||
|
||||
@@ -256,13 +256,13 @@ export default defineContentScript({
|
||||
|
||||
:::
|
||||
|
||||
See the [API Reference](/api/reference/wxt/client/functions/createIntegratedUi) for the complete list of options.
|
||||
See the [API Reference](/api/reference/wxt/utils/content-script-ui/functions/createIntegratedUi) for the complete list of options.
|
||||
|
||||
### Shadow Root
|
||||
|
||||
Often in web extensions, you don't want your content script's CSS affecting the page, or vise-versa. The [`ShadowRoot`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot) API is ideal for this.
|
||||
|
||||
WXT's [`createShadowRootUi`](/api/reference/wxt/client/functions/createShadowRootUi) abstracts all the `ShadowRoot` setup away, making it easy to create UIs whose styles are isolated from the page. It also supports an optional `isolateEvents` parameter to further isolate user interactions.
|
||||
WXT's [`createShadowRootUi`](/api/reference/wxt/utils/content-script-ui/functions/createShadowRootUi) abstracts all the `ShadowRoot` setup away, making it easy to create UIs whose styles are isolated from the page. It also supports an optional `isolateEvents` parameter to further isolate user interactions.
|
||||
|
||||
To use `createShadowRootUi`, follow these steps:
|
||||
|
||||
@@ -445,7 +445,7 @@ export default defineContentScript({
|
||||
|
||||
:::
|
||||
|
||||
See the [API Reference](/api/reference/wxt/client/functions/createShadowRootUi) for the complete list of options.
|
||||
See the [API Reference](/api/reference/wxt/utils/content-script-ui/functions/createShadowRootUi) for the complete list of options.
|
||||
|
||||
Full examples:
|
||||
|
||||
@@ -456,7 +456,7 @@ Full examples:
|
||||
|
||||
If you don't need to run your UI in the same frame as the content script, you can use an IFrame to host your UI instead. Since an IFrame just hosts an HTML page, **_HMR is supported_**.
|
||||
|
||||
WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/functions/createIframeUi), which simplifies setting up the IFrame.
|
||||
WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/utils/content-script-ui/functions/createIframeUi), which simplifies setting up the IFrame.
|
||||
|
||||
1. Create an HTML page that will be loaded into your IFrame:
|
||||
```html
|
||||
@@ -510,7 +510,7 @@ WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/fun
|
||||
});
|
||||
```
|
||||
|
||||
See the [API Reference](/api/reference/wxt/client/functions/createIframeUi) for the complete list of options.
|
||||
See the [API Reference](/api/reference/wxt/utils/content-script-ui/functions/createIframeUi) for the complete list of options.
|
||||
|
||||
## Isolated World vs Main World
|
||||
|
||||
|
||||
@@ -71,6 +71,34 @@ describe('isLoggedIn', () => {
|
||||
});
|
||||
```
|
||||
|
||||
### Mocking WXT APIs
|
||||
|
||||
First, you need to understand how the `#imports` module works. When WXT (and vitest) sees this import during a preprocessing step, the import is replaced with multiple imports pointing to their "real" import path.
|
||||
|
||||
For example, this is what your write in your source code:
|
||||
|
||||
```ts
|
||||
// What you write
|
||||
import { injectScript, createShadowRootUi } from '#imports';
|
||||
```
|
||||
|
||||
But Vitest sees this:
|
||||
|
||||
```ts
|
||||
import { injectScript } from 'wxt/browser';
|
||||
import { createShadowRootUi } from 'wxt/utils/content-script-ui/shadow-root';
|
||||
```
|
||||
|
||||
So in this case, if you wanted to mock `injectScript`, you need to pass in `"wxt/utils/inject-script"`, not `"#imports"`.
|
||||
|
||||
```ts
|
||||
vi.mock("wxt/utils/inject-script", () => ({
|
||||
injectScript: ...
|
||||
}))
|
||||
```
|
||||
|
||||
Refer to your project's `.wxt/types/imports-module.d.ts` file to lookup real import paths for `#imports`. If the file doesn't exist, run [`wxt prepare`](/guide/essentials/config/typescript).
|
||||
|
||||
## Other Testing Frameworks
|
||||
|
||||
To use a different framework, you will likely have to disable auto-imports, setup import aliases, manually mock the extension APIs, and setup the test environment to support all of WXT's features that you use.
|
||||
|
||||
@@ -111,12 +111,12 @@ export default defineWxtModule<AnalyticModuleOptions>({
|
||||
|
||||
```ts
|
||||
import { defineWxtModule } from 'wxt/modules';
|
||||
import 'wxt/sandbox';
|
||||
import 'wxt/utils/define-app-config';
|
||||
|
||||
export interface MyModuleRuntimeOptions {
|
||||
// Add your runtime options here...
|
||||
}
|
||||
declare module 'wxt/sandbox' {
|
||||
declare module 'wxt/utils/define-app-config' {
|
||||
export interface WxtAppConfig {
|
||||
myModule: MyModuleOptions;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineAppConfig } from 'wxt/sandbox';
|
||||
import { defineAppConfig } from '#imports';
|
||||
|
||||
declare module 'wxt/sandbox' {
|
||||
declare module 'wxt/utils/define-app-config' {
|
||||
export interface WxtAppConfig {
|
||||
example: string;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineBuildConfig } from 'unbuild';
|
||||
import { version } from './package.json';
|
||||
import { version, exports } from './package.json';
|
||||
import { readFile, writeFile } from 'fs/promises';
|
||||
import {
|
||||
virtualEntrypointModuleNames,
|
||||
@@ -32,10 +32,7 @@ export default defineBuildConfig([
|
||||
...virtualEntrypointModuleNames.map((name) => `virtual:user-${name}`),
|
||||
'virtual:wxt-plugins',
|
||||
'virtual:app-config',
|
||||
'wxt/browser',
|
||||
'wxt/sandbox',
|
||||
'wxt/client',
|
||||
'wxt/testing',
|
||||
...Object.keys(exports).map((path) => 'wxt' + path.slice(1)), // ./storage => wxt/storage
|
||||
],
|
||||
})),
|
||||
]);
|
||||
|
||||
@@ -15,7 +15,6 @@ exports[`Auto Imports > eslintrc > "enabled: 8" should output a JSON config file
|
||||
"createShadowRootUi": true,
|
||||
"defineAppConfig": true,
|
||||
"defineBackground": true,
|
||||
"defineConfig": true,
|
||||
"defineContentScript": true,
|
||||
"defineUnlistedScript": true,
|
||||
"defineWxtPlugin": true,
|
||||
@@ -42,7 +41,6 @@ const globals = {
|
||||
"createShadowRootUi": true,
|
||||
"defineAppConfig": true,
|
||||
"defineBackground": true,
|
||||
"defineConfig": true,
|
||||
"defineContentScript": true,
|
||||
"defineUnlistedScript": true,
|
||||
"defineWxtPlugin": true,
|
||||
@@ -77,7 +75,6 @@ exports[`Auto Imports > eslintrc > "enabled: true" should output a JSON config f
|
||||
"createShadowRootUi": true,
|
||||
"defineAppConfig": true,
|
||||
"defineBackground": true,
|
||||
"defineConfig": true,
|
||||
"defineContentScript": true,
|
||||
"defineUnlistedScript": true,
|
||||
"defineWxtPlugin": true,
|
||||
@@ -105,7 +102,6 @@ exports[`Auto Imports > eslintrc > should allow customizing the output 1`] = `
|
||||
"createShadowRootUi": "readonly",
|
||||
"defineAppConfig": "readonly",
|
||||
"defineBackground": "readonly",
|
||||
"defineConfig": "readonly",
|
||||
"defineContentScript": "readonly",
|
||||
"defineUnlistedScript": "readonly",
|
||||
"defineWxtPlugin": "readonly",
|
||||
|
||||
@@ -17,24 +17,23 @@ describe('Auto Imports', () => {
|
||||
// Generated by wxt
|
||||
export {}
|
||||
declare global {
|
||||
const ContentScriptContext: typeof import('wxt/client')['ContentScriptContext']
|
||||
const InvalidMatchPattern: typeof import('wxt/sandbox')['InvalidMatchPattern']
|
||||
const MatchPattern: typeof import('wxt/sandbox')['MatchPattern']
|
||||
const ContentScriptContext: typeof import('wxt/utils/content-script-context')['ContentScriptContext']
|
||||
const InvalidMatchPattern: typeof import('wxt/utils/match-patterns')['InvalidMatchPattern']
|
||||
const MatchPattern: typeof import('wxt/utils/match-patterns')['MatchPattern']
|
||||
const MigrationError: typeof import('wxt/storage')['MigrationError']
|
||||
const browser: typeof import('wxt/browser')['browser']
|
||||
const createIframeUi: typeof import('wxt/client')['createIframeUi']
|
||||
const createIntegratedUi: typeof import('wxt/client')['createIntegratedUi']
|
||||
const createShadowRootUi: typeof import('wxt/client')['createShadowRootUi']
|
||||
const defineAppConfig: typeof import('wxt/sandbox')['defineAppConfig']
|
||||
const defineBackground: typeof import('wxt/sandbox')['defineBackground']
|
||||
const defineConfig: typeof import('wxt')['defineConfig']
|
||||
const defineContentScript: typeof import('wxt/sandbox')['defineContentScript']
|
||||
const defineUnlistedScript: typeof import('wxt/sandbox')['defineUnlistedScript']
|
||||
const defineWxtPlugin: typeof import('wxt/sandbox')['defineWxtPlugin']
|
||||
const createIframeUi: typeof import('wxt/utils/content-script-ui/iframe')['createIframeUi']
|
||||
const createIntegratedUi: typeof import('wxt/utils/content-script-ui/integrated')['createIntegratedUi']
|
||||
const createShadowRootUi: typeof import('wxt/utils/content-script-ui/shadow-root')['createShadowRootUi']
|
||||
const defineAppConfig: typeof import('wxt/utils/define-app-config')['defineAppConfig']
|
||||
const defineBackground: typeof import('wxt/utils/define-background')['defineBackground']
|
||||
const defineContentScript: typeof import('wxt/utils/define-content-script')['defineContentScript']
|
||||
const defineUnlistedScript: typeof import('wxt/utils/define-unlisted-script')['defineUnlistedScript']
|
||||
const defineWxtPlugin: typeof import('wxt/utils/define-wxt-plugin')['defineWxtPlugin']
|
||||
const fakeBrowser: typeof import('wxt/testing')['fakeBrowser']
|
||||
const injectScript: typeof import('wxt/client')['injectScript']
|
||||
const injectScript: typeof import('wxt/utils/inject-script')['injectScript']
|
||||
const storage: typeof import('wxt/storage')['storage']
|
||||
const useAppConfig: typeof import('wxt/client')['useAppConfig']
|
||||
const useAppConfig: typeof import('wxt/utils/app-config')['useAppConfig']
|
||||
}
|
||||
"
|
||||
`);
|
||||
@@ -55,10 +54,52 @@ describe('Auto Imports', () => {
|
||||
/// <reference path="./types/paths.d.ts" />
|
||||
/// <reference path="./types/i18n.d.ts" />
|
||||
/// <reference path="./types/globals.d.ts" />
|
||||
/// <reference path="./types/imports-module.d.ts" />
|
||||
/// <reference path="./types/imports.d.ts" />
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should generate the #imports module', async () => {
|
||||
const project = new TestProject();
|
||||
project.addFile('entrypoints/popup.html', `<html></html>`);
|
||||
// Project auto-imports should also be present
|
||||
project.addFile(
|
||||
'utils/time.ts',
|
||||
`export function startOfDay(date: Date): Date {
|
||||
throw Error("TODO")
|
||||
}`,
|
||||
);
|
||||
|
||||
await project.prepare();
|
||||
|
||||
expect(await project.serializeFile('.wxt/types/imports-module.d.ts'))
|
||||
.toMatchInlineSnapshot(`
|
||||
".wxt/types/imports-module.d.ts
|
||||
----------------------------------------
|
||||
// Generated by wxt
|
||||
// Types for the #import virtual module
|
||||
declare module '#imports' {
|
||||
export { browser } from 'wxt/browser';
|
||||
export { MigrationError, storage } from 'wxt/storage';
|
||||
export { useAppConfig } from 'wxt/utils/app-config';
|
||||
export { ContentScriptContext } from 'wxt/utils/content-script-context';
|
||||
export { createIframeUi } from 'wxt/utils/content-script-ui/iframe';
|
||||
export { createIntegratedUi } from 'wxt/utils/content-script-ui/integrated';
|
||||
export { createShadowRootUi } from 'wxt/utils/content-script-ui/shadow-root';
|
||||
export { defineAppConfig } from 'wxt/utils/define-app-config';
|
||||
export { defineBackground } from 'wxt/utils/define-background';
|
||||
export { defineContentScript } from 'wxt/utils/define-content-script';
|
||||
export { defineUnlistedScript } from 'wxt/utils/define-unlisted-script';
|
||||
export { defineWxtPlugin } from 'wxt/utils/define-wxt-plugin';
|
||||
export { injectScript } from 'wxt/utils/inject-script';
|
||||
export { InvalidMatchPattern, MatchPattern } from 'wxt/utils/match-patterns';
|
||||
export { fakeBrowser } from 'wxt/testing';
|
||||
export { startOfDay } from '../utils/time';
|
||||
}
|
||||
"
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('imports: false', () => {
|
||||
@@ -74,7 +115,7 @@ describe('Auto Imports', () => {
|
||||
expect(await project.fileExists('.wxt/types/imports.d.ts')).toBe(false);
|
||||
});
|
||||
|
||||
it('should not include imports.d.ts in the type references', async () => {
|
||||
it('should only include imports-module.d.ts in the the project', async () => {
|
||||
const project = new TestProject();
|
||||
project.setConfigFileConfig({
|
||||
imports: false,
|
||||
@@ -94,10 +135,95 @@ describe('Auto Imports', () => {
|
||||
/// <reference path="./types/paths.d.ts" />
|
||||
/// <reference path="./types/i18n.d.ts" />
|
||||
/// <reference path="./types/globals.d.ts" />
|
||||
/// <reference path="./types/imports-module.d.ts" />
|
||||
"
|
||||
`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should only generate the #imports module', async () => {
|
||||
const project = new TestProject();
|
||||
project.setConfigFileConfig({
|
||||
imports: false,
|
||||
});
|
||||
project.addFile('entrypoints/popup.html', `<html></html>`);
|
||||
// Project auto-imports should also be present
|
||||
project.addFile(
|
||||
'utils/time.ts',
|
||||
`export function startOfDay(date: Date): Date {
|
||||
throw Error("TODO")
|
||||
}`,
|
||||
);
|
||||
|
||||
await project.prepare();
|
||||
|
||||
expect(await project.serializeFile('.wxt/types/imports-module.d.ts'))
|
||||
.toMatchInlineSnapshot(`
|
||||
".wxt/types/imports-module.d.ts
|
||||
----------------------------------------
|
||||
// Generated by wxt
|
||||
// Types for the #import virtual module
|
||||
declare module '#imports' {
|
||||
export { browser } from 'wxt/browser';
|
||||
export { MigrationError, storage } from 'wxt/storage';
|
||||
export { useAppConfig } from 'wxt/utils/app-config';
|
||||
export { ContentScriptContext } from 'wxt/utils/content-script-context';
|
||||
export { createIframeUi } from 'wxt/utils/content-script-ui/iframe';
|
||||
export { createIntegratedUi } from 'wxt/utils/content-script-ui/integrated';
|
||||
export { createShadowRootUi } from 'wxt/utils/content-script-ui/shadow-root';
|
||||
export { defineAppConfig } from 'wxt/utils/define-app-config';
|
||||
export { defineBackground } from 'wxt/utils/define-background';
|
||||
export { defineContentScript } from 'wxt/utils/define-content-script';
|
||||
export { defineUnlistedScript } from 'wxt/utils/define-unlisted-script';
|
||||
export { defineWxtPlugin } from 'wxt/utils/define-wxt-plugin';
|
||||
export { injectScript } from 'wxt/utils/inject-script';
|
||||
export { InvalidMatchPattern, MatchPattern } from 'wxt/utils/match-patterns';
|
||||
export { fakeBrowser } from 'wxt/testing';
|
||||
}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should still generate the #imports module', async () => {
|
||||
const project = new TestProject();
|
||||
project.addFile('entrypoints/popup.html', `<html></html>`);
|
||||
// Project auto-imports should also be exported
|
||||
project.addFile(
|
||||
'utils/time.ts',
|
||||
`export function startOfDay(date: Date): Date {
|
||||
throw Error("TODO")
|
||||
}`,
|
||||
);
|
||||
|
||||
await project.prepare();
|
||||
|
||||
expect(await project.serializeFile('.wxt/types/imports-module.d.ts'))
|
||||
.toMatchInlineSnapshot(`
|
||||
".wxt/types/imports-module.d.ts
|
||||
----------------------------------------
|
||||
// Generated by wxt
|
||||
// Types for the #import virtual module
|
||||
declare module '#imports' {
|
||||
export { browser } from 'wxt/browser';
|
||||
export { MigrationError, storage } from 'wxt/storage';
|
||||
export { useAppConfig } from 'wxt/utils/app-config';
|
||||
export { ContentScriptContext } from 'wxt/utils/content-script-context';
|
||||
export { createIframeUi } from 'wxt/utils/content-script-ui/iframe';
|
||||
export { createIntegratedUi } from 'wxt/utils/content-script-ui/integrated';
|
||||
export { createShadowRootUi } from 'wxt/utils/content-script-ui/shadow-root';
|
||||
export { defineAppConfig } from 'wxt/utils/define-app-config';
|
||||
export { defineBackground } from 'wxt/utils/define-background';
|
||||
export { defineContentScript } from 'wxt/utils/define-content-script';
|
||||
export { defineUnlistedScript } from 'wxt/utils/define-unlisted-script';
|
||||
export { defineWxtPlugin } from 'wxt/utils/define-wxt-plugin';
|
||||
export { injectScript } from 'wxt/utils/inject-script';
|
||||
export { InvalidMatchPattern, MatchPattern } from 'wxt/utils/match-patterns';
|
||||
export { fakeBrowser } from 'wxt/testing';
|
||||
export { startOfDay } from '../utils/time';
|
||||
}
|
||||
"
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('eslintrc', () => {
|
||||
|
||||
@@ -239,6 +239,7 @@ describe('TypeScript Project', () => {
|
||||
/// <reference path="./types/paths.d.ts" />
|
||||
/// <reference path="./types/i18n.d.ts" />
|
||||
/// <reference path="./types/globals.d.ts" />
|
||||
/// <reference path="./types/imports-module.d.ts" />
|
||||
/// <reference path="./types/imports.d.ts" />
|
||||
"
|
||||
`);
|
||||
|
||||
+107
-63
@@ -3,69 +3,7 @@
|
||||
"type": "module",
|
||||
"version": "0.19.29",
|
||||
"description": "⚡ Next-gen Web Extension Framework",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wxt-dev/wxt.git"
|
||||
},
|
||||
"homepage": "https://wxt.dev",
|
||||
"keywords": [
|
||||
"vite",
|
||||
"chrome",
|
||||
"web",
|
||||
"extension",
|
||||
"browser",
|
||||
"bundler",
|
||||
"framework"
|
||||
],
|
||||
"author": {
|
||||
"name": "Aaron Klinker",
|
||||
"email": "aaronklinker1+wxt@gmail.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"files": [
|
||||
"bin",
|
||||
"dist"
|
||||
],
|
||||
"bin": {
|
||||
"wxt": "./bin/wxt.mjs",
|
||||
"wxt-publish-extension": "./bin/wxt-publish-extension.cjs"
|
||||
},
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.mjs"
|
||||
},
|
||||
"./client": {
|
||||
"types": "./dist/client/index.d.ts",
|
||||
"default": "./dist/client/index.mjs"
|
||||
},
|
||||
"./sandbox": {
|
||||
"types": "./dist/sandbox/index.d.ts",
|
||||
"default": "./dist/sandbox/index.mjs"
|
||||
},
|
||||
"./browser": {
|
||||
"types": "./dist/browser.d.ts",
|
||||
"default": "./dist/browser.mjs"
|
||||
},
|
||||
"./testing": {
|
||||
"types": "./dist/testing/index.d.ts",
|
||||
"default": "./dist/testing/index.mjs"
|
||||
},
|
||||
"./storage": {
|
||||
"types": "./dist/storage.d.ts",
|
||||
"default": "./dist/storage.mjs"
|
||||
},
|
||||
"./vite-builder-env": {
|
||||
"types": "./dist/vite-builder-env.d.ts"
|
||||
},
|
||||
"./modules": {
|
||||
"types": "./dist/modules.d.ts",
|
||||
"default": "./dist/modules.mjs"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"wxt": "tsx src/cli/index.ts",
|
||||
"build": "buildc -- unbuild",
|
||||
@@ -142,5 +80,111 @@
|
||||
"vitest": "catalog:",
|
||||
"vitest-plugin-random-seed": "catalog:"
|
||||
},
|
||||
"peerDependenciesMeta": {}
|
||||
"peerDependenciesMeta": {},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wxt-dev/wxt.git"
|
||||
},
|
||||
"homepage": "https://wxt.dev",
|
||||
"keywords": [
|
||||
"vite",
|
||||
"chrome",
|
||||
"web",
|
||||
"extension",
|
||||
"browser",
|
||||
"bundler",
|
||||
"framework"
|
||||
],
|
||||
"author": {
|
||||
"name": "Aaron Klinker",
|
||||
"email": "aaronklinker1+wxt@gmail.com"
|
||||
},
|
||||
"funding": "https://github.com/sponsors/wxt-dev",
|
||||
"files": [
|
||||
"bin",
|
||||
"dist"
|
||||
],
|
||||
"bin": {
|
||||
"wxt": "./bin/wxt.mjs",
|
||||
"wxt-publish-extension": "./bin/wxt-publish-extension.cjs"
|
||||
},
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.mjs"
|
||||
},
|
||||
"./utils/app-config": {
|
||||
"types": "./dist/utils/app-config.d.ts",
|
||||
"default": "./dist/utils/app-config.mjs"
|
||||
},
|
||||
"./utils/inject-script": {
|
||||
"types": "./dist/utils/inject-script.d.ts",
|
||||
"default": "./dist/utils/inject-script.mjs"
|
||||
},
|
||||
"./utils/content-script-context": {
|
||||
"types": "./dist/utils/content-script-context.d.ts",
|
||||
"default": "./dist/utils/content-script-context.mjs"
|
||||
},
|
||||
"./utils/content-script-ui/types": {
|
||||
"types": "./dist/utils/content-script-ui/types.d.ts",
|
||||
"default": "./dist/utils/content-script-ui/types.mjs"
|
||||
},
|
||||
"./utils/content-script-ui/integrated": {
|
||||
"types": "./dist/utils/content-script-ui/integrated.d.ts",
|
||||
"default": "./dist/utils/content-script-ui/integrated.mjs"
|
||||
},
|
||||
"./utils/content-script-ui/shadow-root": {
|
||||
"types": "./dist/utils/content-script-ui/shadow-root.d.ts",
|
||||
"default": "./dist/utils/content-script-ui/shadow-root.mjs"
|
||||
},
|
||||
"./utils/content-script-ui/iframe": {
|
||||
"types": "./dist/utils/content-script-ui/iframe.d.ts",
|
||||
"default": "./dist/utils/content-script-ui/iframe.mjs"
|
||||
},
|
||||
"./utils/define-app-config": {
|
||||
"types": "./dist/utils/define-app-config.d.ts",
|
||||
"default": "./dist/utils/define-app-config.mjs"
|
||||
},
|
||||
"./utils/define-background": {
|
||||
"types": "./dist/utils/define-background.d.ts",
|
||||
"default": "./dist/utils/define-background.mjs"
|
||||
},
|
||||
"./utils/define-content-script": {
|
||||
"types": "./dist/utils/define-content-script.d.ts",
|
||||
"default": "./dist/utils/define-content-script.mjs"
|
||||
},
|
||||
"./utils/define-unlisted-script": {
|
||||
"types": "./dist/utils/define-unlisted-script.d.ts",
|
||||
"default": "./dist/utils/define-unlisted-script.mjs"
|
||||
},
|
||||
"./utils/define-wxt-plugin": {
|
||||
"types": "./dist/utils/define-wxt-plugin.d.ts",
|
||||
"default": "./dist/utils/define-wxt-plugin.mjs"
|
||||
},
|
||||
"./utils/match-patterns": {
|
||||
"types": "./dist/utils/match-patterns.d.ts",
|
||||
"default": "./dist/utils/match-patterns.mjs"
|
||||
},
|
||||
"./browser": {
|
||||
"types": "./dist/browser.d.ts",
|
||||
"default": "./dist/browser.mjs"
|
||||
},
|
||||
"./testing": {
|
||||
"types": "./dist/testing/index.d.ts",
|
||||
"default": "./dist/testing/index.mjs"
|
||||
},
|
||||
"./storage": {
|
||||
"types": "./dist/storage.d.ts",
|
||||
"default": "./dist/storage.mjs"
|
||||
},
|
||||
"./vite-builder-env": {
|
||||
"types": "./dist/vite-builder-env.d.ts"
|
||||
},
|
||||
"./modules": {
|
||||
"types": "./dist/modules.d.ts",
|
||||
"default": "./dist/modules.mjs"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,20 +67,5 @@ describe('Module Utilities', () => {
|
||||
|
||||
expect(wxt.config.imports && wxt.config.imports.presets).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("should not enable imports if they've been disabled", async () => {
|
||||
const preset = 'vue';
|
||||
const wxt = fakeWxt({
|
||||
hooks: createHooks(),
|
||||
config: {
|
||||
imports: false,
|
||||
},
|
||||
});
|
||||
|
||||
addImportPreset(wxt, preset);
|
||||
await wxt.hooks.callHook('config:resolved', wxt);
|
||||
|
||||
expect(wxt.config.imports).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
/**
|
||||
* Contains the `browser` export which you should use to access the extension APIs in your project:
|
||||
* ```ts
|
||||
* import { browser } from 'wxt/browser';
|
||||
*
|
||||
* browser.runtime.onInstalled.addListener(() => {
|
||||
* // ...
|
||||
* })
|
||||
* ```
|
||||
* @module wxt/browser
|
||||
*/
|
||||
import { browser as _browser, type Browser } from '@wxt-dev/browser';
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
import { addViteConfig, defineWxtModule } from '../modules';
|
||||
import type {
|
||||
EslintGlobalsPropValue,
|
||||
Wxt,
|
||||
WxtDirFileEntry,
|
||||
WxtModule,
|
||||
WxtResolvedUnimportOptions,
|
||||
} from '../types';
|
||||
import { type Unimport, createUnimport } from 'unimport';
|
||||
import { type Unimport, createUnimport, toExports } from 'unimport';
|
||||
import UnimportPlugin from 'unimport/unplugin';
|
||||
|
||||
export default defineWxtModule({
|
||||
name: 'wxt:built-in:unimport',
|
||||
setup(wxt) {
|
||||
const options = wxt.config.imports;
|
||||
if (options === false) return;
|
||||
|
||||
let unimport: Unimport;
|
||||
const isEnabled = () => !wxt.config.imports.disabled;
|
||||
|
||||
// Add user module imports to config
|
||||
wxt.hooks.hook('config:resolved', () => {
|
||||
const addModuleImports = (module: WxtModule<any>) => {
|
||||
if (!module.imports) return;
|
||||
|
||||
options.imports ??= [];
|
||||
options.imports.push(...module.imports);
|
||||
wxt.config.imports.imports ??= [];
|
||||
wxt.config.imports.imports.push(...module.imports);
|
||||
};
|
||||
|
||||
wxt.config.builtinModules.forEach(addModuleImports);
|
||||
@@ -33,7 +32,7 @@ export default defineWxtModule({
|
||||
// config inside "config:resolved" are applied.
|
||||
wxt.hooks.afterEach((event) => {
|
||||
if (event.name === 'config:resolved') {
|
||||
unimport = createUnimport(options);
|
||||
unimport = createUnimport(wxt.config.imports);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -42,17 +41,29 @@ export default defineWxtModule({
|
||||
// Update cache before each rebuild
|
||||
await unimport.init();
|
||||
|
||||
// Always generate the #import module types
|
||||
entries.push(await getImportsModuleEntry(wxt, unimport));
|
||||
|
||||
if (!isEnabled()) return;
|
||||
|
||||
// Only create global types when user has enabled auto-imports
|
||||
entries.push(await getImportsDeclarationEntry(unimport));
|
||||
|
||||
if (options.eslintrc.enabled === false) return;
|
||||
if (wxt.config.imports.eslintrc.enabled === false) return;
|
||||
|
||||
// Only generate ESLint config if that feature is enabled
|
||||
entries.push(
|
||||
await getEslintConfigEntry(unimport, options.eslintrc.enabled, options),
|
||||
await getEslintConfigEntry(
|
||||
unimport,
|
||||
wxt.config.imports.eslintrc.enabled,
|
||||
wxt.config.imports,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
// Add vite plugin
|
||||
addViteConfig(wxt, () => ({
|
||||
plugins: [UnimportPlugin.vite(options)],
|
||||
plugins: [UnimportPlugin.vite(wxt.config.imports)],
|
||||
}));
|
||||
},
|
||||
});
|
||||
@@ -60,9 +71,6 @@ export default defineWxtModule({
|
||||
async function getImportsDeclarationEntry(
|
||||
unimport: Unimport,
|
||||
): Promise<WxtDirFileEntry> {
|
||||
// Load project imports into unimport memory so they are output via generateTypeDeclarations
|
||||
await unimport.init();
|
||||
|
||||
return {
|
||||
path: 'types/imports.d.ts',
|
||||
text: [
|
||||
@@ -74,6 +82,25 @@ async function getImportsDeclarationEntry(
|
||||
};
|
||||
}
|
||||
|
||||
async function getImportsModuleEntry(
|
||||
wxt: Wxt,
|
||||
unimport: Unimport,
|
||||
): Promise<WxtDirFileEntry> {
|
||||
const imports = await unimport.getImports();
|
||||
return {
|
||||
path: 'types/imports-module.d.ts',
|
||||
text: [
|
||||
'// Generated by wxt',
|
||||
'// Types for the #import virtual module',
|
||||
"declare module '#imports' {",
|
||||
' ' + toExports(imports, wxt.config.wxtDir).replaceAll('\n', '\n '),
|
||||
'}',
|
||||
'',
|
||||
].join('\n'),
|
||||
tsReference: true,
|
||||
};
|
||||
}
|
||||
|
||||
async function getEslintConfigEntry(
|
||||
unimport: Unimport,
|
||||
version: 8 | 9,
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './content-script-context';
|
||||
export * from './ui';
|
||||
@@ -1,8 +0,0 @@
|
||||
/**
|
||||
* Any runtime APIs that use the web extension APIs.
|
||||
*
|
||||
* @module wxt/client
|
||||
*/
|
||||
export * from './content-scripts';
|
||||
export * from './app-config';
|
||||
export * from './inject-script';
|
||||
@@ -15,7 +15,7 @@ export function noopBackground(): Plugin {
|
||||
},
|
||||
load(id) {
|
||||
if (id === resolvedVirtualModuleId) {
|
||||
return `import { defineBackground } from 'wxt/sandbox';\nexport default defineBackground(() => void 0)`;
|
||||
return `import { defineBackground } from 'wxt/utils/define-background';\nexport default defineBackground(() => void 0)`;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -232,10 +232,11 @@ async function getTsConfigEntry(): Promise<WxtDirFileEntry> {
|
||||
.flatMap(([alias, absolutePath]) => {
|
||||
const aliasPath = getTsconfigPath(absolutePath);
|
||||
return [
|
||||
` "${alias}": ["${aliasPath}"]`,
|
||||
` "${alias}/*": ["${aliasPath}/*"]`,
|
||||
`"${alias}": ["${aliasPath}"]`,
|
||||
`"${alias}/*": ["${aliasPath}/*"]`,
|
||||
];
|
||||
})
|
||||
.map((line) => ` ${line}`)
|
||||
.join(',\n');
|
||||
|
||||
const text = `{
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
WxtModule,
|
||||
WxtModuleWithMetadata,
|
||||
ResolvedEslintrc,
|
||||
Eslintrc,
|
||||
} from '../types';
|
||||
import path from 'node:path';
|
||||
import { createFsCache } from './utils/cache';
|
||||
@@ -332,33 +331,40 @@ async function getUnimportOptions(
|
||||
srcDir: string,
|
||||
logger: Logger,
|
||||
config: InlineConfig,
|
||||
): Promise<WxtResolvedUnimportOptions | false> {
|
||||
if (config.imports === false) return false;
|
||||
|
||||
): Promise<WxtResolvedUnimportOptions> {
|
||||
const disabled = config.imports === false;
|
||||
const eslintrc = await getUnimportEslintOptions(wxtDir, config.imports);
|
||||
// mlly sometimes picks up things as exports that aren't. That's what this array contains.
|
||||
const invalidExports = ['options'];
|
||||
const defaultOptions: WxtResolvedUnimportOptions = {
|
||||
debugLog: logger.debug,
|
||||
imports: [
|
||||
{ name: 'defineConfig', from: 'wxt' },
|
||||
{ name: 'fakeBrowser', from: 'wxt/testing' },
|
||||
],
|
||||
imports: [{ name: 'fakeBrowser', from: 'wxt/testing' }],
|
||||
// prettier-ignore
|
||||
presets: [
|
||||
{
|
||||
package: 'wxt/client',
|
||||
// There seems to be a bug in unimport that thinks "options" is an
|
||||
// export from wxt/client, but it doesn't actually exist... so it's
|
||||
// ignored.
|
||||
ignore: ['options'],
|
||||
},
|
||||
{ package: 'wxt/browser' },
|
||||
{ package: 'wxt/sandbox' },
|
||||
{ package: 'wxt/storage' },
|
||||
{ package: 'wxt/utils/app-config' },
|
||||
{ package: 'wxt/utils/content-script-context' },
|
||||
{ package: 'wxt/utils/content-script-ui/iframe', ignore: invalidExports },
|
||||
{ package: 'wxt/utils/content-script-ui/integrated', ignore: invalidExports },
|
||||
{ package: 'wxt/utils/content-script-ui/shadow-root', ignore: invalidExports },
|
||||
{ package: 'wxt/utils/content-script-ui/types' },
|
||||
{ package: 'wxt/utils/define-app-config' },
|
||||
{ package: 'wxt/utils/define-background' },
|
||||
{ package: 'wxt/utils/define-content-script' },
|
||||
{ package: 'wxt/utils/define-unlisted-script' },
|
||||
{ package: 'wxt/utils/define-wxt-plugin' },
|
||||
{ package: 'wxt/utils/inject-script', ignore: invalidExports },
|
||||
{ package: 'wxt/utils/match-patterns' },
|
||||
],
|
||||
virtualImports: ['#imports'],
|
||||
debugLog: logger.debug,
|
||||
warn: logger.warn,
|
||||
dirs: ['components', 'composables', 'hooks', 'utils'],
|
||||
dirsScanOptions: {
|
||||
cwd: srcDir,
|
||||
},
|
||||
eslintrc: await getUnimportEslintOptions(wxtDir, config.imports?.eslintrc),
|
||||
eslintrc,
|
||||
dirs: disabled ? [] : ['components', 'composables', 'hooks', 'utils'],
|
||||
disabled,
|
||||
};
|
||||
|
||||
return defu<WxtResolvedUnimportOptions, [WxtResolvedUnimportOptions]>(
|
||||
@@ -369,34 +375,34 @@ async function getUnimportOptions(
|
||||
|
||||
async function getUnimportEslintOptions(
|
||||
wxtDir: string,
|
||||
options: Eslintrc | undefined,
|
||||
options: InlineConfig['imports'],
|
||||
): Promise<ResolvedEslintrc> {
|
||||
const rawEslintEnabled = options?.enabled ?? 'auto';
|
||||
let eslintEnabled: ResolvedEslintrc['enabled'];
|
||||
switch (rawEslintEnabled) {
|
||||
const inlineEnabled =
|
||||
options === false ? false : (options?.eslintrc?.enabled ?? 'auto');
|
||||
|
||||
let enabled: ResolvedEslintrc['enabled'];
|
||||
switch (inlineEnabled) {
|
||||
case 'auto':
|
||||
const version = await getEslintVersion();
|
||||
let major = parseInt(version[0]);
|
||||
if (isNaN(major)) eslintEnabled = false;
|
||||
if (major <= 8) eslintEnabled = 8;
|
||||
else if (major >= 9) eslintEnabled = 9;
|
||||
if (isNaN(major)) enabled = false;
|
||||
if (major <= 8) enabled = 8;
|
||||
else if (major >= 9) enabled = 9;
|
||||
// NaN
|
||||
else eslintEnabled = false;
|
||||
else enabled = false;
|
||||
break;
|
||||
case true:
|
||||
eslintEnabled = 8;
|
||||
enabled = 8;
|
||||
break;
|
||||
default:
|
||||
eslintEnabled = rawEslintEnabled;
|
||||
enabled = inlineEnabled;
|
||||
}
|
||||
|
||||
return {
|
||||
enabled: eslintEnabled,
|
||||
enabled,
|
||||
filePath: path.resolve(
|
||||
wxtDir,
|
||||
eslintEnabled === 9
|
||||
? 'eslint-auto-imports.mjs'
|
||||
: 'eslintrc-auto-import.json',
|
||||
enabled === 9 ? 'eslint-auto-imports.mjs' : 'eslintrc-auto-import.json',
|
||||
),
|
||||
globalsPropValue: true,
|
||||
};
|
||||
|
||||
@@ -57,13 +57,13 @@ describe('Transform Utils', () => {
|
||||
|
||||
it('should remove unused imports', () => {
|
||||
const input = `
|
||||
import { defineBackground } from "wxt/sandbox"
|
||||
import { defineBackground } from "#imports"
|
||||
import { test1 } from "somewhere1"
|
||||
import test2 from "somewhere2"
|
||||
|
||||
export default defineBackground(() => {})
|
||||
`;
|
||||
const expected = `import { defineBackground } from "wxt/sandbox"
|
||||
const expected = `import { defineBackground } from "#imports"
|
||||
|
||||
export default defineBackground();`;
|
||||
|
||||
@@ -74,13 +74,13 @@ export default defineBackground();`;
|
||||
|
||||
it('should remove explict side-effect imports', () => {
|
||||
const input = `
|
||||
import { defineBackground } from "wxt/sandbox"
|
||||
import { defineBackground } from "#imports"
|
||||
import "my-polyfill"
|
||||
import "./style.css"
|
||||
|
||||
export default defineBackground(() => {})
|
||||
`;
|
||||
const expected = `import { defineBackground } from "wxt/sandbox"
|
||||
const expected = `import { defineBackground } from "#imports"
|
||||
|
||||
export default defineBackground();`;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineBackground } from '../../../../../sandbox';
|
||||
import { defineBackground } from '../../../../../utils/define-background';
|
||||
|
||||
export default defineBackground({
|
||||
main() {},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineContentScript } from '../../../../../sandbox';
|
||||
import { defineContentScript } from '../../../../../utils/define-content-script';
|
||||
|
||||
export default defineContentScript({
|
||||
matches: ['<all_urls>'],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineContentScript } from '../../../../../sandbox';
|
||||
import { defineContentScript } from '../../../../../utils/define-content-script';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
export default defineContentScript({
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { defineUnlistedScript } from '../../../../../sandbox';
|
||||
import { defineUnlistedScript } from '../../../../../utils/define-unlisted-script';
|
||||
|
||||
export default defineUnlistedScript(() => {});
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { defineUnlistedScript } from '../../../../../sandbox';
|
||||
import { defineUnlistedScript } from '../../../../../utils/define-unlisted-script';
|
||||
|
||||
export default defineUnlistedScript(() => {});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defineBackground } from '../../../../../sandbox';
|
||||
import { defineBackground } from '../../../../../utils/define-background';
|
||||
|
||||
export const a = {};
|
||||
|
||||
|
||||
@@ -243,6 +243,7 @@ export const fakeResolvedConfig = fakeObjectCreator<ResolvedConfig>(() => {
|
||||
env: { browser, command, manifestVersion, mode },
|
||||
fsCache: mock<FsCache>(),
|
||||
imports: {
|
||||
disabled: faker.datatype.boolean(),
|
||||
eslintrc: {
|
||||
enabled: faker.helpers.arrayElement([false, 8, 9]),
|
||||
filePath: fakeFile(),
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
/**
|
||||
* This module contains:
|
||||
* - JS APIs used by the CLI to build extensions or start dev mode.
|
||||
* - Helper functions for defining project config.
|
||||
* - Types for building and extension or configuring WXT.
|
||||
*
|
||||
* @module wxt
|
||||
*/
|
||||
export * from './core';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Utilities for creating reusable, build-time modules for WXT.
|
||||
* Utilities for creating [WXT Modules](https://wxt.dev/guide/essentials/wxt-modules.html).
|
||||
*
|
||||
* @module wxt/modules
|
||||
*/
|
||||
@@ -167,6 +167,7 @@ export function addImportPreset(
|
||||
preset: UnimportOptions['presets'][0],
|
||||
): void {
|
||||
wxt.hooks.hook('config:resolved', (wxt) => {
|
||||
// In older versions of WXT, `wxt.config.imports` could be false
|
||||
if (!wxt.config.imports) return;
|
||||
|
||||
wxt.config.imports.presets ??= [];
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* Any runtime APIs that don't use the web extension APIs.
|
||||
*
|
||||
* @module wxt/sandbox
|
||||
*/
|
||||
export * from './define-unlisted-script';
|
||||
export * from './define-background';
|
||||
export * from './define-content-script';
|
||||
export * from './define-wxt-plugin';
|
||||
export * from './define-app-config';
|
||||
export * from '@webext-core/match-patterns';
|
||||
@@ -1,4 +1,5 @@
|
||||
/**
|
||||
* @module @wxt-dev/storage
|
||||
* Re-export the [`@wxt-dev/storage` package](https://www.npmjs.com/package/@wxt-dev/storage).
|
||||
* @module wxt/storage
|
||||
*/
|
||||
export * from '@wxt-dev/storage';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/**
|
||||
* Utilities for unit testing WXT extensions.
|
||||
* @module wxt/testing
|
||||
*/
|
||||
export * from './fake-browser';
|
||||
|
||||
@@ -37,9 +37,7 @@ export async function WxtVitest(
|
||||
resolveAppConfig(wxt.config),
|
||||
extensionApiMock(wxt.config),
|
||||
];
|
||||
if (wxt.config.imports !== false) {
|
||||
plugins.push(UnimportPlugin.vite(wxt.config.imports));
|
||||
}
|
||||
plugins.push(UnimportPlugin.vite(wxt.config.imports));
|
||||
|
||||
return plugins;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type * as vite from 'vite';
|
||||
import { UnimportOptions, Import } from 'unimport';
|
||||
import { LogLevel } from 'consola';
|
||||
import type { ContentScriptContext } from './client/content-scripts/content-script-context';
|
||||
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';
|
||||
@@ -1297,7 +1297,7 @@ export interface ResolvedConfig {
|
||||
manifestVersion: TargetManifestVersion;
|
||||
env: ConfigEnv;
|
||||
logger: Logger;
|
||||
imports: false | WxtResolvedUnimportOptions;
|
||||
imports: WxtResolvedUnimportOptions;
|
||||
manifest: UserManifest;
|
||||
fsCache: FsCache;
|
||||
runnerConfig: C12ResolvedConfig<WebExtConfig>;
|
||||
@@ -1441,6 +1441,12 @@ export type WxtUnimportOptions = Partial<UnimportOptions> & {
|
||||
};
|
||||
|
||||
export type WxtResolvedUnimportOptions = Partial<UnimportOptions> & {
|
||||
/**
|
||||
* Set to `true` when the user disabled auto-imports. We still use unimport for the #imports module, but other features should be disabled.
|
||||
*
|
||||
* You don't need to check this value before modifying the auto-import options. Even if `disabled` is `true`, there's no harm in adding imports to the config - they'll just be ignored.
|
||||
*/
|
||||
disabled: boolean;
|
||||
eslintrc: ResolvedEslintrc;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
This folder is for public utils, not internal utils. Put generic helpers and other utils in the core/utils folder.
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/** @vitest-environment happy-dom */
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { ContentScriptContext } from '..';
|
||||
import { ContentScriptContext } from '../content-script-context';
|
||||
import { fakeBrowser } from '@webext-core/fake-browser';
|
||||
|
||||
/**
|
||||
@@ -1,6 +1,7 @@
|
||||
/** @module wxt/utils/app-config */
|
||||
// @ts-expect-error: Untyped virtual module
|
||||
import appConfig from 'virtual:app-config';
|
||||
import type { WxtAppConfig } from '../sandbox/define-app-config';
|
||||
import type { WxtAppConfig } from '../utils/define-app-config';
|
||||
|
||||
export function useAppConfig(): WxtAppConfig {
|
||||
return appConfig;
|
||||
+9
-5
@@ -1,8 +1,12 @@
|
||||
import { ContentScriptDefinition } from '../../types';
|
||||
/** @module wxt/utils/content-script-context */
|
||||
import { ContentScriptDefinition } from '../types';
|
||||
import { browser } from 'wxt/browser';
|
||||
import { logger } from '../../sandbox/utils/logger';
|
||||
import { WxtLocationChangeEvent, getUniqueEventName } from './custom-events';
|
||||
import { createLocationWatcher } from './location-watcher';
|
||||
import { logger } from '../utils/internal/logger';
|
||||
import {
|
||||
WxtLocationChangeEvent,
|
||||
getUniqueEventName,
|
||||
} from './internal/custom-events';
|
||||
import { createLocationWatcher } from './internal/location-watcher';
|
||||
|
||||
/**
|
||||
* Implements [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController).
|
||||
@@ -14,7 +18,7 @@ import { createLocationWatcher } from './location-watcher';
|
||||
* To create context for testing, you can use the class's constructor:
|
||||
*
|
||||
* ```ts
|
||||
* import { ContentScriptContext } from 'wxt/client';
|
||||
* import { ContentScriptContext } from 'wxt/utils/content-scripts-context';
|
||||
*
|
||||
* test("storage listener should be removed when context is invalidated", () => {
|
||||
* const ctx = new ContentScriptContext('test');
|
||||
+5
-7
@@ -1,12 +1,10 @@
|
||||
/** @vitest-environment happy-dom */
|
||||
import { describe, it, beforeEach, afterEach, vi, expect } from 'vitest';
|
||||
import {
|
||||
createIntegratedUi,
|
||||
createIframeUi,
|
||||
createShadowRootUi,
|
||||
ContentScriptUi,
|
||||
} from '..';
|
||||
import { describe, it, beforeEach, vi, expect, afterEach } from 'vitest';
|
||||
import { createIntegratedUi } from '../integrated';
|
||||
import { createIframeUi } from '../iframe';
|
||||
import { createShadowRootUi } from '../shadow-root';
|
||||
import { ContentScriptContext } from '../../content-script-context';
|
||||
import { ContentScriptUi } from '../types';
|
||||
|
||||
/**
|
||||
* Util for floating promise.
|
||||
@@ -0,0 +1,50 @@
|
||||
/** @module wxt/utils/content-script-ui/iframe */
|
||||
import { browser } from 'wxt/browser';
|
||||
import { ContentScriptContext } from '../content-script-context';
|
||||
import type {
|
||||
IframeContentScriptUi,
|
||||
IframeContentScriptUiOptions,
|
||||
} from './types';
|
||||
import { applyPosition, createMountFunctions, mountUi } from './shared';
|
||||
|
||||
/**
|
||||
* Create a content script UI using an iframe.
|
||||
*
|
||||
* @see https://wxt.dev/guide/essentials/content-scripts.html#iframe
|
||||
*/
|
||||
export function createIframeUi<TMounted>(
|
||||
ctx: ContentScriptContext,
|
||||
options: IframeContentScriptUiOptions<TMounted>,
|
||||
): IframeContentScriptUi<TMounted> {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.setAttribute('data-wxt-iframe', '');
|
||||
const iframe = document.createElement('iframe');
|
||||
// @ts-expect-error: getURL is defined per-project, but not inside the package
|
||||
iframe.src = browser.runtime.getURL(options.page);
|
||||
wrapper.appendChild(iframe);
|
||||
|
||||
let mounted: TMounted | undefined = undefined;
|
||||
const mount = () => {
|
||||
applyPosition(wrapper, iframe, options);
|
||||
mountUi(wrapper, options);
|
||||
mounted = options.onMount?.(wrapper, iframe);
|
||||
};
|
||||
const remove = () => {
|
||||
options.onRemove?.(mounted);
|
||||
wrapper.remove();
|
||||
mounted = undefined;
|
||||
};
|
||||
|
||||
const mountFunctions = createMountFunctions({ mount, remove }, options);
|
||||
|
||||
ctx.onInvalidated(remove);
|
||||
|
||||
return {
|
||||
get mounted() {
|
||||
return mounted;
|
||||
},
|
||||
iframe,
|
||||
wrapper,
|
||||
...mountFunctions,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/** @module wxt/utils/content-script-ui/integrated */
|
||||
import { ContentScriptContext } from '../content-script-context';
|
||||
import type {
|
||||
IntegratedContentScriptUi,
|
||||
IntegratedContentScriptUiOptions,
|
||||
} from './types';
|
||||
import { applyPosition, createMountFunctions, mountUi } from './shared';
|
||||
|
||||
/**
|
||||
* Create a content script UI without any isolation.
|
||||
*
|
||||
* @see https://wxt.dev/guide/essentials/content-scripts.html#integrated
|
||||
*/
|
||||
export function createIntegratedUi<TMounted>(
|
||||
ctx: ContentScriptContext,
|
||||
options: IntegratedContentScriptUiOptions<TMounted>,
|
||||
): IntegratedContentScriptUi<TMounted> {
|
||||
const wrapper = document.createElement(options.tag || 'div');
|
||||
wrapper.setAttribute('data-wxt-integrated', '');
|
||||
|
||||
let mounted: TMounted | undefined = undefined;
|
||||
const mount = () => {
|
||||
applyPosition(wrapper, undefined, options);
|
||||
mountUi(wrapper, options);
|
||||
mounted = options.onMount?.(wrapper);
|
||||
};
|
||||
const remove = () => {
|
||||
options.onRemove?.(mounted);
|
||||
wrapper.replaceChildren();
|
||||
wrapper.remove();
|
||||
mounted = undefined;
|
||||
};
|
||||
|
||||
const mountFunctions = createMountFunctions(
|
||||
{
|
||||
mount,
|
||||
remove,
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
ctx.onInvalidated(remove);
|
||||
|
||||
return {
|
||||
get mounted() {
|
||||
return mounted;
|
||||
},
|
||||
wrapper,
|
||||
...mountFunctions,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/** @module wxt/utils/content-script-ui/shadow-root */
|
||||
import { ContentScriptContext } from '../content-script-context';
|
||||
import type {
|
||||
ShadowRootContentScriptUi,
|
||||
ShadowRootContentScriptUiOptions,
|
||||
} from './types';
|
||||
import { createIsolatedElement } from '@webext-core/isolated-element';
|
||||
import { applyPosition, createMountFunctions, mountUi } from './shared';
|
||||
import { logger } from '../internal/logger';
|
||||
|
||||
/**
|
||||
* Create a content script UI inside a [`ShadowRoot`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot).
|
||||
*
|
||||
* > This function is async because it has to load the CSS via a network call.
|
||||
*
|
||||
* @see https://wxt.dev/guide/essentials/content-scripts.html#shadow-root
|
||||
*/
|
||||
export async function createShadowRootUi<TMounted>(
|
||||
ctx: ContentScriptContext,
|
||||
options: ShadowRootContentScriptUiOptions<TMounted>,
|
||||
): Promise<ShadowRootContentScriptUi<TMounted>> {
|
||||
const css = [options.css ?? ''];
|
||||
if (ctx.options?.cssInjectionMode === 'ui') {
|
||||
const entryCss = await loadCss();
|
||||
// Replace :root selectors with :host since we're in a shadow root
|
||||
css.push(entryCss.replaceAll(':root', ':host'));
|
||||
}
|
||||
|
||||
const {
|
||||
isolatedElement: uiContainer,
|
||||
parentElement: shadowHost,
|
||||
shadow,
|
||||
} = await createIsolatedElement({
|
||||
name: options.name,
|
||||
css: {
|
||||
textContent: css.join('\n').trim(),
|
||||
},
|
||||
mode: options.mode ?? 'open',
|
||||
isolateEvents: options.isolateEvents,
|
||||
});
|
||||
shadowHost.setAttribute('data-wxt-shadow-root', '');
|
||||
|
||||
let mounted: TMounted | undefined;
|
||||
|
||||
const mount = () => {
|
||||
// Add shadow root element to DOM
|
||||
mountUi(shadowHost, options);
|
||||
applyPosition(shadowHost, shadow.querySelector('html'), options);
|
||||
// Mount UI inside shadow root
|
||||
mounted = options.onMount(uiContainer, shadow, shadowHost);
|
||||
};
|
||||
|
||||
const remove = () => {
|
||||
// Cleanup mounted state
|
||||
options.onRemove?.(mounted);
|
||||
// Detach shadow root from DOM
|
||||
shadowHost.remove();
|
||||
// Remove children from uiContainer
|
||||
while (uiContainer.lastChild)
|
||||
uiContainer.removeChild(uiContainer.lastChild);
|
||||
// Clear mounted value
|
||||
mounted = undefined;
|
||||
};
|
||||
|
||||
const mountFunctions = createMountFunctions(
|
||||
{
|
||||
mount,
|
||||
remove,
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
ctx.onInvalidated(remove);
|
||||
|
||||
return {
|
||||
shadow,
|
||||
shadowHost,
|
||||
uiContainer,
|
||||
...mountFunctions,
|
||||
get mounted() {
|
||||
return mounted;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the CSS for the current entrypoint.
|
||||
*/
|
||||
async function loadCss(): Promise<string> {
|
||||
// @ts-expect-error: getURL is defined per-project, but not inside the package
|
||||
const url = browser.runtime.getURL(
|
||||
`/content-scripts/${import.meta.env.ENTRYPOINT}.css`,
|
||||
);
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
return await res.text();
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
`Failed to load styles @ ${url}. Did you forget to import the stylesheet in your entrypoint?`,
|
||||
err,
|
||||
);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
+16
-211
@@ -1,197 +1,20 @@
|
||||
import { browser } from 'wxt/browser';
|
||||
import type {
|
||||
ContentScriptAnchoredOptions,
|
||||
ContentScriptPositioningOptions,
|
||||
AutoMount,
|
||||
AutoMountOptions,
|
||||
BaseMountFunctions,
|
||||
ContentScriptUiOptions,
|
||||
MountFunctions,
|
||||
} from './types';
|
||||
import { waitElement } from '@1natsu/wait-element';
|
||||
import {
|
||||
isExist as mountDetector,
|
||||
isNotExist as removeDetector,
|
||||
} from '@1natsu/wait-element/detectors';
|
||||
import { ContentScriptContext } from '..';
|
||||
import {
|
||||
AutoMount,
|
||||
AutoMountOptions,
|
||||
BaseMountFunctions,
|
||||
ContentScriptAnchoredOptions,
|
||||
ContentScriptPositioningOptions,
|
||||
ContentScriptUiOptions,
|
||||
IframeContentScriptUi,
|
||||
IframeContentScriptUiOptions,
|
||||
IntegratedContentScriptUi,
|
||||
IntegratedContentScriptUiOptions,
|
||||
MountFunctions,
|
||||
ShadowRootContentScriptUi,
|
||||
ShadowRootContentScriptUiOptions,
|
||||
} from './types';
|
||||
import { logger } from '../../../sandbox/utils/logger';
|
||||
import { createIsolatedElement } from '@webext-core/isolated-element';
|
||||
export * from './types';
|
||||
import { logger } from '../../utils/internal/logger';
|
||||
|
||||
/**
|
||||
* Create a content script UI without any isolation.
|
||||
*
|
||||
* @see https://wxt.dev/guide/essentials/content-scripts.html#integrated
|
||||
*/
|
||||
export function createIntegratedUi<TMounted>(
|
||||
ctx: ContentScriptContext,
|
||||
options: IntegratedContentScriptUiOptions<TMounted>,
|
||||
): IntegratedContentScriptUi<TMounted> {
|
||||
const wrapper = document.createElement(options.tag || 'div');
|
||||
wrapper.setAttribute('data-wxt-integrated', '');
|
||||
|
||||
let mounted: TMounted | undefined = undefined;
|
||||
const mount = () => {
|
||||
applyPosition(wrapper, undefined, options);
|
||||
mountUi(wrapper, options);
|
||||
mounted = options.onMount?.(wrapper);
|
||||
};
|
||||
const remove = () => {
|
||||
options.onRemove?.(mounted);
|
||||
wrapper.replaceChildren();
|
||||
wrapper.remove();
|
||||
mounted = undefined;
|
||||
};
|
||||
|
||||
const mountFunctions = createMountFunctions(
|
||||
{
|
||||
mount,
|
||||
remove,
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
ctx.onInvalidated(remove);
|
||||
|
||||
return {
|
||||
get mounted() {
|
||||
return mounted;
|
||||
},
|
||||
wrapper,
|
||||
...mountFunctions,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a content script UI using an iframe.
|
||||
*
|
||||
* @see https://wxt.dev/guide/essentials/content-scripts.html#iframe
|
||||
*/
|
||||
export function createIframeUi<TMounted>(
|
||||
ctx: ContentScriptContext,
|
||||
options: IframeContentScriptUiOptions<TMounted>,
|
||||
): IframeContentScriptUi<TMounted> {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.setAttribute('data-wxt-iframe', '');
|
||||
const iframe = document.createElement('iframe');
|
||||
// @ts-expect-error: getURL is defined per-project, but not inside the package
|
||||
iframe.src = browser.runtime.getURL(options.page);
|
||||
wrapper.appendChild(iframe);
|
||||
|
||||
let mounted: TMounted | undefined = undefined;
|
||||
const mount = () => {
|
||||
applyPosition(wrapper, iframe, options);
|
||||
mountUi(wrapper, options);
|
||||
mounted = options.onMount?.(wrapper, iframe);
|
||||
};
|
||||
const remove = () => {
|
||||
options.onRemove?.(mounted);
|
||||
wrapper.remove();
|
||||
mounted = undefined;
|
||||
};
|
||||
|
||||
const mountFunctions = createMountFunctions(
|
||||
{
|
||||
mount,
|
||||
remove,
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
ctx.onInvalidated(remove);
|
||||
|
||||
return {
|
||||
get mounted() {
|
||||
return mounted;
|
||||
},
|
||||
iframe,
|
||||
wrapper,
|
||||
...mountFunctions,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a content script UI inside a [`ShadowRoot`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot).
|
||||
*
|
||||
* > This function is async because it has to load the CSS via a network call.
|
||||
*
|
||||
* @see https://wxt.dev/guide/essentials/content-scripts.html#shadow-root
|
||||
*/
|
||||
export async function createShadowRootUi<TMounted>(
|
||||
ctx: ContentScriptContext,
|
||||
options: ShadowRootContentScriptUiOptions<TMounted>,
|
||||
): Promise<ShadowRootContentScriptUi<TMounted>> {
|
||||
const css = [options.css ?? ''];
|
||||
if (ctx.options?.cssInjectionMode === 'ui') {
|
||||
const entryCss = await loadCss();
|
||||
// Replace :root selectors with :host since we're in a shadow root
|
||||
css.push(entryCss.replaceAll(':root', ':host'));
|
||||
}
|
||||
|
||||
const {
|
||||
isolatedElement: uiContainer,
|
||||
parentElement: shadowHost,
|
||||
shadow,
|
||||
} = await createIsolatedElement({
|
||||
name: options.name,
|
||||
css: {
|
||||
textContent: css.join('\n').trim(),
|
||||
},
|
||||
mode: options.mode ?? 'open',
|
||||
isolateEvents: options.isolateEvents,
|
||||
});
|
||||
shadowHost.setAttribute('data-wxt-shadow-root', '');
|
||||
|
||||
let mounted: TMounted | undefined;
|
||||
|
||||
const mount = () => {
|
||||
// Add shadow root element to DOM
|
||||
mountUi(shadowHost, options);
|
||||
applyPosition(shadowHost, shadow.querySelector('html'), options);
|
||||
// Mount UI inside shadow root
|
||||
mounted = options.onMount(uiContainer, shadow, shadowHost);
|
||||
};
|
||||
|
||||
const remove = () => {
|
||||
// Cleanup mounted state
|
||||
options.onRemove?.(mounted);
|
||||
// Detach shadow root from DOM
|
||||
shadowHost.remove();
|
||||
// Remove children from uiContainer
|
||||
while (uiContainer.lastChild)
|
||||
uiContainer.removeChild(uiContainer.lastChild);
|
||||
// Clear mounted value
|
||||
mounted = undefined;
|
||||
};
|
||||
|
||||
const mountFunctions = createMountFunctions(
|
||||
{
|
||||
mount,
|
||||
remove,
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
ctx.onInvalidated(remove);
|
||||
|
||||
return {
|
||||
shadow,
|
||||
shadowHost,
|
||||
uiContainer,
|
||||
...mountFunctions,
|
||||
get mounted() {
|
||||
return mounted;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function applyPosition(
|
||||
export function applyPosition(
|
||||
root: HTMLElement,
|
||||
positionedElement: HTMLElement | undefined | null,
|
||||
options: ContentScriptPositioningOptions,
|
||||
@@ -227,7 +50,9 @@ function applyPosition(
|
||||
}
|
||||
}
|
||||
|
||||
function getAnchor(options: ContentScriptAnchoredOptions): Element | undefined {
|
||||
export function getAnchor(
|
||||
options: ContentScriptAnchoredOptions,
|
||||
): Element | undefined {
|
||||
if (options.anchor == null) return document.body;
|
||||
|
||||
let resolved =
|
||||
@@ -254,7 +79,7 @@ function getAnchor(options: ContentScriptAnchoredOptions): Element | undefined {
|
||||
return resolved ?? undefined;
|
||||
}
|
||||
|
||||
function mountUi(
|
||||
export function mountUi(
|
||||
root: HTMLElement,
|
||||
options: ContentScriptAnchoredOptions,
|
||||
): void {
|
||||
@@ -287,7 +112,7 @@ function mountUi(
|
||||
}
|
||||
}
|
||||
|
||||
function createMountFunctions<TMounted>(
|
||||
export function createMountFunctions<TMounted>(
|
||||
baseFunctions: BaseMountFunctions,
|
||||
options: ContentScriptUiOptions<TMounted>,
|
||||
): MountFunctions {
|
||||
@@ -392,23 +217,3 @@ function autoMountUi(
|
||||
|
||||
return { stopAutoMount: _stopAutoMount };
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the CSS for the current entrypoint.
|
||||
*/
|
||||
async function loadCss(): Promise<string> {
|
||||
// @ts-expect-error: getURL is defined per-project, but not inside the package
|
||||
const url = browser.runtime.getURL(
|
||||
`/content-scripts/${import.meta.env.ENTRYPOINT}.css`,
|
||||
);
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
return await res.text();
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
`Failed to load styles @ ${url}. Did you forget to import the stylesheet in your entrypoint?`,
|
||||
err,
|
||||
);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
+4
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Shared types for the different `wxt/utils/content-script-ui/*` modules.
|
||||
* @module wxt/utils/content-script-ui/types
|
||||
*/
|
||||
export interface IntegratedContentScriptUi<TMounted>
|
||||
extends ContentScriptUi<TMounted> {
|
||||
/**
|
||||
+3
-2
@@ -1,3 +1,4 @@
|
||||
/** @module wxt/utils/define-app-config */
|
||||
export interface WxtAppConfig {}
|
||||
|
||||
/**
|
||||
@@ -7,9 +8,9 @@ export interface WxtAppConfig {}
|
||||
*
|
||||
* ```ts
|
||||
* // app.config.ts
|
||||
* import 'wxt/sandbox';
|
||||
* import 'wxt/utils/define-app-config';
|
||||
*
|
||||
* declare module "wxt/sandbox" {
|
||||
* declare module "wxt/utils/define-app-config" {
|
||||
* export interface WxtAppConfig {
|
||||
* analytics: AnalyticsConfig
|
||||
* }
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
/** @module wxt/utils/define-background */
|
||||
import type { BackgroundDefinition } from '../types';
|
||||
|
||||
export function defineBackground(main: () => void): BackgroundDefinition;
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
/** @module wxt/utils/define-content-script */
|
||||
import type { ContentScriptDefinition } from '../types';
|
||||
|
||||
export function defineContentScript(
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
/** @module wxt/utils/define-unlisted-script */
|
||||
import type { UnlistedScriptDefinition } from '../types';
|
||||
|
||||
export function defineUnlistedScript(
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
/** @module wxt/utils/define-wxt-plugin */
|
||||
import type { WxtPlugin } from '../types';
|
||||
|
||||
export function defineWxtPlugin(plugin: WxtPlugin): WxtPlugin {
|
||||
@@ -1,3 +1,4 @@
|
||||
/** @module wxt/utils/inject-script */
|
||||
import { browser } from 'wxt/browser';
|
||||
|
||||
export type ScriptPublicPath = Extract<
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { logger } from './utils/logger';
|
||||
import { logger } from './logger';
|
||||
|
||||
interface WebSocketMessage {
|
||||
type: string;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { ContentScriptContext } from '.';
|
||||
import { ContentScriptContext } from '../content-script-context';
|
||||
import { WxtLocationChangeEvent } from './custom-events';
|
||||
|
||||
/**
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Re-export the [`@webext-core/match-patterns` package](https://www.npmjs.com/package/@webext-core/match-patterns).
|
||||
* @module wxt/utils/match-patterns
|
||||
*/
|
||||
export * from '@webext-core/match-patterns';
|
||||
@@ -1,7 +1,7 @@
|
||||
import definition from 'virtual:user-background-entrypoint';
|
||||
import { initPlugins } from 'virtual:wxt-plugins';
|
||||
import { getDevServerWebSocket } from '../sandbox/dev-server-websocket';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
import { getDevServerWebSocket } from '../utils/internal/dev-server-websocket';
|
||||
import { logger } from '../utils/internal/logger';
|
||||
import { browser } from 'wxt/browser';
|
||||
import { keepServiceWorkerAlive } from './utils/keep-service-worker-alive';
|
||||
import { reloadContentScript } from './utils/reload-content-scripts';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import definition from 'virtual:user-content-script-isolated-world-entrypoint';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
import { ContentScriptContext } from 'wxt/client';
|
||||
import { logger } from '../utils/internal/logger';
|
||||
import { ContentScriptContext } from 'wxt/utils/content-script-context';
|
||||
import { initPlugins } from 'virtual:wxt-plugins';
|
||||
|
||||
const result = (async () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import definition from 'virtual:user-content-script-main-world-entrypoint';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
import { logger } from '../utils/internal/logger';
|
||||
import { initPlugins } from 'virtual:wxt-plugins';
|
||||
|
||||
const result = (async () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
import { getDevServerWebSocket } from '../sandbox/dev-server-websocket';
|
||||
import { logger } from '../utils/internal/logger';
|
||||
import { getDevServerWebSocket } from '../utils/internal/dev-server-websocket';
|
||||
|
||||
if (import.meta.env.COMMAND === 'serve') {
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import definition from 'virtual:user-unlisted-script-entrypoint';
|
||||
import { logger } from '../sandbox/utils/logger';
|
||||
import { logger } from '../utils/internal/logger';
|
||||
import { initPlugins } from 'virtual:wxt-plugins';
|
||||
|
||||
const result = (async () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { browser } from 'wxt/browser';
|
||||
import { logger } from '../../sandbox/utils/logger';
|
||||
import { MatchPattern } from 'wxt/sandbox';
|
||||
import type { ReloadContentScriptPayload } from '../../sandbox/dev-server-websocket';
|
||||
import { logger } from '../../utils/internal/logger';
|
||||
import { MatchPattern } from 'wxt/utils/match-patterns';
|
||||
import type { ReloadContentScriptPayload } from '../../utils/internal/dev-server-websocket';
|
||||
|
||||
export function reloadContentScript(payload: ReloadContentScriptPayload) {
|
||||
const manifest = browser.runtime.getManifest();
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
{
|
||||
"entryPoints": [
|
||||
"src/client/index.ts",
|
||||
"src/testing/index.ts",
|
||||
"src/sandbox/index.ts",
|
||||
"src/browser.ts",
|
||||
"src/index.ts",
|
||||
"src/modules.ts",
|
||||
"src/storage.ts"
|
||||
"src/utils/app-config.ts",
|
||||
"src/utils/inject-script.ts",
|
||||
"src/utils/content-script-context.ts",
|
||||
"src/utils/content-script-ui/types.ts",
|
||||
"src/utils/content-script-ui/integrated.ts",
|
||||
"src/utils/content-script-ui/shadow-root.ts",
|
||||
"src/utils/content-script-ui/iframe.ts",
|
||||
"src/utils/define-app-config.ts",
|
||||
"src/utils/define-background.ts",
|
||||
"src/utils/define-content-script.ts",
|
||||
"src/utils/define-unlisted-script.ts",
|
||||
"src/utils/define-wxt-plugin.ts",
|
||||
"src/utils/match-patterns.ts",
|
||||
"src/browser.ts",
|
||||
"src/testing/index.ts",
|
||||
"src/storage.ts",
|
||||
"src/modules.ts"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user