Compare commits

..

25 Commits

Author SHA1 Message Date
GitHub Actions ca5a52c6f1 chore(release): v0.17.12 2024-04-03 19:04:03 +00:00
Aaron 982c69f8ae feat: Add hooks for extending vite config (#599) 2024-04-03 14:00:48 -05:00
Aaron 6fc7d9254a fix(content-script-ui): Properly assign and unassign mounted value (#598) 2024-04-03 12:38:46 -05:00
dependabot[bot] 2e0e104d48 chore(deps): bump c12 from 1.5.1 to 1.10.0 (#592)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 23:23:11 -05:00
dependabot[bot] 02430fd7b8 chore(deps-dev): bump sass from 1.69.5 to 1.72.0 (#591)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 23:23:01 -05:00
dependabot[bot] 2e6d35d193 chore(deps-dev): bump vue from 3.3.10 to 3.4.21 (#589)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 23:08:37 -05:00
dependabot[bot] 7cf412ac1f chore(deps): bump vitest from 1.2.2 to 1.4.0 (#590)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 22:15:44 -05:00
Aaron 9398cbb596 docs: Add discord server link (#593) 2024-04-01 19:13:12 -05:00
dependabot[bot] ca9b96142e chore(deps-dev): bump @aklinker1/check from 1.1.1 to 1.2.0 (#588)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 18:10:28 -05:00
Aaron db57c8e079 chore: Remove unnecssary 'Omit' types 2024-03-31 08:40:21 -05:00
GitHub Actions 7e37e11caf chore(release): v0.17.11 2024-03-31 13:22:25 +00:00
Aaron bb90029c54 fix: Resolve absolute paths from the public directory properly (#583) 2024-03-31 08:19:06 -05:00
Aaron d3b14afbce chore: Extract helper function 2024-03-30 14:49:10 -05:00
Aaron ba2197a609 chore: Add some array utils (#582) 2024-03-30 13:30:45 -05:00
Aaron 4c558d3eb6 chore: Simplify virtual module setup (#581) 2024-03-30 12:44:27 -05:00
Qiwei Yang dcd175444a docs: Add "GitHub Custom Notifier" to homepage (#580) 2024-03-30 08:37:26 -05:00
Aaron 16fc58404a docs: Fix zip.includeSources example 2024-03-30 08:37:00 -05:00
GitHub Actions 28c7e7d9ed chore(release): v0.17.10 2024-03-29 05:52:30 +00:00
Zizheng Tai 5a3b42a4b0 feat: Add dev.server.port config (#577)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-03-29 00:49:36 -05:00
Aaron c9c5d721ec chore: Refactor order of config resolution (#578) 2024-03-29 00:21:09 -05:00
Aaron 1556b9ad73 chore: Use @aklinker1/check to simplify checks setup (#550) 2024-03-25 15:15:40 -05:00
GitHub Actions ca15b1f321 chore(release): v0.17.9 2024-03-25 06:13:23 +00:00
Aaron 448436cb08 chore: Merge user config using defu (#568) 2024-03-25 01:09:52 -05:00
Aaron c9ddc3d0f2 fix: Don't override wxt.config.ts options when CLI flags are not passed (#567) 2024-03-25 00:24:56 -05:00
Guillaume 6b72f883b6 feat: Add {{mode}} Template Variable (#566)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-03-25 00:01:59 -05:00
54 changed files with 850 additions and 560 deletions
+2 -14
View File
@@ -7,24 +7,12 @@ on:
- main
jobs:
formatting:
checks:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm format:check
lint:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm lint
type-check:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm compile
- run: pnpm check
validate-demo:
runs-on: ubuntu-22.04
steps:
+83
View File
@@ -1,5 +1,88 @@
# Changelog
## v0.17.12
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.17.11...v0.17.12)
### 🚀 Enhancements
- Add hooks for extending vite config ([#599](https://github.com/wxt-dev/wxt/pull/599))
### 🩹 Fixes
- **content-script-ui:** Properly assign and unassign mounted value ([#598](https://github.com/wxt-dev/wxt/pull/598))
### 📖 Documentation
- Add discord server link ([#593](https://github.com/wxt-dev/wxt/pull/593))
### 🏡 Chore
- Remove unnecssary 'Omit' types ([db57c8e](https://github.com/wxt-dev/wxt/commit/db57c8e))
- **deps-dev:** Bump @aklinker1/check from 1.1.1 to 1.2.0 ([#588](https://github.com/wxt-dev/wxt/pull/588))
- **deps-dev:** Bump vue from 3.3.10 to 3.4.21 ([#589](https://github.com/wxt-dev/wxt/pull/589))
- **deps-dev:** Bump sass from 1.69.5 to 1.72.0 ([#591](https://github.com/wxt-dev/wxt/pull/591))
## v0.17.11
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.17.10...v0.17.11)
### 🩹 Fixes
- Resolve absolute paths from the public directory properly ([#583](https://github.com/wxt-dev/wxt/pull/583))
### 📖 Documentation
- Fix `zip.includeSources` example ([16fc584](https://github.com/wxt-dev/wxt/commit/16fc584))
- Add "GitHub Custom Notifier" to homepage ([#580](https://github.com/wxt-dev/wxt/pull/580))
### 🏡 Chore
- Simplify virtual module setup ([#581](https://github.com/wxt-dev/wxt/pull/581))
- Add some array utils ([#582](https://github.com/wxt-dev/wxt/pull/582))
- Extract helper function ([d3b14af](https://github.com/wxt-dev/wxt/commit/d3b14af))
### ❤️ Contributors
- Qiwei Yang ([@qiweiii](http://github.com/qiweiii))
## v0.17.10
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.17.9...v0.17.10)
### 🚀 Enhancements
- Add `dev.server.port` config ([#577](https://github.com/wxt-dev/wxt/pull/577))
### 🏡 Chore
- Use `@aklinker1/check` to simplify checks setup ([#550](https://github.com/wxt-dev/wxt/pull/550))
- Refactor order of config resolution ([#578](https://github.com/wxt-dev/wxt/pull/578))
### ❤️ Contributors
- Zizheng Tai ([@zizhengtai](http://github.com/zizhengtai))
## v0.17.9
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.17.8...v0.17.9)
### 🚀 Enhancements
- Add `{{mode}}` Template Variable ([#566](https://github.com/wxt-dev/wxt/pull/566))
### 🩹 Fixes
- Don't override `wxt.config.ts` options when CLI flags are not passed ([#567](https://github.com/wxt-dev/wxt/pull/567))
### 🏡 Chore
- Merge user config using `defu` ([#568](https://github.com/wxt-dev/wxt/pull/568))
### ❤️ Contributors
- Guillaume ([@GuiEpi](http://github.com/GuiEpi))
## v0.17.8
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.17.7...v0.17.8)
+2
View File
@@ -29,6 +29,8 @@
<a href="https://wxt.dev/api/config.html" target="_blank">Configuration</a>
&bull;
<a href="https://wxt.dev/examples.html" target="_blank">Examples</a>
&bull;
<a href="https://discord.gg/ZFsZqGery9" target="_blank">Discord</a>
</p>
![Example CLI Output](./docs/assets/cli-output.png)
+1 -1
View File
@@ -1,4 +1,4 @@
import messages from 'public/_locales/en/messages.json';
import messages from '~/public/_locales/en/messages.json';
export default defineBackground({
// type: 'module',
+3 -3
View File
@@ -12,10 +12,10 @@ export default defineConfig({
},
],
},
alias: {
public: 'src/public',
},
zip: {
downloadPackages: ['sass'],
},
analysis: {
open: true,
},
});
@@ -21,6 +21,7 @@ const chromeExtensionIds = [
'aiakblgmlabokilgljkglggnpflljdgp', // Markdown Sticky Notes
'nomnkbngkijpffepcgbbofhcnafpkiep', // DocVersionRedirector
'ceicccfeikoipigeghddpocceifjelph', // Plex Skipper
'aelkipgppclpfimeamgmlonimflbhlgf', // GitHub Custom Notifier
];
const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds);
+4 -1
View File
@@ -146,6 +146,9 @@ export default defineConfig({
],
},
socialLinks: [{ icon: 'github', link: 'https://github.com/wxt-dev/wxt' }],
socialLinks: [
{ icon: 'discord', link: 'https://discord.gg/ZFsZqGery9' },
{ icon: 'github', link: 'https://github.com/wxt-dev/wxt' },
],
},
});
+16 -3
View File
@@ -9,16 +9,21 @@ const hooks: WxtHooks = {
'build:manifestGenerated': vi.fn(),
'entrypoints:resolved': vi.fn(),
'entrypoints:grouped': vi.fn(),
'vite:build:extendConfig': vi.fn(),
'vite:devServer:extendConfig': vi.fn(),
};
function expectHooksToBeCalled(called: Record<keyof WxtHooks, boolean>) {
function expectHooksToBeCalled(
called: Record<keyof WxtHooks, boolean | number>,
) {
Object.keys(hooks).forEach((key) => {
const hookName = key as keyof WxtHooks;
const times = called[hookName] ? 1 : 0;
const value = called[hookName];
const times = typeof value === 'number' ? value : value ? 1 : 0;
expect(
hooks[hookName],
`Expected "${hookName}" to be called ${times} time(s)`,
).toBeCalledTimes(called[hookName] ? 1 : 0);
).toBeCalledTimes(times);
});
}
@@ -40,6 +45,8 @@ describe('Hooks', () => {
'build:manifestGenerated': false,
'entrypoints:grouped': false,
'entrypoints:resolved': true,
'vite:build:extendConfig': false,
'vite:devServer:extendConfig': false,
});
});
@@ -56,6 +63,8 @@ describe('Hooks', () => {
'build:manifestGenerated': true,
'entrypoints:grouped': true,
'entrypoints:resolved': true,
'vite:build:extendConfig': 1,
'vite:devServer:extendConfig': false,
});
});
@@ -72,6 +81,8 @@ describe('Hooks', () => {
'build:manifestGenerated': true,
'entrypoints:grouped': true,
'entrypoints:resolved': true,
'vite:build:extendConfig': 1,
'vite:devServer:extendConfig': false,
});
});
@@ -94,6 +105,8 @@ describe('Hooks', () => {
'build:manifestGenerated': true,
'entrypoints:grouped': true,
'entrypoints:resolved': true,
'vite:build:extendConfig': 2,
'vite:devServer:extendConfig': 1,
});
});
});
+25
View File
@@ -71,4 +71,29 @@ describe('Zipping', () => {
}"
`);
});
it('should correctly apply template variables for zip file names based on provided config', async () => {
const project = new TestProject({
name: 'test',
version: '1.0.0',
});
project.addFile(
'entrypoints/background.ts',
'export default defineBackground(() => {});',
);
const artifactZip = '.output/test-1.0.0-firefox-development.zip';
const sourcesZip = '.output/test-1.0.0-development-sources.zip';
await project.zip({
browser: 'firefox',
mode: 'development',
zip: {
artifactTemplate: '{{name}}-{{version}}-{{browser}}-{{mode}}.zip',
sourcesTemplate: '{{name}}-{{version}}-{{mode}}-sources.zip',
},
});
expect(await project.fileExists(artifactZip)).toBe(true);
expect(await project.fileExists(sourcesZip)).toBe(true);
});
});
+5 -9
View File
@@ -1,7 +1,7 @@
{
"name": "wxt",
"type": "module",
"version": "0.17.8",
"version": "0.17.12",
"description": "Next gen framework for developing web extensions",
"engines": {
"node": ">=18",
@@ -87,14 +87,9 @@
"scripts": {
"wxt": "tsx src/cli/index.ts",
"build": "tsx scripts/build.ts",
"format": "prettier --write .",
"format:check": "prettier --check .",
"lint": "run-p -c -s lint:*",
"lint:eslint": "echo 'ESLint: TODO'",
"lint:package": "publint",
"compile": "run-s -c compile:*",
"compile:wxt": "tsc --noEmit",
"compile:virtual": "tsc --noEmit -p src/virtual",
"check": "run-s -c check:*",
"check:default": "check",
"check:tsc-virtual": "tsc --noEmit -p src/virtual",
"test": "vitest",
"test:coverage": "vitest run --coverage.enabled \"--coverage.include=src/**\" \"--coverage.exclude=src/core/utils/testing/**\" \"--coverage.exclude=**/*.d.ts\"",
"prepare": "simple-git-hooks",
@@ -146,6 +141,7 @@
"webextension-polyfill": "^0.10.0"
},
"devDependencies": {
"@aklinker1/check": "^1.1.1",
"@faker-js/faker": "^8.3.1",
"@types/fs-extra": "^11.0.4",
"@types/lodash.merge": "^4.6.9",
+160 -199
View File
@@ -28,7 +28,7 @@ importers:
version: 0.4.0
c12:
specifier: ^1.5.1
version: 1.5.1
version: 1.10.0
cac:
specifier: ^6.7.14
version: 6.7.14
@@ -123,6 +123,9 @@ importers:
specifier: ^0.10.0
version: 0.10.0
devDependencies:
'@aklinker1/check':
specifier: ^1.1.1
version: 1.2.0(typescript@5.3.3)
'@faker-js/faker':
specifier: ^8.3.1
version: 8.3.1
@@ -209,7 +212,7 @@ importers:
version: 1.0.2(vite@5.1.3)
vue:
specifier: ^3.3.10
version: 3.3.10(typescript@5.3.3)
version: 3.4.21(typescript@5.3.3)
demo:
dependencies:
@@ -238,6 +241,18 @@ importers:
packages:
/@aklinker1/check@1.2.0(typescript@5.3.3):
resolution: {integrity: sha512-8GEoPcifx5f7Yx2t1KCGEQyrLOOb2ErP3cG+H1+TwWBYjkT2HV9ZHCLYy0Ws8CET8VeUcKDvLKmn2DW3HBt+FA==}
hasBin: true
peerDependencies:
typescript: ^5.0.0
dependencies:
'@antfu/utils': 0.7.7
ci-info: 4.0.0
citty: 0.1.6
typescript: 5.3.3
dev: true
/@aklinker1/rollup-plugin-visualizer@5.12.0:
resolution: {integrity: sha512-X24LvEGw6UFmy0lpGJDmXsMyBD58XmX1bbwsaMLhNoM+UMQfQ3b2RtC+nz4b/NoRK5r6QJSKJHBNVeUdwqybaQ==}
engines: {node: '>=14'}
@@ -402,6 +417,10 @@ packages:
'@jridgewell/trace-mapping': 0.3.18
dev: true
/@antfu/utils@0.7.7:
resolution: {integrity: sha512-gFPqTG7otEJ8uP6wrhDv6mqwGWYZKNvAcCq6u9hOj0c+IKCEsY4L1oC9trPq2SaWIzAfHvqfBDxF591JkMf+kg==}
dev: true
/@babel/code-frame@7.22.5:
resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==}
engines: {node: '>=6.9.0'}
@@ -427,8 +446,8 @@ packages:
js-tokens: 4.0.0
dev: false
/@babel/parser@7.23.6:
resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==}
/@babel/parser@7.24.1:
resolution: {integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==}
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
@@ -1202,7 +1221,7 @@ packages:
'@types/node': 20.10.3
optional: true
/@vitejs/plugin-vue@5.0.2(vite@5.1.3)(vue@3.4.3):
/@vitejs/plugin-vue@5.0.2(vite@5.1.3)(vue@3.4.21):
resolution: {integrity: sha512-kEjJHrLb5ePBvjD0SPZwJlw1QTRcjjCA9sB5VyfonoXVBxTS7TMnqL6EkLt1Eu61RDeiuZ/WN9Hf6PxXhPI2uA==}
engines: {node: ^18.0.0 || >=20.0.0}
peerDependencies:
@@ -1210,7 +1229,7 @@ packages:
vue: ^3.2.25
dependencies:
vite: 5.1.3(@types/node@20.10.3)(sass@1.69.5)
vue: 3.4.3(typescript@5.3.3)
vue: 3.4.21(typescript@5.3.3)
dev: true
/@vitest/coverage-v8@1.2.2(vitest@1.2.2):
@@ -1248,13 +1267,13 @@ packages:
dependencies:
'@vitest/utils': 1.2.2
p-limit: 5.0.0
pathe: 1.1.1
pathe: 1.1.2
/@vitest/snapshot@1.2.2:
resolution: {integrity: sha512-SmGY4saEw1+bwE1th6S/cZmPxz/Q4JWsl7LvbQIky2tKE35US4gd0Mjzqfr84/4OD0tikGWaWdMja/nWL5NIPA==}
dependencies:
magic-string: 0.30.5
pathe: 1.1.1
magic-string: 0.30.8
pathe: 1.1.2
pretty-format: 29.7.0
/@vitest/spy@1.2.2:
@@ -1270,179 +1289,96 @@ packages:
loupe: 2.3.7
pretty-format: 29.7.0
/@vue/compiler-core@3.3.10:
resolution: {integrity: sha512-doe0hODR1+i1menPkRzJ5MNR6G+9uiZHIknK3Zn5OcIztu6GGw7u0XUzf3AgB8h/dfsZC9eouzoLo3c3+N/cVA==}
/@vue/compiler-core@3.4.21:
resolution: {integrity: sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==}
dependencies:
'@babel/parser': 7.23.6
'@vue/shared': 3.3.10
estree-walker: 2.0.2
source-map-js: 1.0.2
dev: true
/@vue/compiler-core@3.4.3:
resolution: {integrity: sha512-u8jzgFg0EDtSrb/hG53Wwh1bAOQFtc1ZCegBpA/glyvTlgHl+tq13o1zvRfLbegYUw/E4mSTGOiCnAJ9SJ+lsg==}
dependencies:
'@babel/parser': 7.23.6
'@vue/shared': 3.4.3
'@babel/parser': 7.24.1
'@vue/shared': 3.4.21
entities: 4.5.0
estree-walker: 2.0.2
source-map-js: 1.0.2
dev: true
/@vue/compiler-dom@3.3.10:
resolution: {integrity: sha512-NCrqF5fm10GXZIK0GrEAauBqdy+F2LZRt3yNHzrYjpYBuRssQbuPLtSnSNjyR9luHKkWSH8we5LMB3g+4z2HvA==}
/@vue/compiler-dom@3.4.21:
resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==}
dependencies:
'@vue/compiler-core': 3.3.10
'@vue/shared': 3.3.10
'@vue/compiler-core': 3.4.21
'@vue/shared': 3.4.21
dev: true
/@vue/compiler-dom@3.4.3:
resolution: {integrity: sha512-oGF1E9/htI6JWj/lTJgr6UgxNCtNHbM6xKVreBWeZL9QhRGABRVoWGAzxmtBfSOd+w0Zi5BY0Es/tlJrN6WgEg==}
/@vue/compiler-sfc@3.4.21:
resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==}
dependencies:
'@vue/compiler-core': 3.4.3
'@vue/shared': 3.4.3
dev: true
/@vue/compiler-sfc@3.3.10:
resolution: {integrity: sha512-xpcTe7Rw7QefOTRFFTlcfzozccvjM40dT45JtrE3onGm/jBLZ0JhpKu3jkV7rbDFLeeagR/5RlJ2Y9SvyS0lAg==}
dependencies:
'@babel/parser': 7.23.6
'@vue/compiler-core': 3.3.10
'@vue/compiler-dom': 3.3.10
'@vue/compiler-ssr': 3.3.10
'@vue/reactivity-transform': 3.3.10
'@vue/shared': 3.3.10
'@babel/parser': 7.24.1
'@vue/compiler-core': 3.4.21
'@vue/compiler-dom': 3.4.21
'@vue/compiler-ssr': 3.4.21
'@vue/shared': 3.4.21
estree-walker: 2.0.2
magic-string: 0.30.5
postcss: 8.4.32
source-map-js: 1.0.2
dev: true
/@vue/compiler-sfc@3.4.3:
resolution: {integrity: sha512-NuJqb5is9I4uzv316VRUDYgIlPZCG8D+ARt5P4t5UDShIHKL25J3TGZAUryY/Aiy0DsY7srJnZL5ryB6DD63Zw==}
dependencies:
'@babel/parser': 7.23.6
'@vue/compiler-core': 3.4.3
'@vue/compiler-dom': 3.4.3
'@vue/compiler-ssr': 3.4.3
'@vue/shared': 3.4.3
estree-walker: 2.0.2
magic-string: 0.30.5
magic-string: 0.30.8
postcss: 8.4.35
source-map-js: 1.0.2
dev: true
/@vue/compiler-ssr@3.3.10:
resolution: {integrity: sha512-12iM4jA4GEbskwXMmPcskK5wImc2ohKm408+o9iox3tfN9qua8xL0THIZtoe9OJHnXP4eOWZpgCAAThEveNlqQ==}
/@vue/compiler-ssr@3.4.21:
resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==}
dependencies:
'@vue/compiler-dom': 3.3.10
'@vue/shared': 3.3.10
dev: true
/@vue/compiler-ssr@3.4.3:
resolution: {integrity: sha512-wnYQtMBkeFSxgSSQbYGQeXPhQacQiog2c6AlvMldQH6DB+gSXK/0F6DVXAJfEiuBSgBhUc8dwrrG5JQcqwalsA==}
dependencies:
'@vue/compiler-dom': 3.4.3
'@vue/shared': 3.4.3
'@vue/compiler-dom': 3.4.21
'@vue/shared': 3.4.21
dev: true
/@vue/devtools-api@6.5.1:
resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==}
dev: true
/@vue/reactivity-transform@3.3.10:
resolution: {integrity: sha512-0xBdk+CKHWT+Gev8oZ63Tc0qFfj935YZx+UAynlutnrDZ4diFCVFMWixn65HzjE3S1iJppWOo6Tt1OzASH7VEg==}
/@vue/reactivity@3.4.21:
resolution: {integrity: sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==}
dependencies:
'@babel/parser': 7.23.6
'@vue/compiler-core': 3.3.10
'@vue/shared': 3.3.10
estree-walker: 2.0.2
magic-string: 0.30.5
'@vue/shared': 3.4.21
dev: true
/@vue/reactivity@3.3.10:
resolution: {integrity: sha512-H5Z7rOY/JLO+e5a6/FEXaQ1TMuOvY4LDVgT+/+HKubEAgs9qeeZ+NhADSeEtrNQeiKLDuzeKc8v0CUFpB6Pqgw==}
/@vue/runtime-core@3.4.21:
resolution: {integrity: sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==}
dependencies:
'@vue/shared': 3.3.10
'@vue/reactivity': 3.4.21
'@vue/shared': 3.4.21
dev: true
/@vue/reactivity@3.4.3:
resolution: {integrity: sha512-q5f9HLDU+5aBKizXHAx0w4whkIANs1Muiq9R5YXm0HtorSlflqv9u/ohaMxuuhHWCji4xqpQ1eL04WvmAmGnFg==}
/@vue/runtime-dom@3.4.21:
resolution: {integrity: sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==}
dependencies:
'@vue/shared': 3.4.3
dev: true
/@vue/runtime-core@3.3.10:
resolution: {integrity: sha512-DZ0v31oTN4YHX9JEU5VW1LoIVgFovWgIVb30bWn9DG9a7oA415idcwsRNNajqTx8HQJyOaWfRKoyuP2P2TYIag==}
dependencies:
'@vue/reactivity': 3.3.10
'@vue/shared': 3.3.10
dev: true
/@vue/runtime-core@3.4.3:
resolution: {integrity: sha512-C1r6QhB1qY7D591RCSFhMULyzL9CuyrGc+3PpB0h7dU4Qqw6GNyo4BNFjHZVvsWncrUlKX3DIKg0Y7rNNr06NQ==}
dependencies:
'@vue/reactivity': 3.4.3
'@vue/shared': 3.4.3
dev: true
/@vue/runtime-dom@3.3.10:
resolution: {integrity: sha512-c/jKb3ny05KJcYk0j1m7Wbhrxq7mZYr06GhKykDMNRRR9S+/dGT8KpHuNQjv3/8U4JshfkAk6TpecPD3B21Ijw==}
dependencies:
'@vue/runtime-core': 3.3.10
'@vue/shared': 3.3.10
'@vue/runtime-core': 3.4.21
'@vue/shared': 3.4.21
csstype: 3.1.3
dev: true
/@vue/runtime-dom@3.4.3:
resolution: {integrity: sha512-wrsprg7An5Ec+EhPngWdPuzkp0BEUxAKaQtN9dPU/iZctPyD9aaXmVtehPJerdQxQale6gEnhpnfywNw3zOv2A==}
dependencies:
'@vue/runtime-core': 3.4.3
'@vue/shared': 3.4.3
csstype: 3.1.3
dev: true
/@vue/server-renderer@3.3.10(vue@3.3.10):
resolution: {integrity: sha512-0i6ww3sBV3SKlF3YTjSVqKQ74xialMbjVYGy7cOTi7Imd8ediE7t72SK3qnvhrTAhOvlQhq6Bk6nFPdXxe0sAg==}
/@vue/server-renderer@3.4.21(vue@3.4.21):
resolution: {integrity: sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==}
peerDependencies:
vue: 3.3.10
vue: 3.4.21
dependencies:
'@vue/compiler-ssr': 3.3.10
'@vue/shared': 3.3.10
vue: 3.3.10(typescript@5.3.3)
'@vue/compiler-ssr': 3.4.21
'@vue/shared': 3.4.21
vue: 3.4.21(typescript@5.3.3)
dev: true
/@vue/server-renderer@3.4.3(vue@3.4.3):
resolution: {integrity: sha512-BUxt8oVGMKKsqSkM1uU3d3Houyfy4WAc2SpSQRebNd+XJGATVkW/rO129jkyL+kpB/2VRKzE63zwf5RtJ3XuZw==}
peerDependencies:
vue: 3.4.3
dependencies:
'@vue/compiler-ssr': 3.4.3
'@vue/shared': 3.4.3
vue: 3.4.3(typescript@5.3.3)
/@vue/shared@3.4.21:
resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==}
dev: true
/@vue/shared@3.3.10:
resolution: {integrity: sha512-2y3Y2J1a3RhFa0WisHvACJR2ncvWiVHcP8t0Inxo+NKz+8RKO4ZV8eZgCxRgQoA6ITfV12L4E6POOL9HOU5nqw==}
dev: true
/@vue/shared@3.4.3:
resolution: {integrity: sha512-rIwlkkP1n4uKrRzivAKPZIEkHiuwY5mmhMJ2nZKCBLz8lTUlE73rQh4n1OnnMurXt1vcUNyH4ZPfdh8QweTjpQ==}
dev: true
/@vueuse/core@10.7.1(vue@3.4.3):
/@vueuse/core@10.7.1(vue@3.4.21):
resolution: {integrity: sha512-74mWHlaesJSWGp1ihg76vAnfVq9NTv1YT0SYhAQ6zwFNdBkkP+CKKJmVOEHcdSnLXCXYiL5e7MaewblfiYLP7g==}
dependencies:
'@types/web-bluetooth': 0.0.20
'@vueuse/metadata': 10.7.1
'@vueuse/shared': 10.7.1(vue@3.4.3)
vue-demi: 0.14.6(vue@3.4.3)
'@vueuse/shared': 10.7.1(vue@3.4.21)
vue-demi: 0.14.6(vue@3.4.21)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
dev: true
/@vueuse/integrations@10.7.1(focus-trap@7.5.4)(vue@3.4.3):
/@vueuse/integrations@10.7.1(focus-trap@7.5.4)(vue@3.4.21):
resolution: {integrity: sha512-cKo5LEeKVHdBRBtMTOrDPdR0YNtrmN9IBfdcnY2P3m5LHVrsD0xiHUtAH1WKjHQRIErZG6rJUa6GA4tWZt89Og==}
peerDependencies:
async-validator: '*'
@@ -1483,10 +1419,10 @@ packages:
universal-cookie:
optional: true
dependencies:
'@vueuse/core': 10.7.1(vue@3.4.3)
'@vueuse/shared': 10.7.1(vue@3.4.3)
'@vueuse/core': 10.7.1(vue@3.4.21)
'@vueuse/shared': 10.7.1(vue@3.4.21)
focus-trap: 7.5.4
vue-demi: 0.14.6(vue@3.4.3)
vue-demi: 0.14.6(vue@3.4.21)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
@@ -1496,10 +1432,10 @@ packages:
resolution: {integrity: sha512-jX8MbX5UX067DYVsbtrmKn6eG6KMcXxLRLlurGkZku5ZYT3vxgBjui2zajvUZ18QLIjrgBkFRsu7CqTAg18QFw==}
dev: true
/@vueuse/shared@10.7.1(vue@3.4.3):
/@vueuse/shared@10.7.1(vue@3.4.21):
resolution: {integrity: sha512-v0jbRR31LSgRY/C5i5X279A/WQjD6/JsMzGa+eqt658oJ75IvQXAeONmwvEMrvJQKnRElq/frzBR7fhmWY5uLw==}
dependencies:
vue-demi: 0.14.6(vue@3.4.3)
vue-demi: 0.14.6(vue@3.4.21)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
@@ -1523,8 +1459,8 @@ packages:
resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==}
engines: {node: '>=0.4.0'}
/acorn@8.11.2:
resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==}
/acorn@8.11.3:
resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
engines: {node: '>=0.4.0'}
hasBin: true
@@ -1781,22 +1717,21 @@ packages:
safe-json-stringify: 1.2.0
dev: false
/c12@1.5.1:
resolution: {integrity: sha512-BWZRJgDEveT8uI+cliCwvYSSSSvb4xKoiiu5S0jaDbKBopQLQF7E+bq9xKk1pTcG+mUa3yXuFO7bD9d8Lr9Xxg==}
/c12@1.10.0:
resolution: {integrity: sha512-0SsG7UDhoRWcuSvKWHaXmu5uNjDCDN3nkQLRL4Q42IlFy+ze58FcCoI3uPwINXinkz7ZinbhEgyzYFw9u9ZV8g==}
dependencies:
chokidar: 3.6.0
confbox: 0.1.3
defu: 6.1.4
dotenv: 16.3.1
giget: 1.1.3
dotenv: 16.4.5
giget: 1.2.3
jiti: 1.21.0
mlly: 1.4.2
mlly: 1.6.1
ohash: 1.1.3
pathe: 1.1.1
pathe: 1.1.2
perfect-debounce: 1.0.0
pkg-types: 1.0.3
rc9: 2.1.1
transitivePeerDependencies:
- supports-color
dev: false
/cac@6.7.14:
@@ -1910,13 +1845,11 @@ packages:
/ci-info@4.0.0:
resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==}
engines: {node: '>=8'}
dev: false
/citty@0.1.6:
resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
dependencies:
consola: 3.2.3
dev: false
/cli-boxes@3.0.0:
resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
@@ -2033,6 +1966,10 @@ packages:
typedarray: 0.0.6
dev: false
/confbox@0.1.3:
resolution: {integrity: sha512-eH3ZxAihl1PhKfpr4VfEN6/vUd87fmgb6JkldHgg/YR6aEBhW63qUDgzP2Y6WM0UumdsYp5H3kibalXAdHfbgg==}
dev: false
/config-chain@1.1.13:
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
dependencies:
@@ -2054,7 +1991,6 @@ packages:
/consola@3.2.3:
resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==}
engines: {node: ^14.18.0 || >=16.10.0}
dev: false
/convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
@@ -2284,6 +2220,11 @@ packages:
engines: {node: '>=12'}
dev: false
/dotenv@16.4.5:
resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
engines: {node: '>=12'}
dev: false
/dtrace-provider@0.8.8:
resolution: {integrity: sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==}
engines: {node: '>=0.10'}
@@ -2747,6 +2688,20 @@ packages:
- supports-color
dev: false
/giget@1.2.3:
resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==}
hasBin: true
dependencies:
citty: 0.1.6
consola: 3.2.3
defu: 6.1.4
node-fetch-native: 1.6.4
nypm: 0.3.8
ohash: 1.1.3
pathe: 1.1.2
tar: 6.2.0
dev: false
/glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -3513,7 +3468,7 @@ packages:
resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
engines: {node: '>=14'}
dependencies:
mlly: 1.4.2
mlly: 1.6.1
pkg-types: 1.0.3
/lodash.camelcase@4.3.0:
@@ -3586,10 +3541,16 @@ packages:
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
/magic-string@0.30.8:
resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==}
engines: {node: '>=12'}
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
/magicast@0.3.3:
resolution: {integrity: sha512-ZbrP1Qxnpoes8sz47AM0z08U+jW6TyRgZzcWy3Ma3vDhJttwMwAFDMMQFobwdBxByBD46JYmxRzeF7w2+wJEuw==}
dependencies:
'@babel/parser': 7.23.6
'@babel/parser': 7.24.1
'@babel/types': 7.23.9
source-map-js: 1.0.2
dev: true
@@ -3720,7 +3681,16 @@ packages:
/mlly@1.4.2:
resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==}
dependencies:
acorn: 8.11.2
acorn: 8.11.3
pathe: 1.1.2
pkg-types: 1.0.3
ufo: 1.4.0
dev: false
/mlly@1.6.1:
resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==}
dependencies:
acorn: 8.11.3
pathe: 1.1.2
pkg-types: 1.0.3
ufo: 1.4.0
@@ -3805,6 +3775,10 @@ packages:
resolution: {integrity: sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w==}
dev: false
/node-fetch-native@1.6.4:
resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==}
dev: false
/node-forge@1.3.1:
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
engines: {node: '>= 6.13.0'}
@@ -3907,6 +3881,18 @@ packages:
ufo: 1.4.0
dev: false
/nypm@0.3.8:
resolution: {integrity: sha512-IGWlC6So2xv6V4cIDmoV0SwwWx7zLG086gyqkyumteH2fIgCAM4nDVFB2iDRszDvmdSVW9xb1N+2KjQ6C7d4og==}
engines: {node: ^14.16.0 || >=16.10.0}
hasBin: true
dependencies:
citty: 0.1.6
consola: 3.2.3
execa: 8.0.1
pathe: 1.1.2
ufo: 1.4.0
dev: false
/object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
@@ -3934,7 +3920,7 @@ packages:
resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==}
dependencies:
destr: 2.0.2
node-fetch-native: 1.4.1
node-fetch-native: 1.6.4
ufo: 1.4.0
dev: false
@@ -4168,7 +4154,7 @@ packages:
resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==}
dependencies:
jsonc-parser: 3.2.0
mlly: 1.4.2
mlly: 1.6.1
pathe: 1.1.2
/postcss-load-config@4.0.1:
@@ -4187,15 +4173,6 @@ packages:
yaml: 2.3.4
dev: true
/postcss@8.4.32:
resolution: {integrity: sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==}
engines: {node: ^10 || ^12 || >=14}
dependencies:
nanoid: 3.3.7
picocolors: 1.0.0
source-map-js: 1.0.2
dev: true
/postcss@8.4.35:
resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==}
engines: {node: ^10 || ^12 || >=14}
@@ -4891,7 +4868,7 @@ packages:
/strip-literal@1.3.0:
resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==}
dependencies:
acorn: 8.11.2
acorn: 8.11.3
/sucrase@3.32.0:
resolution: {integrity: sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==}
@@ -5204,7 +5181,7 @@ packages:
/unplugin@1.5.0:
resolution: {integrity: sha512-9ZdRwbh/4gcm1JTOkp9lAkIDrtOyOxgHmY7cjuwI8L/2RTikMcVG25GsZwNAgRuap3iDw2jeq7eoqtAsz5rW3A==}
dependencies:
acorn: 8.11.2
acorn: 8.11.3
chokidar: 3.6.0
webpack-sources: 3.2.3
webpack-virtual-modules: 0.5.0
@@ -5267,7 +5244,7 @@ packages:
dependencies:
cac: 6.7.14
debug: 4.3.4
pathe: 1.1.1
pathe: 1.1.2
picocolors: 1.0.0
vite: 5.1.3(@types/node@20.10.3)(sass@1.69.5)
transitivePeerDependencies:
@@ -5331,10 +5308,10 @@ packages:
'@docsearch/css': 3.5.2
'@docsearch/js': 3.5.2
'@types/markdown-it': 13.0.7
'@vitejs/plugin-vue': 5.0.2(vite@5.1.3)(vue@3.4.3)
'@vitejs/plugin-vue': 5.0.2(vite@5.1.3)(vue@3.4.21)
'@vue/devtools-api': 6.5.1
'@vueuse/core': 10.7.1(vue@3.4.3)
'@vueuse/integrations': 10.7.1(focus-trap@7.5.4)(vue@3.4.3)
'@vueuse/core': 10.7.1(vue@3.4.21)
'@vueuse/integrations': 10.7.1(focus-trap@7.5.4)(vue@3.4.21)
focus-trap: 7.5.4
mark.js: 8.11.1
minisearch: 6.3.0
@@ -5343,7 +5320,7 @@ packages:
shikiji-core: 0.9.16
shikiji-transformers: 0.9.16
vite: 5.1.3(@types/node@20.10.3)(sass@1.69.5)
vue: 3.4.3(typescript@5.3.3)
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- '@algolia/client-search'
- '@types/node'
@@ -5456,7 +5433,7 @@ packages:
resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==}
dev: true
/vue-demi@0.14.6(vue@3.4.3):
/vue-demi@0.14.6(vue@3.4.21):
resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
engines: {node: '>=12'}
hasBin: true
@@ -5468,38 +5445,22 @@ packages:
'@vue/composition-api':
optional: true
dependencies:
vue: 3.4.3(typescript@5.3.3)
vue: 3.4.21(typescript@5.3.3)
dev: true
/vue@3.3.10(typescript@5.3.3):
resolution: {integrity: sha512-zg6SIXZdTBwiqCw/1p+m04VyHjLfwtjwz8N57sPaBhEex31ND0RYECVOC1YrRwMRmxFf5T1dabl6SGUbMKKuVw==}
/vue@3.4.21(typescript@5.3.3):
resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@vue/compiler-dom': 3.3.10
'@vue/compiler-sfc': 3.3.10
'@vue/runtime-dom': 3.3.10
'@vue/server-renderer': 3.3.10(vue@3.3.10)
'@vue/shared': 3.3.10
typescript: 5.3.3
dev: true
/vue@3.4.3(typescript@5.3.3):
resolution: {integrity: sha512-GjN+culMAGv/mUbkIv8zMKItno8npcj5gWlXkSxf1SPTQf8eJ4A+YfHIvQFyL1IfuJcMl3soA7SmN1fRxbf/wA==}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@vue/compiler-dom': 3.4.3
'@vue/compiler-sfc': 3.4.3
'@vue/runtime-dom': 3.4.3
'@vue/server-renderer': 3.4.3(vue@3.4.3)
'@vue/shared': 3.4.3
'@vue/compiler-dom': 3.4.21
'@vue/compiler-sfc': 3.4.21
'@vue/runtime-dom': 3.4.21
'@vue/server-renderer': 3.4.21(vue@3.4.21)
'@vue/shared': 3.4.21
typescript: 5.3.3
dev: true
+12 -17
View File
@@ -8,6 +8,10 @@ import { consola } from 'consola';
import pMap from 'p-map';
import os from 'node:os';
import path from 'node:path';
import {
virtualModuleNames,
virtualEntrypointModuleNames,
} from '~/core/utils/virtual-modules';
const spinnerText = 'Building WXT';
const spinner = ora(spinnerText).start();
@@ -20,12 +24,7 @@ const preset = {
dts: true,
silent: true,
sourcemap: false,
external: [
'virtual:user-unlisted-script',
'virtual:user-content-script-isolated-world',
'virtual:user-content-script-main-world',
'virtual:user-background',
],
external: virtualEntrypointModuleNames.map((name) => `virtual:user-${name}`),
} satisfies tsup.Options;
function spinnerPMap(configs: tsup.Options[]) {
@@ -74,17 +73,13 @@ const config: tsup.Options[] = [
},
{
...preset,
entry: {
'virtual/background-entrypoint': 'src/virtual/background-entrypoint.ts',
'virtual/content-script-isolated-world-entrypoint':
'src/virtual/content-script-isolated-world-entrypoint.ts',
'virtual/content-script-main-world-entrypoint':
'src/virtual/content-script-main-world-entrypoint.ts',
'virtual/mock-browser': 'src/virtual/mock-browser.ts',
'virtual/reload-html': 'src/virtual/reload-html.ts',
'virtual/unlisted-script-entrypoint':
'src/virtual/unlisted-script-entrypoint.ts',
},
entry: virtualModuleNames.reduce<Record<string, string>>(
(acc, moduleName) => {
acc[`virtual/${moduleName}`] = `src/virtual/${moduleName}.ts`;
return acc;
},
{},
),
format: ['esm'],
splitting: false,
dts: false,
+14
View File
@@ -116,6 +116,20 @@ describe('CLI', () => {
});
});
it('should respect passing --port', async () => {
const expectedPort = 3100;
mockArgv('--port', String(expectedPort));
await importCli();
expect(createServerMock).toBeCalledWith({
dev: {
server: {
port: expectedPort,
},
},
});
});
it('should respect passing --debug', async () => {
mockArgv('--debug');
await importCli();
+3 -2
View File
@@ -1,5 +1,6 @@
import { CAC, Command } from 'cac';
import consola, { LogLevels } from 'consola';
import { filterTruthy, toArray } from '~/core/utils/arrays';
import { printHeader } from '~/core/utils/log';
import { formatDuration } from '~/core/utils/time';
import { ValidationError } from '~/core/utils/validation';
@@ -56,8 +57,8 @@ export function getArrayFromFlags<T>(
flags: any,
name: string,
): T[] | undefined {
const array = [flags[name]].flat() as Array<T | undefined>;
const result = array.filter((item) => item != null) as T[];
const array = toArray<T | undefined>(flags[name]);
const result = filterTruthy(array);
return result.length ? result : undefined;
}
+9
View File
@@ -16,6 +16,7 @@ cli
.option('-c, --config <file>', 'use specified config file')
.option('-m, --mode <mode>', 'set env mode')
.option('-b, --browser <browser>', 'specify a browser')
.option('-p, --port <port>', 'specify a port for the dev server')
.option(
'-e, --filter-entrypoint <entrypoint>',
'only build specific entrypoints',
@@ -35,6 +36,14 @@ cli
configFile: flags.config,
debug: flags.debug,
filterEntrypoints: getArrayFromFlags(flags, 'filterEntrypoint'),
dev:
flags.port == null
? undefined
: {
server: {
port: parseInt(flags.port),
},
},
});
await server.start();
return { isOngoing: true };
@@ -404,4 +404,62 @@ describe('Content Script UIs', () => {
});
});
});
describe('mounted value', () => {
describe('integrated', () => {
it('should set the mounted value based on the onMounted return value', () => {
const expected = Symbol();
const ui = createIntegratedUi(new ContentScriptContext('test'), {
position: 'inline',
onMount: () => expected,
});
expect(ui.mounted).toBeUndefined();
ui.mount();
expect(ui.mounted).toBe(expected);
ui.remove();
expect(ui.mounted).toBeUndefined();
});
});
describe('iframe', () => {
it('should set the mounted value based on the onMounted return value', async () => {
const expected = Symbol();
const ui = createIframeUi(new ContentScriptContext('test'), {
page: '',
position: 'inline',
onMount: () => expected,
});
expect(ui.mounted).toBeUndefined();
ui.mount();
expect(ui.mounted).toBe(expected);
ui.remove();
expect(ui.mounted).toBeUndefined();
});
});
describe('shadow-root', () => {
it('should set the mounted value based on the onMounted return value', async () => {
const expected = Symbol();
const ui = await createShadowRootUi(new ContentScriptContext('test'), {
name: 'test',
position: 'inline',
onMount: () => expected,
});
expect(ui.mounted).toBeUndefined();
ui.mount();
expect(ui.mounted).toBe(expected);
ui.remove();
expect(ui.mounted).toBeUndefined();
});
});
});
});
+14 -4
View File
@@ -35,12 +35,15 @@ export function createIntegratedUi<TMounted>(
const remove = () => {
options.onRemove?.(mounted);
wrapper.remove();
mounted = undefined;
};
ctx.onInvalidated(remove);
return {
mounted,
get mounted() {
return mounted;
},
wrapper,
mount,
remove,
@@ -71,12 +74,15 @@ export function createIframeUi<TMounted>(
const remove = () => {
options.onRemove?.(mounted);
wrapper.remove();
mounted = undefined;
};
ctx.onInvalidated(remove);
return {
mounted,
get mounted() {
return mounted;
},
iframe,
wrapper,
mount,
@@ -116,7 +122,7 @@ export async function createShadowRootUi<TMounted>(
});
shadowHost.setAttribute('data-wxt-shadow-root', '');
let mounted: TMounted;
let mounted: TMounted | undefined;
const mount = () => {
// Add shadow root element to DOM
@@ -134,6 +140,8 @@ export async function createShadowRootUi<TMounted>(
// Remove children from uiContainer
while (uiContainer.lastChild)
uiContainer.removeChild(uiContainer.lastChild);
// Clear mounted value
mounted = undefined;
};
ctx.onInvalidated(remove);
@@ -144,7 +152,9 @@ export async function createShadowRootUi<TMounted>(
uiContainer,
mount,
remove,
mounted: mounted!,
get mounted() {
return mounted;
},
};
}
+33 -26
View File
@@ -2,23 +2,28 @@ import type * as vite from 'vite';
import {
BuildStepOutput,
Entrypoint,
InlineConfig,
ResolvedConfig,
UserConfig,
VirtualEntrypointType,
WxtBuilder,
WxtBuilderServer,
WxtDevServer,
WxtHooks,
} from '~/types';
import * as wxtPlugins from './plugins';
import {
getEntrypointBundlePath,
isHtmlEntrypoint,
} from '~/core/utils/entrypoints';
import {
VirtualEntrypointType,
VirtualModuleId,
} from '~/core/utils/virtual-modules';
import { Hookable } from 'hookable';
import { toArray } from '~/core/utils/arrays';
export async function createViteBuilder(
inlineConfig: InlineConfig,
userConfig: UserConfig,
wxtConfig: Omit<ResolvedConfig, 'builder'>,
wxtConfig: ResolvedConfig,
hooks: Hookable<WxtHooks>,
server?: WxtDevServer,
): Promise<WxtBuilder> {
const vite = await import('vite');
@@ -26,14 +31,9 @@ export async function createViteBuilder(
* Returns the base vite config shared by all builds based on the inline and user config.
*/
const getBaseConfig = async () => {
const resolvedInlineConfig =
(await inlineConfig.vite?.(wxtConfig.env)) ?? {};
const resolvedUserConfig = (await userConfig.vite?.(wxtConfig.env)) ?? {};
const config: vite.InlineConfig = vite.mergeConfig(
resolvedUserConfig,
resolvedInlineConfig,
);
const config: vite.InlineConfig = await wxtConfig.vite({
...wxtConfig.env,
});
config.root = wxtConfig.root;
config.configFile = false;
@@ -41,6 +41,8 @@ export async function createViteBuilder(
config.mode = wxtConfig.mode;
config.build ??= {};
config.publicDir = wxtConfig.publicDir;
config.build.copyPublicDir = false;
config.build.outDir = wxtConfig.outDir;
config.build.emptyOutDir = false;
// Disable minification for the dev command
@@ -55,13 +57,10 @@ export async function createViteBuilder(
config.plugins ??= [];
config.plugins.push(
wxtPlugins.download(wxtConfig),
wxtPlugins.devHtmlPrerender(wxtConfig),
wxtPlugins.devHtmlPrerender(wxtConfig, server),
wxtPlugins.unimport(wxtConfig),
wxtPlugins.virtualEntrypoint('background', wxtConfig),
wxtPlugins.virtualEntrypoint('content-script-isolated-world', wxtConfig),
wxtPlugins.virtualEntrypoint('content-script-main-world', wxtConfig),
wxtPlugins.virtualEntrypoint('unlisted-script', wxtConfig),
wxtPlugins.devServerGlobals(wxtConfig),
wxtPlugins.resolveVirtualModules(wxtConfig),
wxtPlugins.devServerGlobals(wxtConfig, server),
wxtPlugins.tsconfigPaths(wxtConfig),
wxtPlugins.noopBackground(),
wxtPlugins.globals(wxtConfig),
@@ -205,6 +204,11 @@ export async function createViteBuilder(
else entryConfig = getLibModeConfig(group);
const buildConfig = vite.mergeConfig(await getBaseConfig(), entryConfig);
await hooks.callHook(
'vite:build:extendConfig',
toArray(group),
buildConfig,
);
const result = await vite.build(buildConfig);
return {
entrypoints: group,
@@ -221,9 +225,9 @@ export async function createViteBuilder(
},
};
const baseConfig = await getBaseConfig();
const viteServer = await vite.createServer(
vite.mergeConfig(baseConfig, serverConfig),
);
const finalConfig = vite.mergeConfig(baseConfig, serverConfig);
await hooks.callHook('vite:devServer:extendConfig', finalConfig);
const viteServer = await vite.createServer(finalConfig);
const server: WxtBuilderServer = {
async listen() {
@@ -277,7 +281,10 @@ function getRollupEntry(entrypoint: Entrypoint): string {
: 'content-script-isolated-world';
break;
}
return virtualEntrypointType
? `virtual:wxt-${virtualEntrypointType}?${entrypoint.inputPath}`
: entrypoint.inputPath;
if (virtualEntrypointType) {
const moduleId: VirtualModuleId = `virtual:wxt-${virtualEntrypointType}-entrypoint`;
return `${moduleId}?${entrypoint.inputPath}`;
}
return entrypoint.inputPath;
}
@@ -5,9 +5,7 @@ import path from 'node:path';
let increment = 0;
export function bundleAnalysis(
config: Omit<ResolvedConfig, 'builder'>,
): vite.Plugin {
export function bundleAnalysis(config: ResolvedConfig): vite.Plugin {
return visualizer({
template: 'raw-data',
filename: path.resolve(
@@ -14,7 +14,7 @@ import { getEntrypointBundlePath } from '~/core/utils/entrypoints';
*/
export function cssEntrypoints(
entrypoint: Entrypoint,
config: Omit<ResolvedConfig, 'builder'>,
config: ResolvedConfig,
): vite.Plugin {
return {
name: 'wxt:css-entrypoint',
@@ -12,7 +12,8 @@ let reactRefreshPreamble = '';
* Pre-renders the HTML entrypoints when building the extension to connect to the dev server.
*/
export function devHtmlPrerender(
config: Omit<ResolvedConfig, 'builder'>,
config: ResolvedConfig,
server: WxtDevServer | undefined,
): vite.PluginOption {
const htmlReloadId = '@wxt/reload-html';
const resolvedHtmlReloadId = resolve(
@@ -38,7 +39,6 @@ export function devHtmlPrerender(
// Convert scripts like src="./main.tsx" -> src="http://localhost:3000/entrypoints/popup/main.tsx"
// before the paths are replaced with their bundled path
transform(code, id) {
const server = config.server;
if (
config.command !== 'serve' ||
server == null ||
@@ -68,7 +68,6 @@ export function devHtmlPrerender(
// Pass the HTML through the dev server to add dev-mode specific code
async transformIndexHtml(html, ctx) {
const server = config.server;
if (config.command !== 'serve' || server == null) return;
const originalUrl = `${server.origin}${ctx.path}`;
@@ -134,7 +133,7 @@ export function devHtmlPrerender(
}
export function pointToDevServer(
config: Omit<ResolvedConfig, 'builder'>,
config: ResolvedConfig,
server: WxtDevServer,
id: string,
document: Document,
@@ -1,22 +1,23 @@
import { Plugin } from 'vite';
import { ResolvedConfig } from '~/types';
import { ResolvedConfig, WxtDevServer } from '~/types';
/**
* Defines global constants about the dev server. Helps scripts connect to the server's web socket.
*/
export function devServerGlobals(
config: Omit<ResolvedConfig, 'builder'>,
config: ResolvedConfig,
server: WxtDevServer | undefined,
): Plugin {
return {
name: 'wxt:dev-server-globals',
config() {
if (config.server == null || config.command == 'build') return;
if (server == null || config.command == 'build') return;
return {
define: {
__DEV_SERVER_PROTOCOL__: JSON.stringify('ws:'),
__DEV_SERVER_HOSTNAME__: JSON.stringify(config.server.hostname),
__DEV_SERVER_PORT__: JSON.stringify(config.server.port),
__DEV_SERVER_HOSTNAME__: JSON.stringify(server.hostname),
__DEV_SERVER_PORT__: JSON.stringify(server.port),
},
};
},
+1 -1
View File
@@ -9,7 +9,7 @@ import { fetchCached } from '~/core/utils/network';
* @example
* import "url:https://google-tagmanager.com/gtag?id=XYZ";
*/
export function download(config: Omit<ResolvedConfig, 'builder'>): Plugin {
export function download(config: ResolvedConfig): Plugin {
return {
name: 'wxt:download',
resolveId(id) {
@@ -6,9 +6,7 @@ import type * as vite from 'vite';
* `webextension-polyfill` module to a virtual module and exporting the `chrome` global from the
* virtual module.
*/
export function excludeBrowserPolyfill(
config: Omit<ResolvedConfig, 'builder'>,
): vite.Plugin {
export function excludeBrowserPolyfill(config: ResolvedConfig): vite.Plugin {
const virtualId = 'virtual:wxt-webextension-polyfill-disabled';
return {
+1 -3
View File
@@ -2,9 +2,7 @@ import type * as vite from 'vite';
import { ResolvedConfig } from '~/types';
import { getGlobals } from '~/core/utils/globals';
export function globals(
config: Omit<ResolvedConfig, 'builder'>,
): vite.PluginOption {
export function globals(config: ResolvedConfig): vite.PluginOption {
return {
name: 'wxt:globals',
config() {
+1 -1
View File
@@ -3,7 +3,7 @@ export * from './devServerGlobals';
export * from './download';
export * from './multipageMove';
export * from './unimport';
export * from './virtualEntrypoint';
export * from './resolveVirtualModules';
export * from './tsconfigPaths';
export * from './noopBackground';
export * from './cssEntrypoints';
@@ -20,7 +20,7 @@ import { normalizePath } from '~/core/utils/paths';
*/
export function multipageMove(
entrypoints: Entrypoint[],
config: Omit<ResolvedConfig, 'builder'>,
config: ResolvedConfig,
): vite.Plugin {
return {
name: 'wxt:multipage-move',
@@ -0,0 +1,41 @@
import { Plugin } from 'vite';
import { ResolvedConfig } from '~/types';
import { normalizePath } from '~/core/utils/paths';
import {
VirtualModuleId,
virtualModuleNames,
} from '~/core/utils/virtual-modules';
import fs from 'fs-extra';
import { resolve } from 'path';
/**
* Resolve all the virtual modules to the `node_modules/wxt/dist/virtual` directory.
*/
export function resolveVirtualModules(config: ResolvedConfig): Plugin[] {
return virtualModuleNames.map((name) => {
const virtualId: `${VirtualModuleId}?` = `virtual:wxt-${name}?`;
const resolvedVirtualId = '\0' + virtualId;
return {
name: `wxt:resolve-virtual-${name}`,
resolveId(id) {
// Id doesn't start with prefix, it looks like this:
// /path/to/project/virtual:wxt-background?/path/to/project/entrypoints/background.ts
const index = id.indexOf(virtualId);
if (index === -1) return;
const inputPath = normalizePath(id.substring(index + virtualId.length));
return resolvedVirtualId + inputPath;
},
async load(id) {
if (!id.startsWith(resolvedVirtualId)) return;
const inputPath = id.replace(resolvedVirtualId, '');
const template = await fs.readFile(
resolve(config.wxtModuleDir, `dist/virtual/${name}.js`),
'utf-8',
);
return template.replace(`virtual:user-${name}`, inputPath);
},
};
});
}
@@ -1,9 +1,7 @@
import { ResolvedConfig } from '~/types';
import type * as vite from 'vite';
export function tsconfigPaths(
config: Omit<ResolvedConfig, 'builder'>,
): vite.Plugin {
export function tsconfigPaths(config: ResolvedConfig): vite.Plugin {
return {
name: 'wxt:aliases',
async config() {
+1 -3
View File
@@ -15,9 +15,7 @@ const ENABLED_EXTENSIONS = new Set([
/**
* Inject any global imports defined by unimport
*/
export function unimport(
config: Omit<ResolvedConfig, 'builder'>,
): vite.PluginOption {
export function unimport(config: ResolvedConfig): vite.PluginOption {
const options = config.imports;
if (options === false) return [];
@@ -1,39 +0,0 @@
import { Plugin } from 'vite';
import { ResolvedConfig, VirtualEntrypointType } from '~/types';
import fs from 'fs-extra';
import { resolve } from 'path';
import { normalizePath } from '~/core/utils/paths';
/**
* Wraps a user's entrypoint with a vitual version with additional logic.
*/
export function virtualEntrypoint(
type: VirtualEntrypointType,
config: Omit<ResolvedConfig, 'builder'>,
): Plugin {
const virtualId = `virtual:wxt-${type}?`;
const resolvedVirtualId = `\0${virtualId}`;
return {
name: `wxt:virtual-entrypoint`,
resolveId(id) {
// Id doesn't start with prefix, it looks like this:
// /path/to/project/virtual:background?/path/to/project/entrypoints/background.ts
const index = id.indexOf(virtualId);
if (index === -1) return;
const inputPath = normalizePath(id.substring(index + virtualId.length));
return resolvedVirtualId + inputPath;
},
async load(id) {
if (!id.startsWith(resolvedVirtualId)) return;
const inputPath = id.replace(resolvedVirtualId, '');
const template = await fs.readFile(
resolve(config.wxtModuleDir, `dist/virtual/${type}-entrypoint.js`),
'utf-8',
);
return template.replace(`virtual:user-${type}`, inputPath);
},
};
}
@@ -16,7 +16,7 @@ import { ResolvedConfig } from '~/types';
* `npm list` and inline them automatically.
*/
export function webextensionPolyfillMock(
config: Omit<ResolvedConfig, 'builder'>,
config: ResolvedConfig,
): vite.PluginOption {
return {
name: 'wxt:testing-inline-deps',
+62 -64
View File
@@ -26,7 +26,10 @@ import pc from 'picocolors';
import { relative } from 'node:path';
import { registerWxt, wxt } from './wxt';
import { unnormalizePath } from './utils/paths';
import { mapWxtOptionsToRegisteredContentScript } from './utils/content-scripts';
import {
getContentScriptJs,
mapWxtOptionsToRegisteredContentScript,
} from './utils/content-scripts';
/**
* Creates a dev server and pre-builds all the files that need to exist before loading the extension.
@@ -40,14 +43,63 @@ import { mapWxtOptionsToRegisteredContentScript } from './utils/content-scripts'
export async function createServer(
inlineConfig?: InlineConfig,
): Promise<WxtDevServer> {
const port = await getPort();
const hostname = 'localhost';
const origin = `http://${hostname}:${port}`;
const serverInfo: ServerInfo = {
port,
hostname,
origin,
};
await registerWxt('serve', inlineConfig, async (config) => {
const { port, hostname } = config.dev.server!;
const serverInfo: ServerInfo = {
port,
hostname,
origin: `http://${hostname}:${port}`,
};
// Server instance must be created first so its reference can be added to the internal config used
// to pre-render entrypoints
const server: WxtDevServer = {
...serverInfo,
get watcher() {
return builderServer.watcher;
},
get ws() {
return builderServer.ws;
},
currentOutput: undefined,
async start() {
await builderServer.listen();
wxt.logger.success(`Started dev server @ ${serverInfo.origin}`);
await buildAndOpenBrowser();
},
async stop() {
await runner.closeBrowser();
await builderServer.close();
},
async restart() {
await closeAndRecreateRunner();
await buildAndOpenBrowser();
},
transformHtml(url, html, originalUrl) {
return builderServer.transformHtml(url, html, originalUrl);
},
reloadContentScript(payload) {
server.ws.send('wxt:reload-content-script', payload);
},
reloadPage(path) {
server.ws.send('wxt:reload-page', path);
},
reloadExtension() {
server.ws.send('wxt:reload-extension');
},
async restartBrowser() {
await closeAndRecreateRunner();
await runner.openBrowser();
},
};
return server;
});
const server = wxt.server!;
let [runner, builderServer] = await Promise.all([
createExtensionRunner(),
wxt.builder.createServer(server),
]);
const buildAndOpenBrowser = async () => {
// Build after starting the dev server so it can be used to transform HTML files
@@ -74,55 +126,6 @@ export async function createServer(
runner = await createExtensionRunner();
};
// Server instance must be created first so its reference can be added to the internal config used
// to pre-render entrypoints
const server: WxtDevServer = {
...serverInfo,
get watcher() {
return builderServer.watcher;
},
get ws() {
return builderServer.ws;
},
currentOutput: undefined,
async start() {
await builderServer.listen();
wxt.logger.success(`Started dev server @ ${serverInfo.origin}`);
await buildAndOpenBrowser();
},
async stop() {
await runner.closeBrowser();
await builderServer.close();
},
async restart() {
await closeAndRecreateRunner();
await buildAndOpenBrowser();
},
transformHtml(url, html, originalUrl) {
return builderServer.transformHtml(url, html, originalUrl);
},
reloadContentScript(payload) {
server.ws.send('wxt:reload-content-script', payload);
},
reloadPage(path) {
server.ws.send('wxt:reload-page', path);
},
reloadExtension() {
server.ws.send('wxt:reload-extension');
},
async restartBrowser() {
await closeAndRecreateRunner();
await runner.openBrowser();
},
};
await registerWxt('serve', inlineConfig, server);
let [runner, builderServer] = await Promise.all([
createExtensionRunner(),
wxt.config.builder.createServer(server),
]);
// Register content scripts for the first time after the background starts up since they're not
// listed in the manifest
server.ws.on('wxt:background-initialized', () => {
@@ -137,11 +140,6 @@ export async function createServer(
return server;
}
async function getPort(): Promise<number> {
const { default: getPort, portNumbers } = await import('get-port');
return await getPort({ port: portNumbers(3000, 3010) });
}
/**
* Returns a function responsible for reloading different parts of the extension when a file
* changes.
@@ -237,7 +235,7 @@ function reloadContentScripts(steps: BuildStepOutput[], server: WxtDevServer) {
const entry = step.entrypoints;
if (Array.isArray(entry) || entry.type !== 'content-script') return;
const js = [getEntrypointBundlePath(entry, wxt.config.outDir, '.js')];
const js = getContentScriptJs(wxt.config, entry);
const cssMap = getContentScriptsCssMap(server.currentOutput, [entry]);
const css = getContentScriptCssFiles([entry], cssMap);
@@ -0,0 +1,20 @@
import { describe, it } from 'vitest';
import {
VirtualModuleId,
VirtualModuleName,
VirtualEntrypointType,
VirtualEntrypointModuleName,
} from '../virtual-modules';
describe('Virtual Modules', () => {
it('should resolve types to litteral values, not string', () => {
// @ts-expect-error
const _c: VirtualEntrypointType = '';
// @ts-expect-error
const _d: VirtualEntrypointModuleName = '';
// @ts-expect-error
const _b: VirtualModuleName = '';
// @ts-expect-error
const _a: VirtualModuleId = '';
});
});
+11
View File
@@ -21,3 +21,14 @@ export function some<T>(
if (predicate(array[i], i)) return true;
return false;
}
/**
* Convert an item or array to an array.
*/
export function toArray<T>(a: T | T[]): T[] {
return Array.isArray(a) ? a : [a];
}
export function filterTruthy<T>(array: Array<T | undefined>): T[] {
return array.filter((item) => !!item) as T[];
}
+3 -2
View File
@@ -5,6 +5,7 @@ import { dirname, resolve } from 'path';
import type { Ora } from 'ora';
import pc from 'picocolors';
import { wxt } from '../../wxt';
import { toArray } from '../arrays';
export async function buildEntrypoints(
groups: EntrypointGroup[],
@@ -13,12 +14,12 @@ export async function buildEntrypoints(
const steps: BuildStepOutput[] = [];
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
const groupNames = [group].flat().map((e) => e.name);
const groupNames = toArray(group).map((e) => e.name);
const groupNameColored = groupNames.join(pc.dim(', '));
spinner.text =
pc.dim(`[${i + 1}/${groups.length}]`) + ` ${groupNameColored}`;
try {
steps.push(await wxt.config.builder.build(group));
steps.push(await wxt.builder.build(group));
} catch (err) {
spinner.stop().clear();
wxt.logger.error(err);
+1 -1
View File
@@ -37,7 +37,7 @@ export async function internalBuild(): Promise<BuildOutput> {
const target = `${wxt.config.browser}-mv${wxt.config.manifestVersion}`;
wxt.logger.info(
`${verb} ${pc.cyan(target)} for ${pc.cyan(wxt.config.mode)} with ${pc.green(
`${wxt.config.builder.name} ${wxt.config.builder.version}`,
`${wxt.builder.name} ${wxt.builder.version}`,
)}`,
);
const startTime = Date.now();
+98 -101
View File
@@ -7,14 +7,13 @@ import {
UserManifestFn,
UserManifest,
ExtensionRunnerConfig,
WxtDevServer,
WxtResolvedUnimportOptions,
Logger,
WxtCommand,
} from '~/types';
import path from 'node:path';
import { createFsCache } from '~/core/utils/cache';
import consola, { LogLevels } from 'consola';
import { createViteBuilder } from '~/core/builders/vite';
import defu from 'defu';
import { NullablyRequired } from '../types';
import { isModuleInstalled } from '../package';
@@ -30,8 +29,7 @@ import { normalizePath } from '../paths';
*/
export async function resolveConfig(
inlineConfig: InlineConfig,
command: 'build' | 'serve',
server?: WxtDevServer,
command: WxtCommand,
): Promise<ResolvedConfig> {
// Load user config
@@ -53,7 +51,7 @@ export async function resolveConfig(
// Merge it into the inline config
const mergedConfig = mergeInlineConfig(inlineConfig, userConfig);
const mergedConfig = await mergeInlineConfig(inlineConfig, userConfig);
// Apply defaults to make internal config.
@@ -65,8 +63,7 @@ export async function resolveConfig(
const manifestVersion =
mergedConfig.manifestVersion ??
(browser === 'firefox' || browser === 'safari' ? 2 : 3);
const mode =
mergedConfig.mode ?? (command === 'build' ? 'production' : 'development');
const mode = mergedConfig.mode ?? COMMAND_MODES[command];
const env: ConfigEnv = { browser, command, manifestVersion, mode };
const root = path.resolve(
@@ -113,14 +110,20 @@ export async function resolveConfig(
}).map(([key, value]) => [key, path.resolve(root, value)]),
);
const analysisOutputFile = path.resolve(
root,
mergedConfig.analysis?.outputFile ?? 'stats.html',
);
const analysisOutputDir = path.dirname(analysisOutputFile);
const analysisOutputName = path.parse(analysisOutputFile).name;
let devServerConfig: ResolvedConfig['dev']['server'];
if (command === 'serve') {
let port = mergedConfig.dev?.server?.port;
if (port == null || !isFinite(port)) {
const { default: getPort, portNumbers } = await import('get-port');
port = await getPort({ port: portNumbers(3000, 3010) });
}
devServerConfig = {
port,
hostname: 'localhost',
};
}
const finalConfig: Omit<ResolvedConfig, 'builder'> = {
return {
browser,
command,
debug,
@@ -142,42 +145,20 @@ export async function resolveConfig(
srcDir,
typesDir,
wxtDir,
zip: resolveInternalZipConfig(root, mergedConfig),
transformManifest(manifest) {
userConfig.transformManifest?.(manifest);
inlineConfig.transformManifest?.(manifest);
},
analysis: {
enabled: mergedConfig.analysis?.enabled ?? false,
open: mergedConfig.analysis?.open ?? false,
template: mergedConfig.analysis?.template ?? 'treemap',
outputFile: analysisOutputFile,
outputDir: analysisOutputDir,
outputName: analysisOutputName,
keepArtifacts: mergedConfig.analysis?.keepArtifacts ?? false,
},
zip: resolveZipConfig(root, mergedConfig),
transformManifest: mergedConfig.transformManifest,
analysis: resolveAnalysisConfig(root, mergedConfig),
userConfigMetadata: userConfigMetadata ?? {},
alias,
experimental: {
includeBrowserPolyfill:
mergedConfig.experimental?.includeBrowserPolyfill ?? true,
},
server,
experimental: defu(mergedConfig.experimental, {
includeBrowserPolyfill: true,
}),
dev: {
server: devServerConfig,
reloadCommand,
},
hooks: mergedConfig.hooks ?? {},
};
const builder = await createViteBuilder(
inlineConfig,
userConfig,
finalConfig,
);
return {
...finalConfig,
builder,
vite: mergedConfig.vite ?? (() => ({})),
};
}
@@ -193,77 +174,45 @@ async function resolveManifestConfig(
/**
* Merge the inline config and user config. Inline config is given priority. Defaults are not applied here.
*/
function mergeInlineConfig(
async function mergeInlineConfig(
inlineConfig: InlineConfig,
userConfig: UserConfig,
): NullablyRequired<InlineConfig> {
let imports: InlineConfig['imports'];
if (inlineConfig.imports === false || userConfig.imports === false) {
imports = false;
} else if (userConfig.imports == null && inlineConfig.imports == null) {
imports = undefined;
} else {
imports = defu(inlineConfig.imports ?? {}, userConfig.imports ?? {});
}
): Promise<InlineConfig> {
// Merge imports option
const imports: InlineConfig['imports'] =
inlineConfig.imports === false || userConfig.imports === false
? false
: userConfig.imports == null && inlineConfig.imports == null
? undefined
: defu(inlineConfig.imports ?? {}, userConfig.imports ?? {});
// Merge manifest option
const manifest: UserManifestFn = async (env) => {
const user = await resolveManifestConfig(env, userConfig.manifest);
const inline = await resolveManifestConfig(env, inlineConfig.manifest);
return defu(inline, user);
};
const runner: InlineConfig['runner'] = defu(
inlineConfig.runner ?? {},
userConfig.runner ?? {},
);
const zip: InlineConfig['zip'] = defu(
inlineConfig.zip ?? {},
userConfig.zip ?? {},
);
const hooks: InlineConfig['hooks'] = defu(
inlineConfig.hooks ?? {},
userConfig.hooks ?? {},
);
// Merge transformManifest option
const transformManifest: InlineConfig['transformManifest'] = (manifest) => {
userConfig.transformManifest?.(manifest);
inlineConfig.transformManifest?.(manifest);
};
// Builders
const builderConfig = await mergeBuilderConfig(inlineConfig, userConfig);
return {
root: inlineConfig.root ?? userConfig.root,
browser: inlineConfig.browser ?? userConfig.browser,
manifestVersion: inlineConfig.manifestVersion ?? userConfig.manifestVersion,
configFile: inlineConfig.configFile,
debug: inlineConfig.debug ?? userConfig.debug,
entrypointsDir: inlineConfig.entrypointsDir ?? userConfig.entrypointsDir,
filterEntrypoints:
inlineConfig.filterEntrypoints ?? userConfig.filterEntrypoints,
...defu(inlineConfig, userConfig),
// Custom merge values
transformManifest,
imports,
logger: inlineConfig.logger ?? userConfig.logger,
manifest,
mode: inlineConfig.mode ?? userConfig.mode,
publicDir: inlineConfig.publicDir ?? userConfig.publicDir,
runner,
srcDir: inlineConfig.srcDir ?? userConfig.srcDir,
outDir: inlineConfig.outDir ?? userConfig.outDir,
zip,
analysis: {
...userConfig.analysis,
...inlineConfig.analysis,
},
alias: {
...userConfig.alias,
...inlineConfig.alias,
},
experimental: {
...userConfig.experimental,
...inlineConfig.experimental,
},
vite: undefined,
transformManifest: undefined,
dev: {
...userConfig.dev,
...inlineConfig.dev,
},
hooks,
...builderConfig,
};
}
function resolveInternalZipConfig(
function resolveZipConfig(
root: string,
mergedConfig: InlineConfig,
): NullablyRequired<ResolvedConfig['zip']> {
@@ -292,6 +241,28 @@ function resolveInternalZipConfig(
};
}
function resolveAnalysisConfig(
root: string,
mergedConfig: InlineConfig,
): NullablyRequired<ResolvedConfig['analysis']> {
const analysisOutputFile = path.resolve(
root,
mergedConfig.analysis?.outputFile ?? 'stats.html',
);
const analysisOutputDir = path.dirname(analysisOutputFile);
const analysisOutputName = path.parse(analysisOutputFile).name;
return {
enabled: mergedConfig.analysis?.enabled ?? false,
open: mergedConfig.analysis?.open ?? false,
template: mergedConfig.analysis?.template ?? 'treemap',
outputFile: analysisOutputFile,
outputDir: analysisOutputDir,
outputName: analysisOutputName,
keepArtifacts: mergedConfig.analysis?.keepArtifacts ?? false,
};
}
async function getUnimportOptions(
wxtDir: string,
logger: Logger,
@@ -360,3 +331,29 @@ function logMissingDir(logger: Logger, name: string, expected: string) {
)}`,
);
}
/**
* Map of `ConfigEnv` commands to their default modes.
*/
const COMMAND_MODES: Record<WxtCommand, string> = {
build: 'production',
serve: 'development',
};
export async function mergeBuilderConfig(
inlineConfig: InlineConfig,
userConfig: UserConfig,
): Promise<Pick<InlineConfig, 'vite'>> {
const vite = await import('vite').catch(() => void 0);
if (vite) {
return {
vite: async (env) => {
const resolvedInlineConfig = (await inlineConfig.vite?.(env)) ?? {};
const resolvedUserConfig = (await userConfig.vite?.(env)) ?? {};
return vite.mergeConfig(resolvedUserConfig, resolvedInlineConfig);
},
};
}
throw Error('Builder not found. Make sure vite is installed.');
}
+9 -1
View File
@@ -1,5 +1,6 @@
import type { Manifest, Scripting } from '~/browser';
import { ContentScriptEntrypoint } from '~/types';
import { ContentScriptEntrypoint, ResolvedConfig } from '~/types';
import { getEntrypointBundlePath } from './entrypoints';
/**
* Returns a unique and consistent string hash based on a content scripts options.
@@ -83,3 +84,10 @@ export function mapWxtOptionsToRegisteredContentScript(
world: options.world,
};
}
export function getContentScriptJs(
config: ResolvedConfig,
entrypoint: ContentScriptEntrypoint,
): string[] {
return [getEntrypointBundlePath(entrypoint, config.outDir, '.js')];
}
+1 -1
View File
@@ -1,7 +1,7 @@
import { ResolvedConfig } from '~/types';
export function getGlobals(
config: Omit<ResolvedConfig, 'builder'>,
config: ResolvedConfig,
): Array<{ name: string; value: any; type: string }> {
return [
{
+4 -4
View File
@@ -111,7 +111,7 @@ export async function generateManifest(
if (wxt.config.command === 'serve') addDevModePermissions(manifest);
// TODO: Remove in v1
wxt.config.transformManifest(manifest);
wxt.config.transformManifest?.(manifest);
await wxt.hooks.callHook('build:manifestGenerated', wxt, manifest);
if (wxt.config.manifestVersion === 2) {
@@ -455,8 +455,8 @@ function discoverIcons(
}
function addDevModeCsp(manifest: Manifest.WebExtensionManifest): void {
const permission = `http://${wxt.config.server?.hostname ?? ''}/*`;
const allowedCsp = wxt.config.server?.origin ?? 'http://localhost:*';
const permission = `http://${wxt.server?.hostname ?? ''}/*`;
const allowedCsp = wxt.server?.origin ?? 'http://localhost:*';
if (manifest.manifest_version === 3) {
addHostPermission(manifest, permission);
@@ -473,7 +473,7 @@ function addDevModeCsp(manifest: Manifest.WebExtensionManifest): void {
"script-src 'self'; object-src 'self';", // default CSP for MV2
);
if (wxt.config.server) csp.add('script-src', allowedCsp);
if (wxt.server) csp.add('script-src', allowedCsp);
if (manifest.manifest_version === 3) {
manifest.content_security_policy ??= {};
+1 -1
View File
@@ -26,7 +26,7 @@ export async function isOnline(): Promise<boolean> {
*/
export async function fetchCached(
url: string,
config: Omit<ResolvedConfig, 'builder'>,
config: ResolvedConfig,
): Promise<string> {
let content: string = '';
+3 -2
View File
@@ -270,7 +270,6 @@ export const fakeResolvedConfig = fakeObjectCreator<ResolvedConfig>(() => {
srcDir: fakeDir(),
typesDir: fakeDir(),
wxtDir: fakeDir(),
server: mock<WxtDevServer>(),
analysis: {
enabled: false,
open: false,
@@ -296,11 +295,11 @@ export const fakeResolvedConfig = fakeObjectCreator<ResolvedConfig>(() => {
experimental: {
includeBrowserPolyfill: true,
},
builder: mock(),
dev: {
reloadCommand: 'Alt+R',
},
hooks: {},
vite: () => ({}),
};
});
@@ -310,6 +309,8 @@ export const fakeWxt = fakeObjectCreator<Wxt>(() => ({
logger: mock(),
reloadConfig: vi.fn(),
pm: mock(),
server: faker.helpers.arrayElement([undefined, mock<WxtDevServer>()]),
builder: mock(),
}));
export function setFakeWxt(overrides?: DeepPartial<Wxt>) {
+37
View File
@@ -0,0 +1,37 @@
export const virtualEntrypointTypes = [
'content-script-main-world' as const,
'content-script-isolated-world' as const,
'background' as const,
'unlisted-script' as const,
];
export type VirtualEntrypointType = (typeof virtualEntrypointTypes)[0];
/**
* All the names of entrypoint files in the `src/virtual/` and `dist/virtual/` directories, minus the extension.
*/
export const virtualEntrypointModuleNames = virtualEntrypointTypes.map(
(name) => `${name}-entrypoint` as const,
);
/**
* Name of entrypoint files in the `src/virtual/` and `dist/virtual/` directories, minus the extension.
*/
export type VirtualEntrypointModuleName =
(typeof virtualEntrypointModuleNames)[0];
/**
* All the names of files in the `src/virtual/` and `dist/virtual/` directories, minus the extension.
*/
export const virtualModuleNames = [
...virtualEntrypointModuleNames,
'mock-browser' as const,
'reload-html' as const,
];
/**
* Name of files in the `src/virtual/` and `dist/virtual/` directories, minus the extension.
*/
export type VirtualModuleName = (typeof virtualModuleNames)[0];
/**
* Import alias used for importing a virtual module
*/
export type VirtualModuleId = `virtual:wxt-${VirtualModuleName}`;
+17 -5
View File
@@ -1,7 +1,15 @@
import { InlineConfig, Wxt, WxtDevServer, WxtHooks } from '~/types';
import {
InlineConfig,
ResolvedConfig,
Wxt,
WxtCommand,
WxtDevServer,
WxtHooks,
} from '~/types';
import { resolveConfig } from './utils/building';
import { createHooks } from 'hookable';
import { createWxtPackageManager } from './package-managers';
import { createViteBuilder } from './builders/vite';
/**
* Global variable set once `createWxt` is called once. Since this variable is used everywhere, this
@@ -13,12 +21,14 @@ export let wxt: Wxt;
* Create and register a global instance of the Wxt interface for use throughout the project.
*/
export async function registerWxt(
command: 'build' | 'serve',
command: WxtCommand,
inlineConfig: InlineConfig = {},
server?: WxtDevServer,
getServer?: (config: ResolvedConfig) => Promise<WxtDevServer>,
): Promise<void> {
const config = await resolveConfig(inlineConfig, command, server);
const hooks = createHooks<WxtHooks>();
const config = await resolveConfig(inlineConfig, command);
const server = await getServer?.(config);
const builder = await createViteBuilder(config, hooks, server);
const pm = await createWxtPackageManager(config.root);
wxt = {
@@ -28,9 +38,11 @@ export async function registerWxt(
return config.logger;
},
async reloadConfig() {
wxt.config = await resolveConfig(inlineConfig, command, server);
wxt.config = await resolveConfig(inlineConfig, command);
},
pm,
builder,
server,
};
// Initialize hooks
+1
View File
@@ -38,6 +38,7 @@ export async function zip(config?: InlineConfig): Promise<string[]> {
'{{version}}',
output.manifest.version_name ?? output.manifest.version,
)
.replaceAll('{{mode}}', wxt.config.mode)
.replaceAll('{{manifestVersion}}', `mv${wxt.config.manifestVersion}`);
await fs.ensureDir(wxt.config.outBaseDir);
+2 -1
View File
@@ -8,6 +8,7 @@
import { Storage, browser } from '~/browser';
import { dequal } from 'dequal/lite';
import { logger } from './sandbox/utils/logger';
import { toArray } from './core/utils/arrays';
export const storage = createStorage();
@@ -107,7 +108,7 @@ function createStorage(): WxtStorage {
await driver.removeItem(metaKey);
} else {
const newFields = getMetaValue(await driver.getItem(metaKey));
[properties].flat().forEach((field) => delete newFields[field]);
toArray(properties).forEach((field) => delete newFields[field]);
await driver.setItem(metaKey, newFields);
}
};
+1 -1
View File
@@ -4,7 +4,7 @@ declare const __DEV_SERVER_PORT__: string;
// Globals defined by the vite-plugins/devServerGlobals.ts and utils/globals.ts
interface ImportMetaEnv {
readonly COMMAND: 'build' | 'serve';
readonly COMMAND: WxtCommand;
readonly MANIFEST_VERSION: 2 | 3;
readonly ENTRYPOINT: string;
}
+66 -21
View File
@@ -117,10 +117,11 @@ export interface InlineConfig {
*
* Available template variables:
*
* - `{{name}}` - The project's name converted to kebab-case
* - `{{version}}` - The version_name or version from the manifest
* - `{{browser}}` - The target browser from the `--browser` CLI flag
* - `{{manifestVersion}}` - Either "2" or "3"
* - <span v-pre>`{{name}}`</span> - The project's name converted to kebab-case
* - <span v-pre>`{{version}}`</span> - The version_name or version from the manifest
* - <span v-pre>`{{browser}}`</span> - The target browser from the `--browser` CLI flag
* - <span v-pre>`{{mode}}`</span> - The current mode
* - <span v-pre>`{{manifestVersion}}`</span> - Either "2" or "3"
*
* @default "{{name}}-{{version}}-{{browser}}.zip"
*/
@@ -130,10 +131,11 @@ export interface InlineConfig {
*
* Available template variables:
*
* - `{{name}}` - The project's name converted to kebab-case
* - `{{version}}` - The version_name or version from the manifest
* - `{{browser}}` - The target browser from the `--browser` CLI flag
* - `{{manifestVersion}}` - Either "2" or "3"
* - <span v-pre>`{{name}}`</span> - The project's name converted to kebab-case
* - <span v-pre>`{{version}}`</span> - The version_name or version from the manifest
* - <span v-pre>`{{browser}}`</span> - The target browser from the `--browser` CLI flag
* - <span v-pre>`{{mode}}`</span> - The current mode
* - <span v-pre>`{{manifestVersion}}`</span> - Either "2" or "3"
*
* @default "{{name}}-{{version}}-sources.zip"
*/
@@ -171,7 +173,7 @@ export interface InlineConfig {
*
* @example
* [
* "coverage", // Ignore the coverage directory in the `sourcesRoot`
* "coverage", // Include the coverage directory in the `sourcesRoot`
* ]
*/
excludeSources?: string[];
@@ -307,6 +309,12 @@ export interface InlineConfig {
* Config effecting dev mode only.
*/
dev?: {
server?: {
/**
* Port to run the dev server on. Defaults to the first open port from 3000 to 3010.
*/
port?: number;
};
/**
* Controls whether a custom keyboard shortcut command, `Alt+R`, is added during dev mode to
* quickly reload the extension.
@@ -342,12 +350,39 @@ export interface InlineConfig {
vite?: (env: ConfigEnv) => WxtViteConfig | Promise<WxtViteConfig>;
}
// TODO: Move into @wxt/vite-builder
export interface ResolvedConfig {
vite: (env: ConfigEnv) => WxtViteConfig | Promise<WxtViteConfig>;
}
// TODO: Move into @wxt/vite-builder
export type WxtViteConfig = Omit<
vite.UserConfig,
'root' | 'configFile' | 'mode'
>;
// TODO: Move into @wxt/vite-builder
export interface WxtHooks {
/**
* Called when WXT has created Vite's config for a build step. Useful if you
* want to add plugins or update the vite config per entrypoint group.
*
* @param entrypoints The list of entrypoints being built with the provided config.
* @param viteConfig The config that will be used for the dev server.
*/
'vite:build:extendConfig': (
entrypoints: readonly Entrypoint[],
viteConfig: vite.InlineConfig,
) => HookResult;
/**
* Called when WXT has created Vite's config for the dev server. Useful if
* you want to add plugins or update the vite config per entrypoint group.
*
* @param viteConfig The config that will be used to build the entrypoints. Can be updated by reference.
*/
'vite:devServer:extendConfig': (config: vite.InlineConfig) => HookResult;
}
export interface BuildOutput {
manifest: Manifest.WebExtensionManifest;
publicAssets: OutputAsset[];
@@ -772,7 +807,7 @@ export interface ConfigEnv {
/**
* The command used to run WXT. `"serve"` during development and `"build"` for any other command.
*/
command: 'build' | 'serve';
command: WxtCommand;
/**
* Browser passed in from the CLI via the `-b` or `--browser` flag. Defaults to `"chrome"` when not passed.
*/
@@ -785,6 +820,8 @@ export interface ConfigEnv {
manifestVersion: 2 | 3;
}
export type WxtCommand = 'build' | 'serve';
/**
* Configure how the browser starts up.
*/
@@ -998,6 +1035,14 @@ export interface Wxt {
* Package manager utilities.
*/
pm: WxtPackageManager;
/**
* If the dev server was started, it will be availble.
*/
server?: WxtDevServer;
/**
* The module in charge of executing all the build steps.
*/
builder: WxtBuilder;
}
export interface ResolvedConfig {
@@ -1016,7 +1061,7 @@ export interface ResolvedConfig {
*/
wxtModuleDir: string;
mode: string;
command: 'build' | 'serve';
command: WxtCommand;
browser: TargetBrowser;
manifestVersion: TargetManifestVersion;
env: ConfigEnv;
@@ -1024,7 +1069,6 @@ export interface ResolvedConfig {
imports: false | WxtResolvedUnimportOptions;
manifest: UserManifest;
fsCache: FsCache;
server?: WxtDevServer;
runnerConfig: C12ResolvedConfig<ExtensionRunnerConfig>;
zip: {
name?: string;
@@ -1036,7 +1080,10 @@ export interface ResolvedConfig {
downloadedPackagesDir: string;
downloadPackages: string[];
};
transformManifest: (manifest: Manifest.WebExtensionManifest) => void;
/**
* @deprecated Use `build:manifestGenerated` hook instead.
*/
transformManifest?: (manifest: Manifest.WebExtensionManifest) => void;
analysis: {
enabled: boolean;
open: boolean;
@@ -1057,11 +1104,15 @@ export interface ResolvedConfig {
experimental: {
includeBrowserPolyfill: boolean;
};
builder: WxtBuilder;
dev: {
/** Only defined during dev command */
server?: {
port: number;
hostname: string;
};
reloadCommand: string | false;
};
hooks: Partial<WxtHooks>;
hooks: NestedHooks<WxtHooks>;
}
export interface FsCache {
@@ -1074,12 +1125,6 @@ export interface ExtensionRunner {
closeBrowser(): Promise<void>;
}
export type VirtualEntrypointType =
| 'content-script-main-world'
| 'content-script-isolated-world'
| 'background'
| 'unlisted-script';
export type EslintGlobalsPropValue =
| boolean
| 'readonly'
+1 -1
View File
@@ -1,4 +1,4 @@
import definition from 'virtual:user-background';
import definition from 'virtual:user-background-entrypoint';
import { setupWebSocket } from './utils/setup-web-socket';
import { logger } from '../sandbox/utils/logger';
import { browser } from 'wxt/browser';
@@ -1,4 +1,4 @@
import definition from 'virtual:user-content-script-isolated-world';
import definition from 'virtual:user-content-script-isolated-world-entrypoint';
import { logger } from '../sandbox/utils/logger';
import { ContentScriptContext } from 'wxt/client';
@@ -1,4 +1,4 @@
import definition from 'virtual:user-content-script-main-world';
import definition from 'virtual:user-content-script-main-world-entrypoint';
import { logger } from '../sandbox/utils/logger';
(async () => {
+1 -1
View File
@@ -1,4 +1,4 @@
import definition from 'virtual:user-unlisted-script';
import definition from 'virtual:user-unlisted-script-entrypoint';
import { logger } from '../sandbox/utils/logger';
(async () => {
+4 -4
View File
@@ -1,11 +1,11 @@
// Types required to make the virtual modules happy.
declare module 'virtual:user-background' {
declare module 'virtual:user-background-entrypoint' {
const definition: { main: () => void };
export default definition;
}
declare module 'virtual:user-content-script-isolated-world' {
declare module 'virtual:user-content-script-isolated-world-entrypoint' {
const definition: {
main: (
ctx: import('wxt/client').ContentScriptContext,
@@ -14,12 +14,12 @@ declare module 'virtual:user-content-script-isolated-world' {
export default definition;
}
declare module 'virtual:user-content-script-main-world' {
declare module 'virtual:user-content-script-main-world-entrypoint' {
const definition: { main: () => void | Promise<void> };
export default definition;
}
declare module 'virtual:user-unlisted-script' {
declare module 'virtual:user-unlisted-script-entrypoint' {
const definition: { main: () => void | Promise<void> };
export default definition;
}