Compare commits

..

148 Commits

Author SHA1 Message Date
GitHub Actions 36cfcd0acb chore(release): @wxt-dev/module-solid v1.1.2 2024-08-06 13:07:15 +00:00
GitHub Actions f746d46247 chore(release): @wxt-dev/module-svelte v1.0.1 2024-08-06 12:29:43 +00:00
GitHub Actions a2de6cbe44 chore(release): @wxt-dev/module-vue v1.0.1 2024-08-06 04:23:00 +00:00
GitHub Actions e632a2964a chore(release): @wxt-dev/module-react v1.1.1 2024-08-06 01:55:29 +00:00
GitHub Actions f736a14651 chore(release): @wxt-dev/auto-icons v1.0.2 2024-08-05 23:52:51 +00:00
uncenter a8b0d40959 docs(auto-icons): fix configuration example typo (#905) 2024-08-05 18:48:54 -05:00
Aaron 4c5504d139 Update changelog 2024-08-04 10:18:02 -05:00
GitHub Actions fb86deb388 chore(release): wxt v0.19.4 2024-08-04 14:31:30 +00:00
Aaron 3a8e6135ac fix: Fix createIframeUi page option types 2024-08-04 09:27:46 -05:00
Aaron a38de0c03f feat: Add injectScript helper (#900) 2024-08-04 09:16:46 -05:00
Aaron ea97410fb4 fix(types): PublicPath type resolution with extensionApi: "chrome" (#901) 2024-08-04 08:59:45 -05:00
hikiko4ern e36549ddce fix: do not clear .wxt/tsconfig.json in findEntrypoints if it exists (#898) 2024-08-03 21:59:12 -05:00
KnightYoshi 10851ae01c docs: add missing extension-apis segment (#896) 2024-08-03 19:28:53 -05:00
GitHub Actions d553ef6b29 chore(release): wxt v0.19.3 2024-08-02 21:48:05 +00:00
Aaron 15bf0da82e fix(content-script-context): Fix initialization logic for Firefox (#895) 2024-08-02 16:43:40 -05:00
hikiko4ern fc246ffaac fix: add consola to wxt dependencies (#892) 2024-08-01 19:05:28 -05:00
Florian Metz 9785eff21e chore: add more metadata for npm (#885) 2024-08-01 18:00:00 -05:00
Himanshu Patil 52fbd2c99e docs: Improve prepare:types hook JSDoc (#886) 2024-08-01 17:11:20 -05:00
GitHub Actions 648ae4fb8d chore(release): @wxt-dev/auto-icons v1.0.1 2024-07-30 18:23:12 +00:00
Aaron Klinker bbeeabc9ea Revert version change for auto-icons module 2024-07-30 13:18:35 -05:00
web-dahuyou 35cf6e7bc0 docs: Add "NiceTab" to homepage (#882) 2024-07-30 13:12:00 -05:00
Florian Metz 78822acdac fix(auto-icons): path option (#880)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-07-30 13:06:41 -05:00
不游 aea123890f docs: Add "1Proompt" to homepage (#879) 2024-07-29 07:50:28 -05:00
Matt Strayer c369f4a955 docs: Add "mindful" to homepage (#878) 2024-07-28 16:33:58 -05:00
GitHub Actions 16d8240406 chore(release): wxt v0.19.2 2024-07-28 15:49:52 +00:00
Aaron 24cd01dd31 fix: Don't default to dev mode for production builds when using vite-node loader (#877) 2024-07-28 10:45:32 -05:00
Aaron fb22beadb8 fix: Remove unused top-level functions and variables when loading entrypoints with the vite-node loader (#875) 2024-07-28 09:27:29 -05:00
Aaron Klinker fa85177648 docs(modules): Adjust wording 2024-07-27 17:04:36 -05:00
Aaron Klinker ed07a49dd2 docs: Update README and homepage features with WXT modules 2024-07-27 16:57:33 -05:00
Aaron 09c9de0a60 docs: Fix environment variable reference (#870) 2024-07-27 16:15:28 -05:00
Aaron 523296b29a chore(deps): Upgrade all dependencies (#869) 2024-07-27 16:07:50 -05:00
Aaron Klinker ef67ef47aa chore: Update template package names 2024-07-27 15:37:48 -05:00
Aaron Klinker cb5eb68d62 Fix changelog 2024-07-27 15:11:27 -05:00
GitHub Actions 2e9ab75e2b chore(release): wxt v0.19.1 2024-07-27 20:09:05 +00:00
Aaron 0c2d795800 pref: Tree-shake unrelated code inside vite-node entrypoint loader (#867) 2024-07-27 15:03:23 -05:00
Aaron 97aa173f7e fix: Define web globals when importing entrypoints (#865) 2024-07-27 14:48:55 -05:00
Aaron 9eb64d94d6 docs: Add README for auto-icons module 2024-07-26 14:00:37 -05:00
Florian Metz a0971cab52 feat: Auto Icons Module (#851)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-07-25 23:41:53 -05:00
Aaron 127562e9d0 ci: Fix breaking changes link generation in changelog 2024-07-25 22:48:05 -05:00
Aaron 038e7450e0 Fix diff 2024-07-25 22:40:33 -05:00
Aaron 6c00763187 docs: Add missing ssr.noExternal docs to vite-node loader 2024-07-25 22:38:21 -05:00
Aaron 2da0f3d686 Fix changelog 2024-07-25 22:14:06 -05:00
GitHub Actions 742d2f1536 chore(release): wxt v0.19.0 2024-07-26 01:03:48 +00:00
Aaron b4b69783d5 docs: Add upgrade guide and breaking changes (#860) 2024-07-25 19:59:15 -05:00
Aaron c8ddc66cfa feat!: Use vite-node to load entrypoints by default (#859)
BREAKING CHANGE: Switch from using `jiti` to import entrypoints during the build process by default to `vite-node`.

To continue using `jiti`, add the following to your `wxt.config.ts` file:

```ts
export default defineConfig({
  entrypointLoader: "jiti",
})
```

NOTE: "jiti" is deprecated and will be removed in the next major version, `v0.20.0`.
2024-07-25 17:25:46 -05:00
Aaron 2b6ff8d30f docs: Update labels in content script UI positioning screenshot 2024-07-25 11:45:49 -05:00
Aaron d79d7ed778 feat(hooks): Add prepare:publicPaths hook (#858) 2024-07-25 11:32:16 -05:00
Aaron Klinker ab234c0f45 docs: Review full docs, fix typos, re-order sections 2024-07-25 00:10:04 -05:00
Aaron Klinker eeb43c6bf4 docs: Fix typo 2024-07-24 23:22:14 -05:00
Aaron 17bda1eb34 feat(storage): init option and rename defaultValue to fallback (#827) 2024-07-24 23:18:16 -05:00
Aaron 96e28c415c docs: Extract comparison comments to footnotes (#853) 2024-07-24 23:17:01 -05:00
Florian Metz 1f9f6d9681 chore: update readme (#852) 2024-07-24 21:11:28 -05:00
Aaron f1bb7cb0c2 feat(experimental): First-class support for excluding webextension-polyfill (#847) 2024-07-24 17:09:56 -05:00
Aaron 5eb5be7123 perf(size)!: Switch from tsup to unbuild for building WXT (#848) 2024-07-24 08:48:48 -05:00
Florian Metz 886b2081c2 fix: wrong module hook type (#849) 2024-07-23 20:02:26 -05:00
Radek Grebski c69e51ce50 docs: Added "RespondEasy" to homepage (#844)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-07-23 09:14:59 -05:00
Hagatopaxi 861efa3415 docs: fix typo (#845) 2024-07-22 23:53:00 -05:00
Aaron 792b57542d updtae lockfile 2024-07-21 11:53:34 -05:00
Aaron 97e6678e5b Upgrade vitest's listed version 2024-07-21 11:46:23 -05:00
Aaron 66c4ec3f99 chore(dev-deps): Upgrade happy-dom from 13 to 14 (#843) 2024-07-21 11:44:52 -05:00
Aaron 8988d6a241 chore(deps): Upgrade minimatch from 9 to 10 (#840) 2024-07-21 11:42:33 -05:00
Aaron b52856bea4 chore(deps): Upgrade webextension-polyfill from 0.10 to 0.12 (#842) 2024-07-21 11:39:40 -05:00
Aaron 16fee19b85 chore(deps): Upgrade ora from 7 to 8 (#841) 2024-07-21 11:39:03 -05:00
Aaron 14011c19cb chore(deps): Upgrade vite-node from 1.6 to 2.0 (#839) 2024-07-21 11:36:02 -05:00
Aaron 005a9dff16 chore(deps): Upgrade esbuild from 0.19.12 to 0.23.0 (#838) 2024-07-21 11:33:39 -05:00
Aaron 3109bbadbe chore(deps): Upgrade async-mutex from 0.4.1 to 0.5.0 (#837) 2024-07-21 11:31:35 -05:00
Aaron 34ae689569 chore(dev-deps): Upgrade vitest from 1.6 to 2.0 (#836) 2024-07-21 11:24:23 -05:00
Aaron 1f216dd57b chore(deps): Bump all non-major dependencies (#834) 2024-07-21 10:01:51 -05:00
GitHub Actions a7963e23db chore(release): wxt v0.18.15 2024-07-21 13:43:02 +00:00
Aaron 069bd6c435 fix: Externalize app config during dependency optimization (#833) 2024-07-21 08:37:09 -05:00
Aaron 88a1244ca9 fix: Build latest version of package before packing 2024-07-21 08:36:45 -05:00
Aaron 7ee391f688 fix: Don't throw error if localization file is missing (#832) 2024-07-21 07:53:38 -05:00
Aaron 2b3eab9c2a docs: Add link to google's update testing tool in migration guide and improve host permission docs 2024-07-20 11:33:17 -05:00
eetann a3fc9e1e18 docs: fix link to unimport (#826) 2024-07-17 07:40:34 -05:00
Aaron 559d32e6eb Update README.md 2024-07-12 08:19:59 -05:00
Aaron f904b79367 Update README.md 2024-07-12 08:19:33 -05:00
eetann 9cd7cca81c docs: fix links to Guide pages (#821) 2024-07-12 07:25:11 -05:00
GitHub Actions 3366c1e35f chore(release): wxt v0.18.14 2024-07-09 16:03:18 +00:00
Aaron 82be31a408 fix(modules): Add types from all wxt node_modules, not just ones with config (#817) 2024-07-09 10:58:41 -05:00
GitHub Actions d767f3f598 chore(release): wxt v0.18.13 2024-07-09 15:07:38 +00:00
Ayub Kokabi 48967c7c5f feat: add XPath support to getAnchor() (#813)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-07-09 10:02:00 -05:00
Aaron 6c4da7225d fix: Add debug logs for vite builder (#816) 2024-07-09 09:58:59 -05:00
多吃点 e9025fb13e docs: Update manifest.md (#815) 2024-07-09 08:12:38 -05:00
jy00566722 8db6b3187b docs: Add "Exchange Rate Converter" extensions to homepage (#808) 2024-07-07 14:41:48 -05:00
Aaron a19f9e12c4 feat(config): dev.server.hostname (#807) 2024-07-07 09:31:38 -05:00
Farzad Soltani a82eb46511 docs: fix grammar (#806) 2024-07-07 09:16:03 -05:00
GitHub Actions e50f2b047a chore(release): wxt v0.18.12 2024-07-07 14:10:47 +00:00
Aaron 1b41cd26ee chore(deps): Upgrade web-ext-run (0.2.0 to 0.2.1) (#804) 2024-07-07 08:57:29 -05:00
Aaron e32fbed1b7 docs: Update README (#802) 2024-07-06 08:29:23 -05:00
sacrosanctic f8acdd6352 doc: detail issues with vite plugins (#799)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-07-06 08:01:22 -05:00
ntnyq 9ea89c6340 fix: Add missing name to ESLint v9 autoImports config (#801) 2024-07-06 08:01:10 -05:00
Margarita Balkheeva a521a80d43 docs: Add "MaxFocus" extension to homepage (#795)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-07-04 14:38:44 -05:00
sacrosanctic 4c6a57dd33 docs: rephrase a paragraph (#797) 2024-07-03 16:16:41 -05:00
Florian Metz 3ce8c8b1f4 perf: create zip using streams (#793) 2024-07-03 01:37:58 -05:00
deyu 4ee8f7837e docs: Add "Vanilla Pudding" extension to homepage (#794) 2024-07-03 01:36:32 -05:00
Aaron 1e8e5488af feat: Support runtime config in app.config.ts (#792) 2024-07-02 17:19:54 -05:00
GitHub Actions 5704765cc4 chore(release): wxt v0.18.11 2024-07-02 16:40:05 +00:00
GitHub Actions 8c7adbf463 chore(release): @wxt-dev/module-react v1.1.0 2024-07-02 16:34:30 +00:00
Aaron 8c4436efe8 Update solid template to @wxt-dev/module-solid v1.1.1 (#789) 2024-07-02 11:29:53 -05:00
GitHub Actions 5e361c0085 chore(release): @wxt-dev/module-solid v1.1.1 2024-07-02 16:23:54 +00:00
Aaron ccfc207e92 fix: Use prepare instead of postinstall for local dev setup (#788) 2024-07-02 11:18:44 -05:00
GitHub Actions 36be4ce771 chore(release): @wxt-dev/module-solid v1.1.0 2024-07-02 15:37:46 +00:00
KnightYoshi 18f8a387b0 feat: add eslint 9 config support (#762)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-07-02 10:32:32 -05:00
C.C 48c2c07557 docs: Fix manifest typo (#787) 2024-07-02 07:09:07 -05:00
Aaron 61548a9478 fix(dev): Catch error when attempting to reload a tab in a saved tab group (#786) 2024-07-01 16:11:00 -05:00
dependabot[bot] fd678e9572 chore(deps): bump oven-sh/setup-bun from 1 to 2 (#785)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 15:40:10 -05:00
Aaron 63fb913f76 docs: New example search (#751) 2024-06-30 09:01:42 -05:00
Aaron faffe20a62 chore(deps): Upgrade non-major deps (#778) 2024-06-29 15:00:15 -05:00
Aaron 3ed8bd10fd chore: Upgrade buildc to v1.0.10 (#780) 2024-06-29 14:09:56 -05:00
Asakura Mizu 6f3f270573 fix: Respect custom outDir when cleaning and zipping (#774) 2024-06-28 09:05:40 -05:00
Aaron 5347cb4626 chore: Replace consola with wxt.logger (#776) 2024-06-28 09:04:21 -05:00
Aaron d6b4d2d1f6 chore(dev-deps): Upgrade buildc to v1.0.9 2024-06-27 16:47:35 -05:00
Aaron 0d7ae287da chore(dev-deps): Upgrade buildc to v1.0.8 2024-06-27 16:38:40 -05:00
Aaron 90cb3bd3bf feat: Enable auto-imports for JSX/TSX files (#773) 2024-06-27 00:05:45 -05:00
Prakhar 🔱 Man of Creativity 60eb97c4b2 docs: Update examples URL (#768)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-06-26 13:52:10 -05:00
Aaron 0ffc6eae3e Fix comment typo 2024-06-25 15:12:59 -05:00
GitHub Actions 06a8c5fb0e chore(release): wxt v0.18.10 2024-06-25 20:03:59 +00:00
Aaron eb86413f35 chore: Consolidate unimport code into a built-in module (#771) 2024-06-25 14:59:28 -05:00
Aaron b29d49cbf1 fix: Await prepare:types hook 2024-06-24 10:04:44 -05:00
Aaron c0a0edb30c feat(modules): Allow adding generated public files (#769) 2024-06-24 08:46:45 -05:00
Aaron b15a933c75 feat: Add prepare:types hook to extend .wxt/ directory generation (#767) 2024-06-23 15:12:28 -05:00
Malix 1851be22a7 docs: Update CRXJS Firefox Compatibility (#764)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-06-23 10:32:09 -05:00
Aaron 39f6c29e4f chore: Refactor package manager test fixtures 2024-06-21 09:10:22 -05:00
GitHub Actions 936e89fbfb chore(release): wxt v0.18.9 2024-06-20 15:34:16 +00:00
Aaron ad365ecde4 feat(experimental): Replace viteRuntime option with entrypointImporter option, and implement vite-node importer (#761) 2024-06-20 10:27:19 -05:00
GitHub Actions b4283e37bd chore(release): wxt v0.18.8 2024-06-20 14:03:16 +00:00
Aaron b467ad760a fix(modules): addViteConfig ignored user vite config (#760) 2024-06-20 08:59:46 -05:00
Aaron 9fc6408ef9 chore: Add E2E test for addImportPreset 2024-06-20 08:52:45 -05:00
Aaron 394cb1a520 docs: Add 'WorkFlowy MultiFlow' to homepage 2024-06-19 14:16:58 -05:00
Aaron ffec88549b fix: Ignore .wxt file changes in dev (#755) 2024-06-19 08:33:52 -05:00
Ziheng Xun 4758bea187 docs: update sandbox.md (#754) 2024-06-19 08:06:08 -05:00
Aaron 6671471f75 feat(dev): Reload extension when public files change (#752) 2024-06-19 08:05:56 -05:00
Aaron ae78dc7fb3 chore: Refactor client web socket util (#753) 2024-06-18 22:47:30 -05:00
Aaron b62af3d007 chore(dev-deps): Upgrade @aklinker1/buildc to 1.0.7 (#748) 2024-06-18 00:11:14 -05:00
Aaron 43ae44ecd5 fix: Don't load plugins twice in HTML pages (#746) 2024-06-17 23:41:39 -05:00
Aaron 5bab9d2f59 chore: Fix build script flags (#745) 2024-06-17 23:41:10 -05:00
Aaron 7edf1c8103 fix: Upgrade wxt peer to >= 0.18.6
This closes https://github.com/wxt-dev/wxt/issues/743
2024-06-17 14:42:24 -05:00
Aaron 53b4eac955 docs: Update wxt init command for bun 2024-06-17 14:39:41 -05:00
GitHub Actions f9a10c2c52 chore(release): wxt v0.18.7 2024-06-17 16:17:42 +00:00
Aaron 8206ca9164 fix(zip): Revert dotfile changes from #674 (#742) 2024-06-17 11:10:06 -05:00
Aaron 1a823cc008 chore: Extract build cache script to NPM package (#737) 2024-06-17 11:09:18 -05:00
Aaron efc011eb81 ci: Fix release 422 failure 2024-06-14 00:36:03 -05:00
GitHub Actions 35f6d28977 chore(release): @wxt-dev/module-solid v1.0.1 2024-06-14 05:29:40 +00:00
Aaron 43fcbec0eb fix: Add target: esnext by default (#733) 2024-06-14 00:25:11 -05:00
Aaron a0d56b4d27 chore: Update templates to use new modules (#732) 2024-06-14 00:19:13 -05:00
Aaron 38ccb6ace6 docs: Update frontend framework docs with new modules (#731) 2024-06-14 00:06:23 -05:00
Aaron aaf75f1de1 ci: Only mark wxt releases as latest 2024-06-14 00:02:41 -05:00
Aaron 21e8ca0a2c chore: Add changelog 2024-06-13 23:52:58 -05:00
261 changed files with 10611 additions and 6369 deletions
+1
View File
@@ -12,6 +12,7 @@ on:
- module-vue - module-vue
- module-svelte - module-svelte
- module-solid - module-solid
- auto-icons
jobs: jobs:
validate: validate:
+5 -4
View File
@@ -18,7 +18,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./.github/actions/setup - uses: ./.github/actions/setup
- run: pnpm -r --sequential build - run: pnpm buildc all
build-demo: build-demo:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
@@ -33,9 +33,9 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./.github/actions/setup - uses: ./.github/actions/setup
- uses: oven-sh/setup-bun@v1 - uses: oven-sh/setup-bun@v2
- name: pnpm test:coverage - name: pnpm test:coverage
run: pnpm test:coverage --reporter=default --reporter=hanging-process run: pnpm test:coverage -- --reporter=default --reporter=hanging-process
- uses: codecov/codecov-action@v4 - uses: codecov/codecov-action@v4
env: env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -44,10 +44,11 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./.github/actions/setup - uses: ./.github/actions/setup
- run: pnpm test run - run: pnpm test
template: template:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
strategy: strategy:
fail-fast: false
matrix: matrix:
template: template:
- react - react
+7 -6
View File
@@ -1,5 +1,5 @@
<h1 align="center"> <h1 align="center">
<img style="vertical-align:middle" width="44" src="./docs/public/hero-logo.svg" alt="WXT Logo"> <img style="vertical-align:middle" width="44" src="https://raw.githubusercontent.com/wxt-dev/wxt/HEAD/docs/public/hero-logo.svg" alt="WXT Logo">
<span>WXT</span> <span>WXT</span>
</h1> </h1>
@@ -18,22 +18,22 @@
<br/> <br/>
<span>⚡</span> <span>⚡</span>
<br/> <br/>
<q><i>It's like Nuxt, but for Chrome Extensions</i></q> <q><i>It's like Nuxt, but for Web Extensions</i></q>
</p> </p>
<p align="center"> <p align="center">
<a href="https://wxt.dev" target="_blank">Get Started</a> <a href="https://wxt.dev/guide/installation.html" target="_blank">Get Started</a>
&bull;
<a href="https://wxt.dev/guide/installation.html" target="_blank">Installation</a>
&bull; &bull;
<a href="https://wxt.dev/api/config.html" target="_blank">Configuration</a> <a href="https://wxt.dev/api/config.html" target="_blank">Configuration</a>
&bull; &bull;
<a href="https://wxt.dev/examples.html" target="_blank">Examples</a> <a href="https://wxt.dev/examples.html" target="_blank">Examples</a>
&bull; &bull;
<a href="https://github.com/wxt-dev/wxt/blob/main/packages/wxt/CHANGELOG.md" target="_blank">Changelog</a>
&bull;
<a href="https://discord.gg/ZFsZqGery9" target="_blank">Discord</a> <a href="https://discord.gg/ZFsZqGery9" target="_blank">Discord</a>
</p> </p>
![Example CLI Output](./docs/assets/cli-output.png) ![Example CLI Output](https://raw.githubusercontent.com/wxt-dev/wxt/HEAD/docs/assets/cli-output.png)
## Demo ## Demo
@@ -59,6 +59,7 @@ Or see the [installation guide](https://wxt.dev/guide/installation.html) to get
- 🦾 Auto-imports - 🦾 Auto-imports
- 🤖 Automated publishing - 🤖 Automated publishing
- 🎨 Frontend framework agnostic: works with Vue, React, Svelte, etc - 🎨 Frontend framework agnostic: works with Vue, React, Svelte, etc
- 📦 Modular architecture with [WXT modules](https://wxt.dev/guide/go-further/reusable-modules.html#overview)
- 🖍️ Quickly bootstrap a new project - 🖍️ Quickly bootstrap a new project
- 📏 Bundle analysis - 📏 Bundle analysis
- ⬇️ Download and bundle remote URL imports - ⬇️ Download and bundle remote URL imports
@@ -1,34 +0,0 @@
<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue';
const props = defineProps<{
tag?: string;
}>();
const examples = ref();
onMounted(async () => {
const res = await fetch(
'https://raw.githubusercontent.com/wxt-dev/wxt-examples/main/examples.json',
);
examples.value = await res.json();
});
const filteredExamples = computed(() => {
if (props.tag == null) return examples.value;
return examples.value.filter((example) => {
return example.tags?.includes(props.tag);
});
});
</script>
<template>
<ul>
<li v-if="examples == null">Loading...</li>
<template v-else>
<li v-for="example of filteredExamples">
<a :href="example.url" target="_blank">{{ example.name }}</a>
</li>
</template>
</ul>
</template>
@@ -0,0 +1,226 @@
<script lang="ts" setup>
import { ref, onMounted, computed, toRaw, Ref } from 'vue';
import ExampleSearchFilterByItem from './ExampleSearchFilterByItem.vue';
import ExampleSearchResult from './ExampleSearchResult.vue';
import { ExamplesMetadata, KeySelectedObject } from '../utils/types';
const props = defineProps<{
tag?: string;
}>();
const exampleMetadata = ref<ExamplesMetadata>();
onMounted(async () => {
const res = await fetch(
'https://raw.githubusercontent.com/wxt-dev/examples/main/metadata.json',
);
exampleMetadata.value = await res.json();
});
const searchText = ref('');
const selectedApis = ref<KeySelectedObject>({});
const selectedPermissions = ref<KeySelectedObject>({});
const selectedPackages = ref<KeySelectedObject>({});
function useRequiredItems(selectedItems: Ref<KeySelectedObject>) {
return computed(() =>
Array.from(
Object.entries(toRaw(selectedItems.value)).reduce(
(set, [pkg, checked]) => {
if (checked) set.add(pkg);
return set;
},
new Set<string>(),
),
),
);
}
const requiredApis = useRequiredItems(selectedApis);
const requiredPermissions = useRequiredItems(selectedPermissions);
const requiredPackages = useRequiredItems(selectedPackages);
function doesExampleMatchSelected(
exampleItems: string[],
requiredItems: Ref<string[]>,
) {
const exampleItemsSet = new Set(exampleItems);
return !requiredItems.value.find((item) => !exampleItemsSet.has(item));
}
const filteredExamples = computed(() => {
const text = searchText.value.toLowerCase();
return exampleMetadata.value.examples.filter((example) => {
const matchesText = example.searchText.toLowerCase().includes(text);
const matchesApis = doesExampleMatchSelected(example.apis, requiredApis);
const matchesPermissions = doesExampleMatchSelected(
example.permissions,
requiredPermissions,
);
const matchesPackages = doesExampleMatchSelected(
example.packages,
requiredPackages,
);
return matchesText && matchesApis && matchesPermissions && matchesPackages;
});
});
</script>
<template>
<div class="example-layout">
<div class="search">
<input v-model="searchText" placeholder="Search for an example..." />
</div>
<div class="filters">
<ExampleSearchFilterByItem
label="APIs"
:items="exampleMetadata?.allApis"
v-model="selectedApis"
/>
<ExampleSearchFilterByItem
label="Permissions"
:items="exampleMetadata?.allPermissions"
v-model="selectedPermissions"
/>
<ExampleSearchFilterByItem
label="Packages"
:items="exampleMetadata?.allPackages"
v-model="selectedPackages"
/>
</div>
<div class="results">
<p v-if="exampleMetadata == null">Loading examples...</p>
<template v-else>
<ul class="search-results">
<ExampleSearchResult
v-for="example of filteredExamples"
:key="example.name"
:example
/>
</ul>
<p v-if="filteredExamples.length === 0">No matching examples</p>
</template>
</div>
</div>
</template>
<style scoped>
.example-layout {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
grid-template-areas:
'search'
'results';
gap: 16px;
}
@media only screen and (min-width: 720px) {
.example-layout {
grid-template-columns: 256px 1fr;
grid-template-rows: auto 1fr;
grid-template-areas:
'filters search'
'filters results';
}
}
.search {
grid-area: search;
background: var(--vp-c-bg-soft);
padding: 20px;
width: 100%;
display: flex;
border-radius: 16px;
}
.filters {
display: none;
grid-area: filters;
}
@media only screen and (min-width: 720px) {
.filters {
display: flex;
flex-direction: column;
gap: 2px;
border-radius: 16px;
overflow: hidden;
align-self: flex-start;
}
}
.results {
grid-area: results;
}
.box {
border-radius: 16px;
overflow: hidden;
}
.search input {
min-width: 0;
flex: 1;
font-size: 16px;
}
.checkbox-col {
flex: 1;
padding: 16px;
display: flex;
flex-direction: column;
overflow-y: auto;
max-height: 200px;
font-size: 14px;
gap: 4px;
}
.filter-btn {
color: var(--vp-c-brand-1);
}
.checkbox-col .header {
font-size: 12px;
font-weight: bold;
opacity: 50%;
}
.checkbox-col p {
display: flex;
gap: 4px;
align-items: flex-start;
text-wrap: wrap;
overflow-wrap: anywhere;
line-height: 140%;
}
span {
padding-top: 1px;
}
.checkbox-col input[type='checkbox'] {
width: 16px;
height: 16px;
flex-shrink: 0;
}
.checkbox-col-container {
display: flex;
}
.search-results {
display: grid;
grid-template-columns: repeat(1, 1fr);
gap: 16px;
}
@media only screen and (min-width: 800px) {
.search-results {
grid-template-columns: repeat(2, 1fr);
}
}
@media only screen and (min-width: 1024px) {
.search-results {
grid-template-columns: repeat(3, 1fr);
}
}
a {
background-color: red;
}
</style>
@@ -0,0 +1,100 @@
<script lang="ts" setup>
import { computed, toRaw } from 'vue';
import { KeySelectedObject } from '../utils/types';
const props = defineProps<{
label: string;
items?: string[];
}>();
const selectedItems = defineModel<KeySelectedObject>({
required: true,
});
const count = computed(() => {
return Object.values(toRaw(selectedItems.value)).filter(Boolean).length;
});
function toggleItem(pkg: string) {
selectedItems.value = {
...toRaw(selectedItems.value),
[pkg]: !selectedItems.value[pkg],
};
}
</script>
<template>
<div class="filter-container">
<p class="header">
<span>Filter by {{ label }}</span> <span v-if="count">({{ count }})</span>
</p>
<div class="scroll-container">
<ul>
<li v-for="item in items">
<label :title="item">
<input
type="checkbox"
:checked="selectedItems[item]"
@input="toggleItem(item)"
/>
<span>{{ item }}</span>
</label>
</li>
</ul>
</div>
</div>
</template>
<style scoped>
.filter-container {
height: 300px;
display: flex;
flex-direction: column;
background: var(--vp-c-bg-soft);
}
.scroll-container {
flex: 1;
overflow: hidden;
position: relative;
}
.scroll-container ul {
position: absolute;
overflow-y: auto;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
gap: 4px;
font-size: small;
padding: 8px 16px 16px 16px;
}
.header {
padding: 8px 16px;
font-size: 12px;
font-weight: bold;
opacity: 50%;
}
label {
display: flex;
gap: 4px;
align-items: flex-start;
text-wrap: wrap;
overflow-wrap: anywhere;
line-height: 140%;
cursor: pointer;
text-wrap: nowrap;
}
span {
padding-top: 1px;
}
input[type='checkbox'] {
width: 16px;
height: 16px;
flex-shrink: 0;
}
</style>
@@ -0,0 +1,72 @@
<script lang="ts" setup>
import { Example } from '../utils/types';
const props = defineProps<{
example: Example;
}>();
</script>
<template>
<li>
<a :href="example.url" target="_blank">
<p class="name">{{ example.name }}</p>
<p class="description">{{ example.description }}</p>
<p class="link">Open &rarr;</p>
</a>
</li>
</template>
<style scoped>
* {
min-width: 0;
}
a {
padding: 16px;
display: flex;
flex-direction: column;
border: 2px solid var(--vp-c-bg-soft);
border-radius: 16px;
color: var(--vp-c-text-1) !important;
gap: 8px;
}
a:hover {
outline: 2px solid var(--vp-c-brand-2);
}
.name {
font-size: 16px;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex-shrink: 0;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.description {
height: 53px;
opacity: 70%;
font-size: 14px;
font-weight: normal;
line-height: 120%;
min-height: 0;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.link {
opacity: 0;
transition: 250ms;
color: var(--vp-c-brand-2);
font-weight: bold;
text-align: right;
}
a:hover .link {
opacity: 100%;
}
</style>
@@ -29,6 +29,15 @@ const chromeExtensionIds = [
'nedcanggplmbbgmlpcjiafgjcpdimpea', // YTBlock - Block any content from YouTube™ 'nedcanggplmbbgmlpcjiafgjcpdimpea', // YTBlock - Block any content from YouTube™
'oadbjpccljkplmhnjekgjamejnbadlne', // demo.fun - Interactive product demos that convert 'oadbjpccljkplmhnjekgjamejnbadlne', // demo.fun - Interactive product demos that convert
'iopdafdcollfgaoffingmahpffckmjni', // SmartEReply: Elevate Your LinkedIn™ Engagement with AI 🚀📈 'iopdafdcollfgaoffingmahpffckmjni', // SmartEReply: Elevate Your LinkedIn™ Engagement with AI 🚀📈
'khjdmjcmpolknpccmaaipmidphjokhdf', // WorkFlowy MultiFlow
'fencadnndhdeggodopebjgdfdlhcimfk', // 香草布丁🌿🍮- https://github.com/Xdy1579883916/vanilla-pudding
'bnacincmbaknlbegecpioobkfgejlojp', // MaxFocus: Link Preview
'bcpgdpedphodjcjlminjbdeejccjbimp', // 汇率转换-中文版本
'loeilaonggnalkaiiaepbegccilkmjjp', // Currency Converter Plus
'npcnninnjghigjfiecefheeibomjpkak', // Respond Easy
'cfkdcideecefncbglkhneoflfnmhoicc', // mindful - stay focused on your goals
'lnhejcpclabmbgpiiomjbhalblnnbffg', // 1Proompt
'fonflmjnjbkigocpoommgmhljdpljain', // NiceTab - https://github.com/web-dahuyou/NiceTab
]; ];
const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds); const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds);
+5 -2
View File
@@ -78,7 +78,6 @@ export default defineConfig({
menuItem('Configuration', 'configuration'), menuItem('Configuration', 'configuration'),
menuItem('Entrypoints', 'entrypoints'), menuItem('Entrypoints', 'entrypoints'),
menuItem('Assets', 'assets'), menuItem('Assets', 'assets'),
menuItem('Testing', 'testing'),
menuItem('Publishing', 'publishing'), menuItem('Publishing', 'publishing'),
menuItem('Migrate to WXT', 'migrate-to-wxt'), menuItem('Migrate to WXT', 'migrate-to-wxt'),
menuItem('Compare', 'compare'), menuItem('Compare', 'compare'),
@@ -122,6 +121,7 @@ export default defineConfig({
// Files // Files
menuItem('.env', 'env'), menuItem('.env', 'env'),
menuItem('app.config.ts', 'app-config'),
menuItem('package.json', 'package'), menuItem('package.json', 'package'),
menuItem('tsconfig.json', 'tsconfig'), menuItem('tsconfig.json', 'tsconfig'),
menuItem('web-ext.config.ts', 'web-ext-config'), menuItem('web-ext.config.ts', 'web-ext-config'),
@@ -142,9 +142,12 @@ export default defineConfig({
menuItem('Custom Events', 'custom-events'), menuItem('Custom Events', 'custom-events'),
menuItem('Reusable Modules', 'reusable-modules'), menuItem('Reusable Modules', 'reusable-modules'),
menuItem('Remote Code', 'remote-code'), menuItem('Remote Code', 'remote-code'),
menuItem('Entrypoint Side Effects', 'entrypoint-side-effects'), menuItem('Entrypoint Loaders', 'entrypoint-loaders'),
menuItem('How WXT Works', 'how-wxt-works'), menuItem('How WXT Works', 'how-wxt-works'),
]), ]),
menuGroup('Upgrade Guide', '/guide/upgrade-guide/', [
menuItem('wxt', 'wxt'),
]),
]), ]),
'/api/': menuRoot([ '/api/': menuRoot([
menuGroup('CLI', '/api/cli/', [ menuGroup('CLI', '/api/cli/', [
+2 -2
View File
@@ -2,7 +2,7 @@ import DefaultTheme from 'vitepress/theme';
import Icon from '../components/Icon.vue'; import Icon from '../components/Icon.vue';
import EntrypointPatterns from '../components/EntrypointPatterns.vue'; import EntrypointPatterns from '../components/EntrypointPatterns.vue';
import UsingWxtSection from '../components/UsingWxtSection.vue'; import UsingWxtSection from '../components/UsingWxtSection.vue';
import ExampleList from '../components/ExampleList.vue'; import ExampleSearch from '../components/ExampleSearch.vue';
import './custom.css'; import './custom.css';
export default { export default {
@@ -11,6 +11,6 @@ export default {
ctx.app.component('Icon', Icon); ctx.app.component('Icon', Icon);
ctx.app.component('EntrypointPatterns', EntrypointPatterns); ctx.app.component('EntrypointPatterns', EntrypointPatterns);
ctx.app.component('UsingWxtSection', UsingWxtSection); ctx.app.component('UsingWxtSection', UsingWxtSection);
ctx.app.component('ExampleList', ExampleList); ctx.app.component('ExampleSearch', ExampleSearch);
}, },
}; };
+18
View File
@@ -0,0 +1,18 @@
export interface Example {
name: string;
description?: string;
url: string;
searchText: string;
apis: string[];
permissions: string[];
packages: string[];
}
export type ExamplesMetadata = {
examples: Example[];
allApis: string[];
allPermissions: string[];
allPackages: string[];
};
export type KeySelectedObject = Record<string, boolean | undefined>;
+16 -4
View File
@@ -1,7 +1,19 @@
# Examples ---
layout: page
---
Simple walkthroughs to accomplish common tasks or patterns with WXT. <style>
.examples-container {
padding: 32px;
}
</style>
<ExampleList /> <div class="examples-container">
<div class="vp-doc">
<h1>Examples</h1>
</div>
> Full code available at [`wxt-dev/wxt-examples`](https://github.com/wxt-dev/wxt-examples) <br />
<ExampleSearch />
</div>
+41 -27
View File
@@ -4,30 +4,44 @@ Lets compare the features of WXT vs [Plasmo](https://docs.plasmo.com/framework)
## Overview ## Overview
| Features | WXT | Plasmo | CRXJS | | Features | WXT | Plasmo | CRXJS |
| ---------------------------------------------------- | :-------------------------: | :--------------------------------------: | :---------------------------------------------------------------------: | | ---------------------------------------------------- | :--------------: | :-------------: | :--------------: |
| Supports all browsers | ✅ | | ❌ See [#56](https://github.com/crxjs/chrome-extension-tools/issues/56) | | Supports all browsers | ✅ || 🟡 <sup>10</sup> |
| MV2 Support | ✅ | | 🟡 Either MV2 or MV3 | | MV2 Support | ✅ || 🟡 <sup>1</sup> |
| MV3 Support | ✅ | | 🟡 Either MV2 or MV3 | | MV3 Support | ✅ || 🟡 <sup>1</sup> |
| Create Extension ZIPs | | ✅ | ❌ | | Create Extension ZIPs | | ✅ | ❌ |
| Create Firefox Sources ZIP | | ❌ | ❌ | | Create Firefox Sources ZIP | | ❌ | ❌ |
| First-class TypeScript support | | ✅ | ✅ | | First-class TypeScript support | | ✅ | ✅ |
| Entrypoint discovery | File based | File based | ❌ | | Entrypoint discovery | ✅ <sup>2</sup> | ✅ <sup>2</sup> | ❌ |
| Inline entrypoint config | ✅ | | Manifest based | | Inline entrypoint config | ✅ || ❌ <sup>9</sup> |
| Auto-imports | | ❌ | ❌ | | Auto-imports | | ❌ | ❌ |
| Supports all frontend frameworks | ✅ | 🟡 Only React, Vue, and Svelte | ✅ | | Supports all frontend frameworks | ✅ | 🟡 <sup>3</sup> | ✅ |
| Framework specific entrypoints (like `Popup.tsx`) | 🟡 `.html` `.ts` `.tsx` | ✅ `.html` `.ts` `.tsx` `.vue` `.svelte` | ❌ | | Framework specific entrypoints (like `Popup.tsx`) | 🟡 <sup>4</sup> | ✅ <sup>5</sup> | ❌ |
| Automated publishing | | ✅ | ❌ | | Automated publishing | | ✅ | ❌ |
| Remote Code Bundling (Google Analytics) | | ✅ | ❌ | | Remote Code Bundling (Google Analytics) | | ✅ | ❌ |
| <strong style="opacity: 50%">Dev Mode</strong> | | | | <strong style="opacity: 50%">Dev Mode</strong> | | |
| `.env` Files | | ✅ | ✅ | | `.env` Files | | ✅ | ✅ |
| Opens browser and install extension | | ❌ | ❌ | | Opens browser with extension installed | | ❌ | ❌ |
| HMR for UIs | ✅ | 🟡 React only | ✅ | | HMR for UIs | ✅ | 🟡 <sup>6</sup> | ✅ |
| Reload HTML Files on Change | ✅ | 🟡 Reloads entire extension | ✅ | | Reload HTML Files on Change | ✅ | 🟡 <sup>7</sup> | ✅ |
| Reload Content Scripts on Change | ✅ | 🟡 Reloads entire extension | ✅ | | Reload Content Scripts on Change | ✅ | 🟡 <sup>7</sup> | ✅ |
| Reload Background on Change | 🟡 Reloads entire extension | 🟡 Reloads entire extension | 🟡 Reloads entire extension | | Reload Background on Change | 🟡 <sup>7</sup> | 🟡 <sup>7</sup> | 🟡 <sup>7</sup> |
| Respects Content Script `run_at` | ✅ | ✅ | ❌ ESM-style loaders run asynchronously | | Respects Content Script `run_at` | ✅ | ✅ | ❌ <sup>8</sup> |
| <strong style="opacity: 50%">Built-in Utils</strong> | | | | | <strong style="opacity: 50%">Built-in Utils</strong> | | | |
| Storage | ✅ | | ❌ | | Storage | ✅ || ❌ <sup>11</sup> |
| Messaging | ❌ | ✅ | ❌ | | Messaging | ❌ <sup>11</sup> | ✅ | ❌ <sup>11</sup> |
| Content Script UI | ✅ | | ❌ | | Content Script UI | ✅ || ❌ <sup>11</sup> |
<small>
<sup>1</sup>: Either MV2 or MV3, not both.
<br/><sup>2</sup>: File based.
<br/><sup>3</sup>: Only React, Vue, and Svelte.
<br/><sup>4</sup>: <code>.html</code> <code>.ts</code> <code>.tsx</code>.
<br/><sup>5</sup>: <code>.html</code> <code>.ts</code> <code>.tsx</code>. <code>.vue</code> <code>.svelte</code>.
<br/><sup>6</sup>: React only.
<br/><sup>7</sup>: Reloads entire extension.
<br/><sup>8</sup>: ESM-style loaders run asynchronously.
<br/><sup>9</sup>: Entrypoint options all configured in `manifest.json`.
<br/><sup>10</sup>: As of <code>v2.0.0-beta.23</code>, but v2 stable hasn't been released yet.
<br/><sup>11</sup>: There is no built-in wrapper around this API. However, you can still access the standard APIs via <code>chrome</code>/<code>browser</code> globals or use any 3rd party NPM package.
</small>
+1 -1
View File
@@ -17,7 +17,7 @@ In WXT, you create an entrypoint by adding a file to the `entrypoints/` director
Some entrypoint filesname patterns are reserved by WXT and effect how the manifest is generated. Some entrypoint filesname patterns are reserved by WXT and effect how the manifest is generated.
- `popup` adds a `action` to the manifest - `popup` adds an `action` to the manifest
- `background` adds a background script/service worker - `background` adds a background script/service worker
- `*.content.ts` adds a content script - `*.content.ts` adds a content script
- ... - ...
+9 -3
View File
@@ -15,7 +15,14 @@ npx wxt@latest init <project-name>
``` ```
```sh [bun] ```sh [bun]
bunx wxt@latest init <project-name> # The "wxt init" command currently fails when ran with bunx.
# Use NPX as a workaround, and select "bun" as your package
# manager. To stay up to date with this issue, follow
# https://github.com/wxt-dev/wxt/issues/707
#
# bunx wxt@latest init <project-name>
npx wxt@latest init <project-name>
``` ```
::: :::
@@ -96,7 +103,6 @@ pnpm dev
``` ```
:::tip 🎉&ensp;Well done! :::tip 🎉&ensp;Well done!
The dev command will build the extension for development, open the browser, and reload the different parts of the extension when you save changes. The dev command will build the extension for development, open the browser, and reload the different parts of the extension when you save changes.
::: :::
@@ -107,4 +113,4 @@ You're ready to build your web extension!
- Read the rest of the "Get Started" pages for a high-overview of what WXT can do - Read the rest of the "Get Started" pages for a high-overview of what WXT can do
- Read the [Guide](/guide/key-concepts/manifest) to learn in-depth about each feature WXT supports - Read the [Guide](/guide/key-concepts/manifest) to learn in-depth about each feature WXT supports
- [Configure WXT](./configuration) by creating a `wxt.config.ts` file - [Configure WXT](./configuration) by creating a `wxt.config.ts` file
- Checkout [example projects](https://github.com/wxt-dev/wxt-examples) to see how to perform common tasks with WXT - Checkout [example projects](https://github.com/wxt-dev/examples) to see how to perform common tasks with WXT
+1 -1
View File
@@ -11,7 +11,7 @@ head:
WXT is a free and open source framework for building web extensions in an conventional, intuitive, and safe way **_for all browsers_**. WXT is a free and open source framework for building web extensions in an conventional, intuitive, and safe way **_for all browsers_**.
WXT is based of [Nuxt](https://nuxt.com), and aims to provide the same great DX with TypeScript, auto-imports, and an opinionated project structure. WXT is based on [Nuxt](https://nuxt.com), and aims to provide the same great DX with TypeScript, auto-imports, and an opinionated project structure.
![Example build output](../assets/cli-output.png) ![Example build output](../assets/cli-output.png)
+1 -1
View File
@@ -25,7 +25,7 @@ In general, you'll need to:
&ensp;<input type="checkbox" /> Convert custom import syntax to be compatible with Vite<br /> &ensp;<input type="checkbox" /> Convert custom import syntax to be compatible with Vite<br />
&ensp;<input type="checkbox" /> Add a default export to JS entrypoints<br /> &ensp;<input type="checkbox" /> Add a default export to JS entrypoints<br />
&ensp;<input type="checkbox" /> Use the `browser` global instead of `chrome`<br /> &ensp;<input type="checkbox" /> Use the `browser` global instead of `chrome`<br />
&ensp;<input type="checkbox" /> Compare final `manifest.json` files, making sure permissions and host permissions are unchanged<br /> &ensp;<input type="checkbox" /> Compare final `manifest.json` files, making sure permissions and host permissions are unchanged. Use [Google's update testing tool](https://github.com/GoogleChromeLabs/extension-update-testing-tool) if your extension is already live on the Chrome Web Store<br />
&ensp;<input type="checkbox" /> Extension output by `wxt build` works the same way as before the migration<br /> &ensp;<input type="checkbox" /> Extension output by `wxt build` works the same way as before the migration<br />
Every project is different, so there's no one-solution-fits-all to migrating your project. Just make sure `wxt dev` runs, `wxt build` results in a working extension, and the list of permissions in the `manifest.json` hasn't changed. If all that looks good, you've finished migrating your extension! Every project is different, so there's no one-solution-fits-all to migrating your project. Just make sure `wxt dev` runs, `wxt build` results in a working extension, and the list of permissions in the `manifest.json` hasn't changed. If all that looks good, you've finished migrating your extension!
+2 -2
View File
@@ -176,6 +176,8 @@ bun zip:firefox
::: :::
Ensure that you have a `README.md` or `SOURCE_CODE_REVIEW.md` file with the above commands so that the Firefox team knows how to build your extension.
Make sure the build output is the exact same when running `wxt build -b firefox` in your main project and inside the zipped sources. Make sure the build output is the exact same when running `wxt build -b firefox` in your main project and inside the zipped sources.
:::warning :::warning
@@ -184,8 +186,6 @@ If you use a `.env` files, they can effect the chunk hashes in the output direct
See Issue [#377](https://github.com/wxt-dev/wxt/issues/377) for more details. See Issue [#377](https://github.com/wxt-dev/wxt/issues/377) for more details.
::: :::
Ensure that you have a `README.md` or `SOURCE_CODE_REVIEW.md` file with the above commands so that the Firefox team knows how to build your extension.
#### Private Packages #### Private Packages
If you use private packages and you don't want to provide your auth token to the Firefox team during the review process, you can use `zip.downloadPackages` to download any private packages and include them in the zip. If you use private packages and you don't want to provide your auth token to the Firefox team during the review process, you can use `zip.downloadPackages` to download any private packages and include them in the zip.
-25
View File
@@ -1,25 +0,0 @@
# Testing
## Official Frameworks
WXT officially supports [Vitest](https://vitest.dev/) for unit tests and either [Playwright](https://playwright.dev/) or [Puppeteer](https://pptr.dev/) for E2E tests against Chromium browsers.
For details setting up each testing framework, see the official examples:
<ExampleList tag="testing" />
## Unofficial Frameworks
Puppeteer and Playwright are the only E2E test runners that support Chrome Extensions. There are no other options at the time of writing.
There are other options for unit tests however, like [Jest](https://jestjs.io/), [Mocha](https://mochajs.org/), or [`node:test`](https://nodejs.org/api/test.html). **_WXT does not claim to support any of them_** because none of them support all of WXT's features, like TypeScript or auto-imports.
If you want to try to use a different framework for unit tests, you will need to configure the environment manually:
- **Auto-imports**: Add `unimport` to your test environment or disable them by setting `imports: false` in your `wxt.config.ts` file
- **`browser` mock**: Mock the `webextension-polyfill` module globally with `wxt/dist/virtual/mock-browser.js`
- **[Remote Code Bundling](/guide/go-further/remote-code)**: If you use it, configure your environment to handle the `url:` module prefix
- **Global Variables**: If you consume them, manually define globals provided by WXT (like `import.meta.env.BROWSER`) by adding them to the global scope before accessing them (`import.meta.env.BROWSER = "chrome"`)
- **Import paths**: If you use the `@/` or `~/` path aliases, add them to your test environment
[Here's how Vitest is configured](https://github.com/wxt-dev/wxt/blob/main/packages/wxt/src/testing/wxt-vitest-plugin.ts) for reference.
@@ -0,0 +1,61 @@
# `<srcDir>/app.config.ts`
:::warning Nuxt Users
If you're familiar with Nuxt, this file is meant to be a direct equivalent to Nuxt's `app.config.ts` file.
However, some of Nuxt's features, like overriding the app config based on a `.env` file or automatically generating the config's types, are not implemented. They are planned, just not implemented yet. Feel free to open a PR!
:::
## Overview
Define runtime configuration in a single place.
```ts
// <srcDir>/app.config.ts
import { defineAppConfig } from 'wxt/sandbox';
// Define types for your config
declare module 'wxt/sandbox' {
export interface WxtAppConfig {
theme?: 'light' | 'dark';
}
}
export default defineAppConfig({
theme: 'dark',
});
```
Then access the config in your extension by calling `useAppConfig`:
```ts
console.log(useAppConfig()); // { theme: "dark" }
```
## Environment Variables
If you have a `.env` file, you can access any variables defined in it here. You can convert them to better types (like booleans), add types for them, or leave them as is.
```txt
# .env
VITE_BUG_REPORTING_DISABLED=true
VITE_API_KEY=...
```
```ts
// <srcDir>/app.config.ts
declare module 'wxt/sandbox' {
export interface WxtAppConfig {
bugReportingDisabled: boolean;
apiKey?: string;
}
}
export default defineAppConfig({
bugReportingDisabled: import.meta.env.VITE_BUG_REPORTING_DISABLED === 'true',
apiKey: import.meta.env.VITE_API_KEY,
});
```
> You don't have to do this, you can use `import.meta.env.VITE_*` anywhere in your runtime code, but putting them here consolidates them to one place and defines what variables are expected.
@@ -37,4 +37,4 @@ Chrome extensions allow you to add panels and side panes to the devtools window.
See the WXT's examples for a full walkthrough of extending the devtools window: See the WXT's examples for a full walkthrough of extending the devtools window:
<ExampleList tag="devtools" /> - [Devtools Setup](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vanilla-devtools#readme)
@@ -12,8 +12,8 @@ Firefox does not support sandboxed pages.
:patterns="[ :patterns="[
['sandbox.html', 'sandbox.html'], ['sandbox.html', 'sandbox.html'],
['sandbox/index.html', 'sandbox.html'], ['sandbox/index.html', 'sandbox.html'],
['<name>.sandbox.html', '<name>.html` '], ['<name>.sandbox.html', '<name>.html'],
['<name>.sandbox/index.html', '<name>.html` '], ['<name>.sandbox/index.html', '<name>.html'],
]" ]"
/> />
+38 -6
View File
@@ -121,7 +121,7 @@ Storage items contain the same APIs as the `storage` variable, but you can confi
const showChangelogOnUpdate = storage.defineItem<boolean>( const showChangelogOnUpdate = storage.defineItem<boolean>(
'local:showChangelogOnUpdate', 'local:showChangelogOnUpdate',
{ {
defaultValue: true, fallback: true,
}, },
); );
``` ```
@@ -153,7 +153,7 @@ type IgnoredWebsiteV1 = string;
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV1[]>( export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV1[]>(
'local:ignoredWebsites', 'local:ignoredWebsites',
{ {
defaultValue: [], fallback: [],
version: 1, version: 1,
}, },
); );
@@ -173,7 +173,7 @@ export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV1[]>( // [!code
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( // [!code ++] export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( // [!code ++]
'local:ignoredWebsites', 'local:ignoredWebsites',
{ {
defaultValue: [], fallback: [],
version: 1, // [!code --] version: 1, // [!code --]
version: 2, // [!code ++] version: 2, // [!code ++]
migrations: { // [!code ++] migrations: { // [!code ++]
@@ -205,7 +205,7 @@ export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( // [!code
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV3[]>( // [!code ++] export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV3[]>( // [!code ++]
'local:ignoredWebsites', 'local:ignoredWebsites',
{ {
defaultValue: [], fallback: [],
version: 2, // [!code --] version: 2, // [!code --]
version: 3, // [!code ++] version: 3, // [!code ++]
migrations: { migrations: {
@@ -242,7 +242,7 @@ Lets look at the same ignored websites example from before, but start with an un
export const ignoredWebsites = storage.defineItem<string[]>( export const ignoredWebsites = storage.defineItem<string[]>(
'local:ignoredWebsites', 'local:ignoredWebsites',
{ {
defaultValue: [], fallback: [],
}, },
); );
``` ```
@@ -262,7 +262,7 @@ export const ignoredWebsites = storage.defineItem<string[]>( // [!code --]
export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( // [!code ++] export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( // [!code ++]
'local:ignoredWebsites', 'local:ignoredWebsites',
{ {
defaultValue: [], fallback: [],
version: 2, // [!code ++] version: 2, // [!code ++]
migrations: { // [!code ++] migrations: { // [!code ++]
// Ran when migrating from v1 to v2 // [!code ++] // Ran when migrating from v1 to v2 // [!code ++]
@@ -279,3 +279,35 @@ export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( // [!code
### Running Migrations ### Running Migrations
As soon as `storage.defineItem` is called, WXT checks if migrations need to be ran, and if so, runs them. Calls to get or update the storage item's value or metadata (`getValue`, `setValue`, `removeValue`, `getMeta`, etc) will automatically wait for the migration process to finish before actually reading or writing values. As soon as `storage.defineItem` is called, WXT checks if migrations need to be ran, and if so, runs them. Calls to get or update the storage item's value or metadata (`getValue`, `setValue`, `removeValue`, `getMeta`, etc) will automatically wait for the migration process to finish before actually reading or writing values.
### Default Values
With `storage.defineItem`, there are multiple ways of defining default values:
1. `fallback` - Return this value from `getValue` instead of `null` if the value is missing.
This option is great for providing default values for settings:
```ts
const theme = storage.defineItem('local:theme', {
fallback: 'dark',
});
const allowEditing = storage.defineItem('local:allow-editing', {
fallback: true,
});
```
2. `init` - Initialize and save a value in storage if it is not already saved.
This is great for values that need to be initialized or set once:
```ts
const userId = storage.defineItem('local:user-id', {
init: () => globalThis.crypto.randomUUID(),
});
const installDate = storage.defineItem('local:install-date', {
init: () => new Date().getTime(),
});
```
The value is initialized in storage immediately.
+120
View File
@@ -0,0 +1,120 @@
# Entrypoint Loaders
Because entrypoint options, like content script `matches`, are listed in the entrypoint's JS file, WXT has to import them during the build process to use those options when generating the manifest.
There are two options for loading your entrypoints:
1. `vite-node` - default as of `v0.19.0`
2. `jiti` (**DEPRECATED, will be removed in `v0.20.0`**) - Default before `v0.19.0`
## vite-node
Since 0.19.0, WXT uses `vite-node`, the same tool that powers Vitest and Nuxt, to import your entrypoint files.
If you use any runtime packages that depend on `webextension-polyfill`, you need to add them to [Vite's `ssr.noExternal` option](https://vitejs.dev/config/ssr-options#ssr-noexternal):
```ts
export default defineConfig({
vite: () => ({
ssr: {
noExternal: ['@webext-core/messaging', '@webext-core/proxy-service'],
},
}),
});
```
:::details Why?
This tells Vite it needs process these module's, letting WXT properly disable the polyfill in the NodeJS environment so it doesn't cause any build errors like this:
```
ERROR This script should only be loaded in a browser extension
```
:::
To get a list of installed packages that use on `webextension-polyfill`, run your package manager's `list` command. Here's an example with PNPM:
```sh
$ pnpm why webextension-polyfill
dependencies:
@webext-core/messaging 1.4.0
└── webextension-polyfill 0.10.0
@webext-core/proxy-service 1.2.0
├─┬ @webext-core/messaging 1.4.0 peer
│ └── webextension-polyfill 0.10.0
└── webextension-polyfill 0.12.0 peer
devDependencies:
@wxt-dev/module-vue 1.0.0
└─┬ wxt 0.19.0-alpha1 peer
└── webextension-polyfill 0.12.0
webextension-polyfill 0.12.0
wxt 0.19.0-alpha1
└── webextension-polyfill 0.12.0
```
Ignoring WXT itself (it's added automatically for you), there are three packages that depend on the polyfill: `@wxt-dev/module-vue`, `@webext-core/messaging`, and `@webext-core/proxy-service`. Since the vue module is a build dependency, with no runtime code, you don't have to add it. That means for this case, you need to add `@webext-core/messaging`, and `@webext-core/proxy-service`, as shown in the original code snippet.
## jiti
The original method WXT used to import TS files. However, because it doesn't support vite plugins like `vite-node`, there is one main caveot to it's usage: **_module side-effects_**.
To enable `jiti`:
```ts
export default defineConfig({
entrypointLoader: 'jiti',
});
```
You cannot use imported variables outside the `main` function in JS entrypoints. This includes options, as shown below:
```ts
// entrypoints/content.ts
import { GOOGLE_MATCHES } from '~/utils/match-patterns';
export default defineContentScript({
matches: GOOGLE_MATCHES,
main() {
// ...
},
});
```
```
$ wxt build
wxt build
WXT 0.14.1
Building chrome-mv3 for production with Vite 5.0.5
✖ Command failed after 360 ms
[8:55:54 AM] ERROR entrypoints/content.ts: Cannot use imported variable "GOOGLE_MATCHES" before main function. See https://wxt.dev/guide/entrypoints.html#side-effects
```
This throws an error because WXT needs to import each entrypoint during the build process to extract its definition (containing the `match`, `runAt`, `include`/`exclude`, etc.) to render the `manifest.json` correctly. Before loading an entrypoint, a transformation is applied to remove all imports. This prevents imported modules (local or NPM) with side-effects from running during the build process, potentially throwing an error.
:::details Why?
When importing your entrypoint to get its definition, the file is imported in a **_node environment_**, and doesn't have access to the `window`, `chrome`, or `browser` globals a web extension usually has access to. If WXT doesn't remove all the imports from the file, the imported modules could try and access one of these variables, throwing an error.
:::
:::warning
See [`wxt-dev/wxt#336`](https://github.com/wxt-dev/wxt/issues/336) to track the status of this bug.
:::
Usually, this error occurs when you try to extract options into a shared file or try to run code outside the `main` function. To fix the example from above, use literal values when defining an entrypoint instead of importing them:
```ts
import { GOOGLE_MATCHES } from '~/utils/match-patterns'; // [!code --]
export default defineContentScript({
matches: GOOGLE_MATCHES, // [!code --]
matches: ['*//*.google.com/*'], // [!code ++]
main() {
// ...
},
});
```
@@ -1,52 +0,0 @@
# Entrypoint Side Effects
You cannot use imported variables outside the `main` function in JS entrypoints. This includes options, as shown below:
```ts
// entrypoints/content.ts
import { GOOGLE_MATCHES } from '~/utils/match-patterns';
export default defineContentScript({
matches: GOOGLE_MATCHES,
main() {
// ...
},
});
```
```
$ wxt build
wxt build
WXT 0.14.1
Building chrome-mv3 for production with Vite 5.0.5
✖ Command failed after 360 ms
[8:55:54 AM] ERROR entrypoints/content.ts: Cannot use imported variable "GOOGLE_MATCHES" before main function. See https://wxt.dev/guide/entrypoints.html#side-effects
```
This throws an error because WXT needs to import each entrypoint during the build process to extract its definition (containing the `match`, `runAt`, `include`/`exclude`, etc.) to render the `manifest.json` correctly. Before loading an entrypoint, a transformation is applied to remove all imports. This prevents imported modules (local or NPM) with side-effects from running during the build process, potentially throwing an error.
:::details Why?
When importing your entrypoint to get its definition, the file is imported in a **_node environment_**, and doesn't have access to the `window`, `chrome`, or `browser` globals a web extension usually has access to. If WXT doesn't remove all the imports from the file, the imported modules could try and access one of these variables, throwing an error.
:::
:::warning
See [`wxt-dev/wxt#336`](https://github.com/wxt-dev/wxt/issues/336) to track the status of this bug.
:::
Usually, this error occurs when you try to extract options into a shared file or try to run code outside the `main` function. To fix the example from above, use literal values when defining an entrypoint instead of importing them:
```ts
import { GOOGLE_MATCHES } from '~/utils/match-patterns'; // [!code --]
export default defineContentScript({
matches: GOOGLE_MATCHES, // [!code --]
matches: ['*//*.google.com/*'], // [!code ++]
main() {
// ...
},
});
```
+6 -46
View File
@@ -6,7 +6,7 @@ When releasing an update to your extension, there's a couple of things you need
## Content Script Cleanup ## Content Script Cleanup
Old content scripts are not automatically stopped when an extension updates and reloads. Often, this leads to "Invalidated context" errors in production when a content script from an old version of your extension tries to use a web extension API (ie, the `browser` or `chrome` globals). Old content scripts are not automatically stopped when an extension updates and reloads. Often, this leads to "Invalidated context" errors in production when a content script from an old version of your extension tries to use an extension API.
WXT provides a utility for handling this process: `ContentScriptContext`. An instance of this class is provided to you automatically inside the `main` function of each content script. WXT provides a utility for handling this process: `ContentScriptContext`. An instance of this class is provided to you automatically inside the `main` function of each content script.
@@ -51,33 +51,12 @@ This prevents old content scripts from interfering with new content scripts, and
## Testing Permission Changes ## Testing Permission Changes
When `permissions`/`host_permissions` change during an update, depending on what exactly changed, Chrome will disable your extension until the user accepts the new permissions. When `permissions`/`host_permissions` change during an update, depending on what exactly changed, the browser will disable your extension until the user accepts the new permissions.
It is possible to test this before you release an update, but it's not a simple process: You can test if your permission changes will result in a disabled extension:
1. Get 2 ZIPs of your extension, both generated by `wxt zip`. The first contains a previous version of your extension, the second contains the latest version. Make sure the second ZIP's version is higher than the first's. - Chromium: Use [Google's Extension Update Testing tool](https://github.com/GoogleChromeLabs/extension-update-testing-tool)
2. Unzip the two ZIP files somewhere next to each other that's easy to locate. - Firefox/Safari: Everyone breaks something in production eventually... 🫡 Good luck soldier
3. In Chrome, open `chrome://extensions` and make sure developer mode is enabled
4. Pack the first extension into a CRX, generating a new private key:
1. Click "Pack Extension" in the top left
2. For "Extension root directory", enter the path to the first extracted zip directory. The directory should contain a `manifest.json` file
3. Leave "Private key file" blank
4. Click "Pack Extension". This will generate a `.crx` and `.pem` file
5. Pack the second extension into a CRX, reusing the private key generated by the previous step
1. Click "Pack Extension" in the top left
2. For "Extension root directory", enter the path to the second extracted zip directory.
3. For "Private key file", enter the path to the generated `.pem` private key file
4. Click "Pack Extension". This will generate a second `.crx` file.
6. Install the first CRX file by dragging and dropping it onto the `chrome://extensions` page
7. Install the second CRX file by dragging and dropping it onthe the `chrome://extensions` page
If a new permission must be accepted, you'll be prompted to accept it after dropping the second CRX file onto the page.
:::Info Note
Note: Chrome no longer allows self-signed CRX extensions to run, but that's OK for this test case. We're still prompted to accept new permissions, even if we can't interact with the installed extension.
To validate this, you can create a third ZIP file with a rare permission like `geolocation` in the manifest, that's guarenteed to reprompt permissions when added.
:::
## Update Event ## Update Event
@@ -94,23 +73,4 @@ browser.runtime.onInstalled.addListener(({ reason }) => {
If the logic is simple, write a unit test to cover this logic. If you feel the need to manually test this callback, you can either: If the logic is simple, write a unit test to cover this logic. If you feel the need to manually test this callback, you can either:
1. In dev mode, remove the `if` statement and reload the extension from `chrome://extensions` 1. In dev mode, remove the `if` statement and reload the extension from `chrome://extensions`
2. Build two ZIPs with the same runtime ID and actually update the extension 2. Use [Google's Extension Update Testing tool](https://github.com/GoogleChromeLabs/extension-update-testing-tool)
The first approach is very straightforward. The second is more complicated...
Here are the steps:
So the steps:
1. Checkout an old commit.
2. [Add a `key`](https://developer.chrome.com/docs/extensions/reference/manifest/key#keep-consistent-id) to the `manifest` in your `wxt.config.ts`.
3. Run `wxt zip` to create the first ZIP.
4. Stash or reset changes and checkout your latest code.
5. Add back the same `key` to your manifest.
6. Make sure the extension's version is higher than the first zip. It can be any version that's higher, since you won't be releasing this version.
7. Run `wxt zip` to create the second ZIP.
8. In a fresh chrome profile, go to `chrome://extensions`, enable dev mode, and drag and drop the first zip onto the page to install it.
9. In the extension, play around and setup your test case.
10. Back on `chrome://extensions`, drag and drop your second zip onto the page.
If you setup the `key` correctly, it will cause the extension to act like it was updated instead of installing a second version of your extension.
+5 -5
View File
@@ -25,12 +25,12 @@ There are two ways to add a module to your project:
}); });
``` ```
2. **NPM package**: By convention, any package on NPM that starts with `@wxt-dev/module-*` or `wxt-module-*` can be installed and included in your project: 2. **NPM package**: Find WXT modules on NPM and include them in your project:
```ts ```ts
// wxt.config.ts // wxt.config.ts
export default defineConfig({ export default defineConfig({
// Add the module to your project // Add the module to your project
modules: ['wxt-module-example'], modules: ['@wxt-dev/auto-icons'],
}); });
``` ```
@@ -99,9 +99,9 @@ export default defineConfig({
### Actually Doing Something ### Actually Doing Something
The first argument of the setup function, `wxt`, provides full access to the current build's context. You can access the resolved configuration via `wxt.config`, or setup hooks to manipulate the build at different steps of the build process. The first argument of the setup function, `wxt`, provides full access to the current build's context. You can access the resolved configuration via `wxt.config`, or setup hooks to manipulate the build at different steps of the build process with `wxt.hooks`.
Here's an example that shows you how to update the `outDir` based on the build mode. It does a good job showing how to access config, set up a hook, and do something when the hook is called. Here's an example that updates the `outDir` based on the build mode. It's a very simple example of how to access config and setup a hook.
```ts ```ts
export default defineWxtModule((wxt) => { export default defineWxtModule((wxt) => {
@@ -176,7 +176,7 @@ export default defineWxtPlugin(() => {
::: :::
:::warning Async Plugins :::warning Async Plugins
Unlike modules, **_plugins cannot be async_**!! If you need to do some async work and expose that result to the rest of the extension, wrap it in an object and handle awaiting the promise internally. Unlike modules, **_plugins cannot be async_**!! If you need to do some async work and expose that result to the rest of the extension, store the result's promise synchronously and await it later on.
::: :::
## Publishing to NPM ## Publishing to NPM
+4 -2
View File
@@ -6,7 +6,9 @@ WXT officially supports [Vitest](https://vitest.dev/) for unit tests and either
For details setting up each testing framework, see the official examples: For details setting up each testing framework, see the official examples:
<ExampleList tag="testing" /> - [Vitest](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vanilla-vitest#readme)
- [Playwright](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vanilla-playwright#readme)
- [Puppeteer](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vanilla-puppeteer#readme)
### Unofficial Frameworks ### Unofficial Frameworks
@@ -17,7 +19,7 @@ There are other options for unit tests however, like [Jest](https://jestjs.io/),
If you want to try to use a different framework for unit tests, you will need to configure the environment manually: If you want to try to use a different framework for unit tests, you will need to configure the environment manually:
- **Auto-imports**: Add `unimport` to your test environment or disable them by setting `imports: false` in your `wxt.config.ts` file - **Auto-imports**: Add `unimport` to your test environment or disable them by setting `imports: false` in your `wxt.config.ts` file
- **`browser` mock**: Mock the `webextension-polyfill` module globally with `wxt/dist/virtual/mock-browser.js` - **`browser` mock**: Mock the `webextension-polyfill` module globally with `wxt/dist/virtual/mock-browser.mjs`
- **[Remote Code Bundling](/guide/go-further/remote-code)**: If you use it, configure your environment to handle the `url:` module prefix - **[Remote Code Bundling](/guide/go-further/remote-code)**: If you use it, configure your environment to handle the `url:` module prefix
- **Global Variables**: If you consume them, manually define globals provided by WXT (like `import.meta.env.BROWSER`) by adding them to the global scope before accessing them (`import.meta.env.BROWSER = "chrome"`) - **Global Variables**: If you consume them, manually define globals provided by WXT (like `import.meta.env.BROWSER`) by adding them to the global scope before accessing them (`import.meta.env.BROWSER = "chrome"`)
- **Import paths**: If you use the `@/` or `~/` path aliases, add them to your test environment - **Import paths**: If you use the `@/` or `~/` path aliases, add them to your test environment
+7 -3
View File
@@ -18,9 +18,7 @@ export default defineConfig({
## Using Plugins ## Using Plugins
Plugins can be passed into the `vite` configuration in you `wxt.config.ts` file, just like any other option. Plugins can be passed into the `vite` configuration in your `wxt.config.ts` file, just like any other option.
All plugins should work in WXT, but it is worth pointing out that since WXT orchestrates multiple vite builds to bundle an extension, plugins will be executed multiple times if necessary.
```ts ```ts
import { defineConfig } from 'wxt'; import { defineConfig } from 'wxt';
@@ -33,3 +31,9 @@ export default defineConfig({
}), }),
}); });
``` ```
:::warning UNEXPECTED BEHAVIOR
Due to the way WXT orchestrates Vite builds, some plugins may not work as expected. Search [GitHub issues](https://github.com/wxt-dev/wxt/issues?q=is%3Aissue+label%3A%22vite+plugin%22) if you run into issues with a specific plugin.
If one doesn't exist, please open a [new issue](https://github.com/wxt-dev/wxt/issues/new/choose)!
:::
+26 -11
View File
@@ -79,24 +79,39 @@ export default defineConfig({
## ESLint ## ESLint
ESLint doesn't understand auto-imports; it thinks all auto-imported variables are undeclared globals and will report lint errors for each. To fix this, extend the ESLint file generated inside the `.wxt` directory: ESLint doesn't know about the auto-imported variables unless they are explicitly defined in the `globals` config. By default, WXT will generate the config if it detects ESLint is installed in your project. If the config isn't generated automatically, you can manually tell WXT to generate it.
```js
// .eslintrc.js
module.exports = {
extends: ['./.wxt/eslintrc-auto-import.json'],
};
```
By default, this file will be generated when ESLint is a direct dependency. If ESLint is a subdependency or your project is a monorepo, it may not be generated automatically. In this case, you can tell WXT to generate it:
```ts ```ts
// wxt.config.ts // wxt.config.ts
export default defineConfig({ export default defineConfig({
imports: { imports: {
eslintrc: { eslintrc: {
enabled: true, enabled: 8, // Generate ESLint v8 compatible config
// or
enabled: 9, // Generate ESLint v9 compatible config
}, },
}, },
}); });
``` ```
### ESLint 9 and above
WXT supports the "flat config" file format introduced in ESLint 9. Just import the generated file and add it to the array of config to extend.
```js
// eslint.config.mjs
import autoImports from './.wxt/eslint-auto-imports.mjs';
export default [autoImports];
```
### ESLint 8 and below
Just extend the generated file:
```js
// .eslintrc.mjs
export default {
extends: ['./.wxt/eslintrc-auto-import.json'],
};
```
+51 -31
View File
@@ -1,28 +1,59 @@
# Frontend Frameworks # Frontend Frameworks
WXT supports all frontend frameworks with a Vite plugin: ## Built-in Modules
- `@vitejs/plugin-vue` WXT has preconfigured modules for 4 frameworks:
- `@vitejs/plugin-react`
- `@vitejs/plugin-react-swc`
- And more!
Just add the vite plugin to your config and you're good to go! Use the framework in HTML pages or content scripts, it will just work 👍 - [`@wxt-dev/module-react`](https://github.com/wxt-dev/wxt/tree/main/packages/module-react)
- [`@wxt-dev/module-vue`](https://github.com/wxt-dev/wxt/tree/main/packages/module-vue)
- [`@wxt-dev/module-svelte`](https://github.com/wxt-dev/wxt/tree/main/packages/module-svelte)
- [`@wxt-dev/module-solid`](https://github.com/wxt-dev/wxt/tree/main/packages/module-solid)
Install the module for your framework, then add it to your config:
:::code-group :::code-group
```ts [Vue] ```ts [React]
import { defineConfig } from 'wxt'; import { defineConfig } from 'wxt';
import vue from '@vitejs/plugin-vue';
export default defineConfig({ export default defineConfig({
vite: () => ({ modules: ['@wxt-dev/module-react'],
plugins: [vue()],
}),
}); });
``` ```
```ts [React] ```ts [Vue]
import { defineConfig } from 'wxt';
export default defineConfig({
modules: ['@wxt-dev/module-vue'],
});
```
```ts [Svelte]
import { defineConfig } from 'wxt';
export default defineConfig({
modules: ['@wxt-dev/module-svelte'],
});
```
```ts [Solid]
import { defineConfig } from 'wxt';
export default defineConfig({
modules: ['@wxt-dev/module-solid'],
});
```
:::
## Adding Vite Plugins
If your framework doesn't have an official WXT module, no worries! WXT supports any framework with a Vite plugin.
Just add the Vite plugin to your config and you're good to go! Use the framework in HTML pages or content scripts and it will just work 👍
```ts
import { defineConfig } from 'wxt'; import { defineConfig } from 'wxt';
import react from '@vitejs/plugin-react'; import react from '@vitejs/plugin-react';
@@ -33,18 +64,7 @@ export default defineConfig({
}); });
``` ```
```ts [Svelte] The WXT modules just simplify the configuration and add auto-imports. They're not much different than the above.
import { defineConfig } from 'wxt';
import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
vite: () => ({
plugins: [svelte()],
}),
});
```
:::
## Multiple Apps ## Multiple Apps
@@ -75,18 +95,18 @@ Usually, this means each entrypoint should be a directory with it's own files in
├ App.vue ├ App.vue
├ main.ts ├ main.ts
├ style.css ├ style.css
└ rotuer.ts └ router.ts
``` ```
## Configuring Routers ## Configuring Routers
Lots of frameworks come with routers for building a multi-page app using the URL's path. Chrome extensions don't don't work like this. Since HTML files are static, `chrome-extension://{id}/popup.html`, there's no way to change the entire path for routing. Lots of frameworks come with routers for building a multi-page app using the URL's path. Chrome extensions don't don't work like this. Since HTML files are static, `chrome-extension://{id}/popup.html`, there's no way to change the entire path for routing.
Instead, you need to configure the router to run in "hash" mode, where the routing information is apart of the URL's hash, not the path (ie: `popup.html#/` and `popup.html#/account/settings`) Instead, you need to configure the router to run in "hash" mode, where the routing information is apart of the URL's hash, not the path (ie: `popup.html#/` and `popup.html#/account/settings`).
Refer to your router's docs for information about "hash" mode and how to enable it. Here's a non-extensive list of a few popular routers: Refer to your router's docs for information about hash mode and how to enable it. Here's a non-extensive list of a few popular routers:
- [React](https://reactrouter.com/en/main/routers/create-hash-router) - [`react-router`](https://reactrouter.com/en/main/routers/create-hash-router)
- [Vue](https://router.vuejs.org/guide/essentials/history-mode.html#Hash-Mode) - [`vue-router`](https://router.vuejs.org/guide/essentials/history-mode.html#Hash-Mode)
- [Svelte](https://www.npmjs.com/package/svelte-spa-router#hash-based-routing) - [`svelte-spa-router`](https://www.npmjs.com/package/svelte-spa-router#hash-based-routing)
- [Solid](https://github.com/solidjs/solid-router?tab=readme-ov-file#hash-mode-router) - [`solid-router`](https://github.com/solidjs/solid-router?tab=readme-ov-file#hash-mode-router)
+31 -5
View File
@@ -25,7 +25,7 @@ Here's an example `wxt.config.ts` file:
import { defineConfig } from 'wxt'; import { defineConfig } from 'wxt';
export default defineConfig({ export default defineConfig({
mainfest: { manifest: {
action: { action: {
default_title: 'Some Title', default_title: 'Some Title',
}, },
@@ -102,7 +102,7 @@ If a version is not found, a warning is logged and the version defaults to `"0.0
} }
``` ```
### `icons` ## `icons`
By default, WXT will discover icons in your [`public` directory](/guide/directory-structure/public/) and use them for the [manifest's `icons`](https://developer.chrome.com/docs/extensions/mv3/manifest/icons/). By default, WXT will discover icons in your [`public` directory](/guide/directory-structure/public/) and use them for the [manifest's `icons`](https://developer.chrome.com/docs/extensions/mv3/manifest/icons/).
@@ -135,7 +135,7 @@ export default defineConfig({
}); });
``` ```
### Permissions ## Permissions
[Permissions](https://developer.chrome.com/docs/extensions/reference/permissions/) must be listed in the manifest config. [Permissions](https://developer.chrome.com/docs/extensions/reference/permissions/) must be listed in the manifest config.
@@ -147,6 +147,31 @@ export default defineConfig({
}); });
``` ```
## Host Permissions
[Host Permissions](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#host-permissions) must be listed in the manifest config.
```ts
export default defineConfig({
manifest: {
host_permissions: ['*://*.google.com/*'],
},
});
```
:::warning
If you use host permissions and target both MV2 and MV3, make sure to only include the required host permissions for each version:
```ts
export default defineConfig({
manifest: ({ manifestVersion }) => ({
host_permissions: manifestVersion === 2 ? [...] : [...],
}),
});
```
:::
## Localization ## Localization
Similar to the icon, the [`_locales` directory](https://developer.chrome.com/docs/extensions/reference/i18n/) should be placed inside the the WXT's [`public` directory](/guide/directory-structure/public/). Similar to the icon, the [`_locales` directory](https://developer.chrome.com/docs/extensions/reference/i18n/) should be placed inside the the WXT's [`public` directory](/guide/directory-structure/public/).
@@ -176,7 +201,8 @@ export default defineConfig({
See the official localization examples for more details: See the official localization examples for more details:
<ExampleList tag="i18n" /> - [I18n](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vanilla-i18n#readme)
- [Vue I18n](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vue-i18n#readme)
## Actions ## Actions
@@ -228,7 +254,7 @@ The `manifest` option can also be set equal to a function, letting you use logic
```ts ```ts
// wxt.config.ts // wxt.config.ts
export default defineConfig({ export default defineConfig({
manifest: ({ manifestVersion, browser, mode, comamnd }) => { manifest: ({ manifestVersion, browser, mode, command }) => {
return { ... } return { ... }
} }
}) })
@@ -4,7 +4,7 @@
WXT is built on top [`webextension-polyfill` by Mozilla](https://www.npmjs.com/package/webextension-polyfill). The polyfill standardizes much of web extension APIs so they behave the same across different browsers and manifest versions. WXT is built on top [`webextension-polyfill` by Mozilla](https://www.npmjs.com/package/webextension-polyfill). The polyfill standardizes much of web extension APIs so they behave the same across different browsers and manifest versions.
Unlike with Chrome Extension development, which uses a `chrome` global, you need to import the `browser` variable from WXT to use the polyfill: Unlike with Chrome Extension development, which uses a `chrome` global, you need to import the `browser` variable from WXT to access the extension APIs:
```ts ```ts
import { browser } from 'wxt/browser'; import { browser } from 'wxt/browser';
@@ -80,11 +80,11 @@ WXT uses Vite, so all of Vite's `import.meta.env` variables are also available:
Based on the files in your project, WXT will modify some of the polyfill's types to be type-safe. Based on the files in your project, WXT will modify some of the polyfill's types to be type-safe.
For example, `browser.runtime.getURL` will be typed to only allow getting the URL of known files. For example, `browser.runtime.getURL` will be typed to only allow getting the URL of known files. `browser.i18n.getMessage` will only allow getting translations of messages defined in your `public/_locales/<default-locale>/messages.json` file.
## Missing Types ## Missing Types
Some newer APIs that Chrome provides are missing types. But don't worry, the APIs are present at runtime! The polyfill only provides types for standard and stable APIs that work on all browsers, so just be careful when you use them. Some newer APIs that Chrome provides are missing types. Don't worry, the APIs are present at runtime! The polyfill only provides types for standard and stable APIs that work on all browsers, so just be careful when you use them.
If you're using TypeScript, you can use `@ts-expect-error` to ignore any errors when using an API that doesn't have any types. If you're using TypeScript, you can use `@ts-expect-error` to ignore any errors when using an API that doesn't have any types.
+291
View File
@@ -0,0 +1,291 @@
# Upgrading WXT
## Overview
To upgrade WXT to the latest version... just install it!
```sh
pnpm i wxt@latest
```
If there was a major version change, follow the steps below to fix breaking changes.
## v0.18.0 &rarr; v0.19.0
### `vite-node` Entrypoint Loader
The default entrypoint loader has changed to `vite-node`. If you use any NPM packages that depend on the `webextension-polyfill`, you need to add them to Vite's `ssr.noExternal` option:
<!-- prettier-ignore -->
```ts
export default defineConfig({
vite: () => ({ // [!code ++]
ssr: { // [!code ++]
noExternal: ['@webext-core/messaging', '@webext-core/proxy-service'], // [!code ++]
}, // [!code ++]
}), // [!code ++]
});
```
> [Read the full docs](/guide/go-further/entrypoint-loaders#vite-node) for more information.
:::details This change enables:
Importing variables and using them in the entrypoint options:
```ts
// entrypoints/content.ts
import { GOOGLE_MATCHES } from '~/utils/constants'
export default defineContentScript({
matches: [GOOGLE_MATCHES],
main: () => ...,
})
```
Using Vite-specific APIs like `import.meta.glob` to define entrypoint options:
```ts
// entrypoints/content.ts
const providers: Record<string, any> = import.meta.glob('../providers/*', {
eager: true,
});
export default defineContentScript({
matches: Object.values(providers).flatMap(
(provider) => provider.default.paths,
),
async main() {
console.log('Hello content.');
},
});
```
Basically, you can now import and do things outside the `main` function of the entrypoint - you could not do that before. Still though, be careful. It is recommended to avoid running code outside the `main` function to keep your builds fast.
:::
To continue using the old approach, add the following to your `wxt.config.ts` file:
```ts
export default defineConfig({
entrypointLoader: 'jiti', // [!code ++]
});
```
:::warning
`entrypointLoader: "jiti"` is deprecated and will be removed in the next major version.
:::
### Drop CJS Support
WXT no longer ships with Common JS support. If you're using CJS, here's your migration steps:
1. Add [`"type": "module"`](https://nodejs.org/api/packages.html#type) to your `package.json`.
2. Change the file extension of any `.js` files that use CJS syntax to `.cjs`, or update them to use EMS syntax.
Vite also provides steps for migrating to ESM. Check them out for more details: https://vitejs.dev/guide/migration#deprecate-cjs-node-api
## v0.17.0 &rarr; v0.18.0
### Automatic MV3 `host_permissions` to MV2 `permissions`
> Out of an abundance of caution, this change has been marked as a breaking change because permission generation is different.
If you list `host_permissions` in your `wxt.config.ts`'s manifest and have released your extension, double check that your `permissions` and `host_permissions` have not changed for all browsers you target in your `.output/*/manifest.json` files. Permission changes can cause the extension to be disabled on update, and can cause a drop in users, so be sure to double check for differences compared to the previous manifest version.
## v0.16.0 &rarr; v0.17.0
### Storage - `defineItem` Requires `defaultValue` Option
If you were using `defineItem` with versioning and no default value, you will need to add `defaultValue: null` to the options and update the first type parameter:
```ts
const item = storage.defineItem<number>("local:count", { // [!code --]
const item = storage.defineItem<number | null>("local:count", { // [!code ++]
defaultValue: null, // [!code ++]
version: ...,
migrations: ...,
})
```
The `defaultValue` property is now required if passing in the second options argument.
If you exclude the second options argument, it will default to being nullable, as before.
```ts
const item: WxtStorageItem<number | null> =
storage.defineItem<number>('local:count');
const value: number | null = await item.getValue();
```
### Storage - Fix Types In `watch` Callback
> If you don't use TypeScript, this isn't a breaking change, this is just a type change.
```ts
const item = storage.defineItem<number>('local:count', { defaultValue: 0 });
item.watch((newValue: number | null, oldValue: number | null) => { // [!code --]
item.watch((newValue: number, oldValue: number) => { // [!code ++]
// ...
});
```
## v0.15.0 &rarr; v0.16.0
### Output Directory Structure Changed
JS entrypoints in the output directory have been moved. Unless you're doing some kind of post-build work referencing files, you don't have to make any changes.
```
.output/
<target>/
chunks/
some-shared-chunk-<hash>.js
popup-<hash>.js // [!code --]
popup.html
popup.html
popup.js // [!code ++]
```
## v0.14.0 &rarr; v0.15.0
### Renamed `zip.ignoredSources` to `zip.excludeSources`
```ts
// wxt.config.ts
export default defineConfig({
zip: {
ignoredSources: [
/*...*/
], // [!code --]
excludeSources: [
/*...*/
], // [!code ++]
},
});
```
### Renamed Undocumented Constants
Renamed undocumented constants for detecting the build config at runtime in [#380](https://github.com/wxt-dev/wxt/pull/380). Now documented here: https://wxt.dev/guide/multiple-browsers.html#runtime
- `__BROWSER__``import.meta.env.BROWSER`
- `__COMMAND__``import.meta.env.COMMAND`
- `__MANIFEST_VERSION__``import.meta.env.MANIFEST_VERSION`
- `__IS_CHROME__``import.meta.env.CHROME`
- `__IS_FIREFOX__``import.meta.env.FIREFOX`
- `__IS_SAFARI__``import.meta.env.SAFARI`
- `__IS_EDGE__``import.meta.env.EDGE`
- `__IS_OPERA__``import.meta.env.OPERA`
## v0.13.0 &rarr; v0.14.0
### Content Script UI API changes
`createContentScriptUi` and `createContentScriptIframe`, and some of their options, have been renamed:
- `createContentScriptUi({ ... })` &rarr; `createShadowRootUi({ ... })`
- `createContentScriptIframe({ ... })` &rarr; `createIframeUi({ ... })`
- `type: "inline" | "overlay" | "modal"` has been changed to `position: "inline" | "overlay" | "modal"`
- `onRemove` is now called **_before_** the UI is removed from the DOM, previously it was called after the UI was removed
- `mount` option has been renamed to `onMount`, to better match the related option, `onRemove`.
## v0.12.0 &rarr; v0.13.0
### New `wxt/storage` APIs
`wxt/storage` no longer relies on [`unstorage`](https://www.npmjs.com/package/unstorage). Some `unstorage` APIs, like `prefixStorage`, have been removed, while others, like `snapshot`, are methods on the new `storage` object. Most of the standard usage remains the same. See https://wxt.dev/guide/storage and https://wxt.dev/api/reference/wxt/storage/ for more details ([#300](https://github.com/wxt-dev/wxt/pull/300))
## v0.11.0 &rarr; v0.12.0
### API Exports Changed
`defineContentScript` and `defineBackground` are now exported from `wxt/sandbox` instead of `wxt/client`. ([#284](https://github.com/wxt-dev/wxt/pull/284))
- If you use auto-imports, no changes are required.
- If you have disabled auto-imports, you'll need to manually update your import statements:
```ts
import { defineBackground, defineContentScript } from 'wxt/client'; // [!code --]
import { defineBackground, defineContentScript } from 'wxt/sandbox'; // [!code ++]
```
## v0.10.0 &rarr; v0.11.0
### Vite 5
You will need to update any other Vite plugins to a version that supports Vite 5.
## v0.9.0 &rarr; v0.10.0
### Extension Icon Discovery
WXT no longer discovers icons other than `.png` files. If you previously used `.jpg`, `.jpeg`, `.bmp`, or `.svg`, you'll need to convert your icons to `.png` files or manually add them to the manifest inside your `wxt.config.ts` file.
## v0.8.0 &rarr; v0.9.0
### Removed `WebWorker` Types by Default
Removed [`"WebWorker"` types](https://www.typescriptlang.org/tsconfig/lib.html) from `.wxt/tsconfig.json`. These types are useful for MV3 projects using a service worker.
To add them back to your project, add the following to your project's TSConfig:
```json
{
"extends": "./.wxt/tsconfig.json",
"compilerOptions": {
// [!code ++]
"lib": ["ESNext", "DOM", "WebWorker"] // [!code ++]
} // [!code ++]
}
```
## v0.7.0 &rarr; v0.8.0
### `defineUnlistedScript`
Unlisted scripts must now `export default defineUnlistedScript(...)`.
### `BackgroundDefinition` Type
Rename `BackgroundScriptDefintition` to `BackgroundDefinition`.
## v0.6.0 &rarr; v0.7.0
### Content Script CSS Output Location Changed
Content script CSS used to be output to `assets/<name>.css`, but is now `content-scripts/<name>.css` to match the docs.
## v0.5.0 &rarr; v0.6.0
### Require a Function for `vite` Config
The `vite` config option must now be a function. If you were using an object before, change it from `vite: { ... }` to `vite: () => ({ ... })`.
## v0.4.0 &rarr; v0.5.0
### Revert Move Public Directory
Change default `publicDir` to from `<rootDir>/public` to `<srcDir>/public`.
## v0.3.0 &rarr; v0.4.0
### Update Default Path Aliases
Use relative path aliases inside `.wxt/tsconfig.json`.
## v0.2.0 &rarr; v0.3.0
### Move Public Directory
Change default `publicDir` to from `<srcDir>/public` to `<rootDir>/public`.
### Improve Type Safety
Add type safety to `browser.runtime.getURL`.
## v0.1.0 &rarr; v0.2.0
### Rename `defineBackground`
Rename `defineBackgroundScript` to `defineBackground`.
+5
View File
@@ -53,6 +53,11 @@ features:
details: Works with any front-end framework with a Vite plugin. details: Works with any front-end framework with a Vite plugin.
link: /guide/key-concepts/frontend-frameworks link: /guide/key-concepts/frontend-frameworks
linkText: Add a framework linkText: Add a framework
- icon: 📦
title: Modular Architecture
details: Reuse build-time and runtime-code across multiple extensions.
link: /guide/go-further/reusable-modules
linkText: Read docs
- icon: 🖍️ - icon: 🖍️
title: Bootstrap a New Project title: Bootstrap a New Project
details: Get started quickly with several awesome project templates. details: Get started quickly with several awesome project templates.
+5
View File
@@ -2,6 +2,8 @@
# https://docs.netlify.com/routing/redirects/ # https://docs.netlify.com/routing/redirects/
# Old URLs -> New URLs # Old URLs -> New URLs
# OLD
/config.html /api/reference/wxt/interfaces/InlineConfig.html /config.html /api/reference/wxt/interfaces/InlineConfig.html
/api/config.html /api/reference/wxt/interfaces/InlineConfig.html /api/config.html /api/reference/wxt/interfaces/InlineConfig.html
/entrypoints /entrypoints/background.html /entrypoints /entrypoints/background.html
@@ -29,3 +31,6 @@
/guide/build-targets.html /guide/multiple-browsers.html /guide/build-targets.html /guide/multiple-browsers.html
/guide/installation.html /get-started/installation.html /guide/installation.html /get-started/installation.html
/guide/introduction.html /get-started/introduction.html /guide/introduction.html /get-started/introduction.html
# 0.19.0
/guide/go-further/entrypoint-side-effects.html /guide/go-further/entrypoint-loaders.html
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

+15 -18
View File
@@ -2,49 +2,46 @@
"private": true, "private": true,
"type": "module", "type": "module",
"engines": { "engines": {
"node": ">=18.20.3", "node": ">=18.20.3"
"pnpm": "^8.6.3"
}, },
"packageManager": "pnpm@8.15.8", "packageManager": "pnpm@9.6.0",
"scripts": { "scripts": {
"check": "check && pnpm -r --sequential run check", "check": "check && pnpm -r --sequential run check",
"test": "vitest", "test": "pnpm -r --sequential run test run",
"test:coverage": "vitest run --coverage.enabled \"--coverage.include=packages/wxt/src/**\" \"--coverage.exclude=packages/wxt/src/core/utils/testing/**\" \"--coverage.exclude=**/*.d.ts\" \"--coverage.exclude=**/fixtures/**\"", "test:coverage": "pnpm -r --sequential run test:coverage",
"prepare": "simple-git-hooks", "prepare": "simple-git-hooks",
"prepublish": "pnpm -s build", "prepublish": "pnpm -s build",
"docs:gen": "typedoc --options docs/typedoc.json", "docs:gen": "typedoc --options docs/typedoc.json",
"docs:dev": "pnpm -s docs:gen && vitepress dev docs", "docs:dev": "pnpm -s docs:gen && vitepress dev docs",
"docs:build": "pnpm -s docs:gen && vitepress build docs", "docs:build": "pnpm -s docs:gen && vitepress build docs",
"docs:preview": "pnpm -s docs:gen && vitepress preview docs", "docs:preview": "pnpm -s docs:gen && vitepress preview docs"
"build-deps": "pnpm tsx scripts/build-deps.ts"
}, },
"devDependencies": { "devDependencies": {
"@aklinker1/buildc": "^1.0.11",
"@aklinker1/check": "^1.3.1", "@aklinker1/check": "^1.3.1",
"@types/fs-extra": "^11.0.4", "@types/fs-extra": "^11.0.4",
"@vitest/coverage-v8": "^1.6.0", "@vitest/coverage-v8": "^2.0.4",
"changelogen": "^0.5.5", "changelogen": "^0.5.5",
"consola": "^3.2.3", "consola": "^3.2.3",
"dependency-graph": "^1.0.0", "dependency-graph": "^1.0.0",
"execa": "^9.2.0", "execa": "^9.3.0",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"fs-extra": "^11.2.0", "fs-extra": "^11.2.0",
"hasha": "^6.0.0", "hasha": "^6.0.0",
"lint-staged": "^15.2.7", "lint-staged": "^15.2.7",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.3.2", "prettier": "^3.3.3",
"simple-git-hooks": "^2.11.1", "simple-git-hooks": "^2.11.1",
"tsx": "^4.15.4", "tsx": "4.15.7",
"typedoc": "^0.25.4", "typedoc": "^0.25.4",
"typedoc-plugin-markdown": "4.0.0-next.23", "typedoc-plugin-markdown": "4.0.0-next.23",
"typedoc-vitepress-theme": "1.0.0-next.3", "typedoc-vitepress-theme": "1.0.0-next.3",
"typescript": "^5.4.5", "typescript": "^5.5.4",
"vitepress": "^1.2.3", "vitepress": "^1.3.1",
"vitest": "^1.6.0", "vitest-mock-extended": "^2.0.0",
"vitest-mock-extended": "^1.3.1", "vue": "^3.4.34",
"vitest-plugin-random-seed": "^1.1.0",
"vue": "^3.4.27",
"wxt": "workspace:*", "wxt": "workspace:*",
"yaml": "^2.4.5" "yaml": "^2.5.0"
}, },
"simple-git-hooks": { "simple-git-hooks": {
"pre-commit": "pnpm lint-staged" "pre-commit": "pnpm lint-staged"
+34
View File
@@ -0,0 +1,34 @@
# Changelog
## v1.0.2
[compare changes](https://github.com/wxt-dev/wxt/compare/auto-icons-v1.0.1...auto-icons-v1.0.2)
### 📖 Documentation
- **auto-icons:** Fix configuration example typo ([#905](https://github.com/wxt-dev/wxt/pull/905))
### 🏡 Chore
- Add more metadata for npm ([#885](https://github.com/wxt-dev/wxt/pull/885))
### ❤️ Contributors
- Uncenter ([@uncenter](http://github.com/uncenter))
- Florian Metz ([@Timeraa](http://github.com/Timeraa))
## v1.0.1
[compare changes](https://github.com/wxt-dev/wxt/compare/auto-icons-v1.0.0...auto-icons-v1.0.1)
### 🩹 Fixes
- **auto-icons:** Path option ([#880](https://github.com/wxt-dev/wxt/pull/880))
### 🏡 Chore
- **deps:** Upgrade all dependencies ([#869](https://github.com/wxt-dev/wxt/pull/869))
### ❤️ Contributors
- Florian Metz ([@Timeraa](http://github.com/Timeraa))
+42
View File
@@ -0,0 +1,42 @@
# WXT Auto Icons
## Features
- Generate extension icons with the correct sizes
- Make the icon greyscale during development
## Usage
Install the package:
```sh
npm i --save-dev @wxt-dev/auto-icons
pnpm i -D @wxt-dev/auto-icons
yarn add --dev @wxt-dev/auto-icons
bun i -D @wxt-dev/auto-icons
```
Add the module to `wxt.config.ts`:
```ts
export default defineConfig({
modules: ['@wxt-dev/auto-icons'],
});
```
And finally, save the base icon to `<srcDir>/assets/icon.png`.
## Configuration
The module can be configured via the `autoIcons` config:
```ts
export default defineConfig({
modules: ['@wxt-dev/auto-icons'],
autoIcons: {
// ...
},
});
```
Options have JSDocs available in your editor, or you can read them in the source code: [`AutoIconsOptions`](./src/index.ts).
+59
View File
@@ -0,0 +1,59 @@
{
"name": "@wxt-dev/auto-icons",
"description": "WXT module for automatically generating extension icons in different sizes",
"repository": {
"type": "git",
"url": "git+https://github.com/wxt-dev/wxt.git",
"directory": "packages/auto-icons"
},
"homepage": "https://github.com/wxt-dev/wxt/blob/main/packages/auto-icons/README.md",
"keywords": [
"wxt",
"module",
"icons",
"manifest"
],
"author": {
"name": "Florian Metz",
"email": "me@timeraa.dev"
},
"contributors": [
{
"name": "Aaron Klinker",
"email": "aaronklinker1+wxt@gmail.com"
}
],
"license": "MIT",
"version": "1.0.2",
"type": "module",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
}
},
"files": [
"dist"
],
"scripts": {
"build": "buildc -- unbuild",
"check": "pnpm build && check"
},
"peerDependencies": {
"wxt": ">=0.19.0"
},
"devDependencies": {
"@aklinker1/check": "^1.3.1",
"publint": "^0.2.9",
"typescript": "^5.5.4",
"unbuild": "^2.0.0",
"wxt": "workspace:*"
},
"dependencies": {
"defu": "^6.1.4",
"fs-extra": "^11.2.0",
"sharp": "^0.33.4"
}
}
+108
View File
@@ -0,0 +1,108 @@
import 'wxt';
import { defineWxtModule } from 'wxt/modules';
import { resolve, relative } from 'node:path';
import defu from 'defu';
import sharp from 'sharp';
import { ensureDir, exists } from 'fs-extra';
export default defineWxtModule<AutoIconsOptions>({
name: '@wxt-dev/auto-icons',
configKey: 'autoIcons',
async setup(wxt, options) {
const parsedOptions = defu<Required<AutoIconsOptions>, AutoIconsOptions[]>(
options,
{
enabled: true,
baseIconPath: resolve(wxt.config.srcDir, 'assets/icon.png'),
grayscaleOnDevelopment: true,
sizes: [128, 48, 32, 16],
},
);
const resolvedPath = resolve(wxt.config.srcDir, parsedOptions.baseIconPath);
if (!parsedOptions.enabled)
return wxt.logger.warn(`\`[auto-icons]\` ${this.name} disabled`);
if (!(await exists(resolvedPath))) {
return wxt.logger.warn(
`\`[auto-icons]\` Skipping icon generation, no base icon found at ${relative(process.cwd(), resolvedPath)}`,
);
}
wxt.hooks.hook('build:manifestGenerated', async (wxt, manifest) => {
if (manifest.icons)
return wxt.logger.warn(
'`[auto-icons]` icons property found in manifest, overwriting with auto-generated icons',
);
manifest.icons = Object.fromEntries(
parsedOptions.sizes.map((size) => [size, `icons/${size}.png`]),
);
});
wxt.hooks.hook('build:done', async (wxt, output) => {
const image = sharp(resolvedPath).png();
if (
wxt.config.mode === 'development' &&
parsedOptions.grayscaleOnDevelopment
) {
image.grayscale();
}
const outputFolder = wxt.config.outDir;
for (const size of parsedOptions.sizes) {
const resized = image.resize(size);
ensureDir(resolve(outputFolder, 'icons'));
await resized.toFile(resolve(outputFolder, `icons/${size}.png`));
output.publicAssets.push({
type: 'asset',
fileName: `icons/${size}.png`,
});
}
});
wxt.hooks.hook('prepare:publicPaths', (wxt, paths) => {
for (const size of parsedOptions.sizes) {
paths.push(`icons/${size}.png`);
}
});
},
});
/**
* Options for the auto-icons module
*/
export interface AutoIconsOptions {
/**
* Enable auto-icons generation
* @default true
*/
enabled?: boolean;
/**
* Path to the image to use.
*
* Path is relative to the project's src directory.
* @default "<srcDir>/assets/icon.png"
*/
baseIconPath?: string;
/**
* Grayscale the image when in development mode to indicate development
* @default true
*/
grayscaleOnDevelopment?: boolean;
/**
* Sizes to generate icons for
* @default [128, 48, 32, 16]
*/
sizes?: number[];
}
declare module 'wxt' {
export interface InlineConfig {
autoIcons?: AutoIconsOptions;
}
}
+4
View File
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.base.json",
"exclude": ["node_modules/**", "dist/**"]
}
+38
View File
@@ -0,0 +1,38 @@
# Changelog
## v1.1.1
[compare changes](https://github.com/wxt-dev/wxt/compare/module-react-v1.1.0...module-react-v1.1.1)
### 🏡 Chore
- **deps:** Bump all non-major dependencies ([#834](https://github.com/wxt-dev/wxt/pull/834))
- **deps:** Upgrade all dependencies ([#869](https://github.com/wxt-dev/wxt/pull/869))
- Add more metadata for npm ([#885](https://github.com/wxt-dev/wxt/pull/885))
### ❤️ Contributors
- Florian Metz ([@Timeraa](http://github.com/Timeraa))
## v1.1.0
[compare changes](https://github.com/wxt-dev/wxt/compare/module-react-v1.0.0...module-react-v1.1.0)
### 🚀 Enhancements
- Enable auto-imports for JSX/TSX files ([#773](https://github.com/wxt-dev/wxt/pull/773))
### 🩹 Fixes
- Upgrade wxt peer to >= 0.18.6 ([7edf1c8](https://github.com/wxt-dev/wxt/commit/7edf1c8))
- Use `prepare` instead of `postinstall` for local dev setup ([#788](https://github.com/wxt-dev/wxt/pull/788))
### 🏡 Chore
- Add changelog ([21e8ca0](https://github.com/wxt-dev/wxt/commit/21e8ca0))
- Extract build cache script to NPM package ([#737](https://github.com/wxt-dev/wxt/pull/737))
- **deps:** Upgrade non-major deps ([#778](https://github.com/wxt-dev/wxt/pull/778))
## v1.0.0
Initial release 🎉
+12
View File
@@ -0,0 +1,12 @@
import { defineBuildConfig } from 'unbuild';
import { resolve } from 'node:path';
export default defineBuildConfig({
rootDir: 'modules',
outDir: resolve(__dirname, 'dist'),
entries: [{ input: 'react.ts', name: 'index' }],
rollup: {
emitCJS: true,
},
declaration: true,
});
+5
View File
@@ -0,0 +1,5 @@
export default function () {
const [count, setCount] = useState(0);
const increment = () => setCount((count) => count + 1);
return <button onClick={increment}>Count: {count}</button>;
}
@@ -0,0 +1,33 @@
import { defineContentScript } from 'wxt/sandbox';
import { ContentScriptContext, createShadowRootUi } from 'wxt/client';
import React from 'react';
import ReactDOM from 'react-dom/client';
export default defineContentScript({
matches: ['*://*/*'],
async main(ctx) {
const ui = await createUi(ctx);
ui.mount();
},
});
function createUi(ctx: ContentScriptContext) {
return createShadowRootUi(ctx, {
name: 'react-ui',
position: 'inline',
append: 'first',
onMount(container) {
const root = ReactDOM.createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
return root;
},
onRemove(root) {
root?.unmount();
},
});
}
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./main.tsx"></script>
</body>
</html>
@@ -0,0 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
const root = document.getElementById('app')!;
ReactDOM.createRoot(root).render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
@@ -13,6 +13,17 @@ export default defineWxtModule<ReactModuleOptions>({
})); }));
addImportPreset(wxt, 'react'); addImportPreset(wxt, 'react');
// Enable auto-imports for JSX files
wxt.hooks.hook('ready', (wxt) => {
if (wxt.config.imports === false) return;
wxt.config.imports.dirsScanOptions ??= {};
wxt.config.imports.dirsScanOptions.filePatterns = [
// Default plus JSX/TSX
'*.{ts,js,mjs,cjs,mts,cts,jsx,tsx}',
];
});
}, },
}); });
+29 -7
View File
@@ -1,6 +1,23 @@
{ {
"name": "@wxt-dev/module-react", "name": "@wxt-dev/module-react",
"version": "1.0.0", "description": "WXT module to enable React support",
"repository": {
"type": "git",
"url": "git+https://github.com/wxt-dev/wxt.git",
"directory": "packages/module-react"
},
"homepage": "https://github.com/wxt-dev/wxt/blob/main/packages/module-react/README.md",
"keywords": [
"wxt",
"module",
"react"
],
"author": {
"name": "Aaron Klinker",
"email": "aaronklinker1+wxt@gmail.com"
},
"license": "MIT",
"version": "1.1.1",
"type": "module", "type": "module",
"main": "./dist/index.cjs", "main": "./dist/index.cjs",
"module": "./dist/index.mjs", "module": "./dist/index.mjs",
@@ -21,20 +38,25 @@
"dist" "dist"
], ],
"scripts": { "scripts": {
"build": "pnpm -s build-deps && unbuild", "dev": "wxt",
"check": "pnpm -s build-deps && check", "check": "pnpm build && check",
"build-deps": "pnpm -ws build-deps @wxt-dev/module-react" "build": "buildc -- unbuild",
"prepare": "buildc --deps-only -- wxt prepare"
}, },
"peerDependencies": { "peerDependencies": {
"wxt": ">=0.18.5" "wxt": ">=0.18.6"
}, },
"dependencies": { "dependencies": {
"@vitejs/plugin-react": "^4.3.1" "@vitejs/plugin-react": "^4.3.1"
}, },
"devDependencies": { "devDependencies": {
"@aklinker1/check": "^1.3.1", "@aklinker1/check": "^1.3.1",
"publint": "^0.2.8", "@types/react": "^18.3.3",
"typescript": "^5.4.5", "@types/react-dom": "^18.3.0",
"publint": "^0.2.9",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"typescript": "^5.5.4",
"unbuild": "^2.0.0", "unbuild": "^2.0.0",
"wxt": "workspace:*" "wxt": "workspace:*"
} }
View File
+5 -1
View File
@@ -1,4 +1,8 @@
{ {
"extends": "../../tsconfig.base.json", "extends": ["../../tsconfig.base.json", "./.wxt/tsconfig.json"],
"compilerOptions": {
"allowImportingTsExtensions": true,
"jsx": "react-jsx"
},
"exclude": ["node_modules/**", "dist/**"] "exclude": ["node_modules/**", "dist/**"]
} }
+56
View File
@@ -0,0 +1,56 @@
# Changelog
## v1.1.2
[compare changes](https://github.com/wxt-dev/wxt/compare/module-solid-v1.1.1...module-solid-v1.1.2)
### 🏡 Chore
- **deps:** Bump all non-major dependencies ([#834](https://github.com/wxt-dev/wxt/pull/834))
- **deps:** Upgrade all dependencies ([#869](https://github.com/wxt-dev/wxt/pull/869))
- Add more metadata for npm ([#885](https://github.com/wxt-dev/wxt/pull/885))
### ❤️ Contributors
- Florian Metz ([@Timeraa](http://github.com/Timeraa))
## v1.1.1
[compare changes](https://github.com/wxt-dev/wxt/compare/module-solid-v1.1.0...module-solid-v1.1.1)
### 🩹 Fixes
- Use `prepare` instead of `postinstall` for local dev setup ([#788](https://github.com/wxt-dev/wxt/pull/788))
## v1.1.0
[compare changes](https://github.com/wxt-dev/wxt/compare/module-solid-v1.0.1...module-solid-v1.1.0)
### 🚀 Enhancements
- Enable auto-imports for JSX/TSX files ([#773](https://github.com/wxt-dev/wxt/pull/773))
### 🩹 Fixes
- Upgrade wxt peer to >= 0.18.6 ([7edf1c8](https://github.com/wxt-dev/wxt/commit/7edf1c8))
### 🏡 Chore
- Extract build cache script to NPM package ([#737](https://github.com/wxt-dev/wxt/pull/737))
- **deps:** Upgrade non-major deps ([#778](https://github.com/wxt-dev/wxt/pull/778))
## v1.0.1
[compare changes](https://github.com/wxt-dev/wxt/compare/module-solid-v1.0.0...module-solid-v1.0.1)
### 🩹 Fixes
- Add `target: esnext` by default ([#733](https://github.com/wxt-dev/wxt/pull/733))
### 🏡 Chore
- Add changelog ([21e8ca0](https://github.com/wxt-dev/wxt/commit/21e8ca0))
## v1.0.0
Initial release 🎉
+1 -1
View File
@@ -4,7 +4,7 @@ Enables the use of [SolidJS](https://www.solidjs.com/) in your web extension, in
This plugin makes a few changes: This plugin makes a few changes:
1. Adds `vite-plugin-solid` to vite 1. Adds `vite-plugin-solid` to and sets `build.target: esnext` in the vite config
2. Adds the [`solid-js` preset](https://github.com/unjs/unimport/blob/main/src/presets/solid.ts) to auto-imports 2. Adds the [`solid-js` preset](https://github.com/unjs/unimport/blob/main/src/presets/solid.ts) to auto-imports
## Usage ## Usage
+12
View File
@@ -0,0 +1,12 @@
import { defineBuildConfig } from 'unbuild';
import { resolve } from 'node:path';
export default defineBuildConfig({
rootDir: 'modules',
outDir: resolve(__dirname, 'dist'),
entries: [{ input: 'solid.ts', name: 'index' }],
rollup: {
emitCJS: true,
},
declaration: true,
});
+7
View File
@@ -0,0 +1,7 @@
import { Component } from 'solid-js';
export const App: Component = () => {
const [count, setCount] = createSignal(0);
const increment = () => setCount((count) => count + 1);
return <button onClick={increment}>Count: {count()}</button>;
};
@@ -0,0 +1,26 @@
import { defineContentScript } from 'wxt/sandbox';
import { ContentScriptContext, createShadowRootUi } from 'wxt/client';
import { render } from 'solid-js/web';
export default defineContentScript({
matches: ['*://*/*'],
async main(ctx) {
const ui = await createUi(ctx);
ui.mount();
},
});
function createUi(ctx: ContentScriptContext) {
return createShadowRootUi(ctx, {
name: 'solid-ui',
position: 'inline',
append: 'first',
onMount(container) {
return render(() => <App />, container);
},
onRemove(unmount) {
unmount?.();
},
});
}
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./main.tsx"></script>
</body>
</html>
@@ -0,0 +1,5 @@
import { render } from 'solid-js/web';
const root = document.getElementById('app')!;
render(() => <App />, root);
@@ -10,9 +10,23 @@ export default defineWxtModule<SolidModuleOptions>({
addViteConfig(wxt, () => ({ addViteConfig(wxt, () => ({
plugins: [solid(vite)], plugins: [solid(vite)],
build: {
target: 'esnext',
},
})); }));
addImportPreset(wxt, 'solid-js'); addImportPreset(wxt, 'solid-js');
// Enable auto-imports for JSX files
wxt.hooks.hook('ready', (wxt) => {
if (wxt.config.imports === false) return;
wxt.config.imports.dirsScanOptions ??= {};
wxt.config.imports.dirsScanOptions.filePatterns = [
// Default plus JSX/TSX
'*.{ts,js,mjs,cjs,mts,cts,jsx,tsx}',
];
});
}, },
}); });
+26 -7
View File
@@ -1,6 +1,23 @@
{ {
"name": "@wxt-dev/module-solid", "name": "@wxt-dev/module-solid",
"version": "1.0.0", "description": "WXT module to enable SolidJS support",
"repository": {
"type": "git",
"url": "git+https://github.com/wxt-dev/wxt.git",
"directory": "packages/module-solid"
},
"homepage": "https://github.com/wxt-dev/wxt/blob/main/packages/module-solid/README.md",
"keywords": [
"wxt",
"module",
"solidjs"
],
"author": {
"name": "Aaron Klinker",
"email": "aaronklinker1+wxt@gmail.com"
},
"license": "MIT",
"version": "1.1.2",
"type": "module", "type": "module",
"main": "./dist/index.cjs", "main": "./dist/index.cjs",
"module": "./dist/index.mjs", "module": "./dist/index.mjs",
@@ -21,20 +38,22 @@
"dist" "dist"
], ],
"scripts": { "scripts": {
"build": "pnpm -s build-deps && unbuild", "dev": "wxt",
"check": "pnpm -s build-deps && check", "check": "pnpm build && check",
"build-deps": "pnpm -ws build-deps @wxt-dev/module-solid" "build": "buildc -- unbuild",
"prepare": "buildc --deps-only -- wxt prepare"
}, },
"peerDependencies": { "peerDependencies": {
"wxt": ">=0.18.5" "wxt": ">=0.18.6"
}, },
"dependencies": { "dependencies": {
"vite-plugin-solid": "^2.10.2" "vite-plugin-solid": "^2.10.2"
}, },
"devDependencies": { "devDependencies": {
"@aklinker1/check": "^1.3.1", "@aklinker1/check": "^1.3.1",
"publint": "^0.2.8", "publint": "^0.2.9",
"typescript": "^5.4.5", "solid-js": "^1.8.19",
"typescript": "^5.5.4",
"unbuild": "^2.0.0", "unbuild": "^2.0.0",
"wxt": "workspace:*" "wxt": "workspace:*"
} }
View File
+5 -1
View File
@@ -1,4 +1,8 @@
{ {
"extends": "../../tsconfig.base.json", "extends": ["../../tsconfig.base.json", "./.wxt/tsconfig.json"],
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "solid-js"
},
"exclude": ["node_modules/**", "dist/**"] "exclude": ["node_modules/**", "dist/**"]
} }
+31
View File
@@ -0,0 +1,31 @@
# Changelog
## v1.0.1
[compare changes](https://github.com/wxt-dev/wxt/compare/module-svelte-v1.0.0...module-svelte-v1.0.1)
### 🩹 Fixes
- Upgrade wxt peer to >= 0.18.6 ([7edf1c8](https://github.com/wxt-dev/wxt/commit/7edf1c8))
### 📖 Documentation
- Fix link to unimport ([#826](https://github.com/wxt-dev/wxt/pull/826))
### 🏡 Chore
- Add changelog ([21e8ca0](https://github.com/wxt-dev/wxt/commit/21e8ca0))
- Extract build cache script to NPM package ([#737](https://github.com/wxt-dev/wxt/pull/737))
- **deps:** Upgrade non-major deps ([#778](https://github.com/wxt-dev/wxt/pull/778))
- **deps:** Bump all non-major dependencies ([#834](https://github.com/wxt-dev/wxt/pull/834))
- **deps:** Upgrade all dependencies ([#869](https://github.com/wxt-dev/wxt/pull/869))
- Add more metadata for npm ([#885](https://github.com/wxt-dev/wxt/pull/885))
### ❤️ Contributors
- Florian Metz ([@Timeraa](http://github.com/Timeraa))
- Eetann ([@eetann](http://github.com/eetann))
## v1.0.0
Initial release 🎉
+1 -1
View File
@@ -5,7 +5,7 @@ Enables the use of [Svelte](https://svelte.dev/) in your web extension, in HTML
This plugin makes a few changes: This plugin makes a few changes:
1. Adds `@sveltejs/vite-plugin-svelte` to vite 1. Adds `@sveltejs/vite-plugin-svelte` to vite
2. Adds the [`svelte` preset](https://github.com/unjs/unimport/blob/main/src/presets/vue.ts) to auto-imports 2. Adds the [`svelte` preset](https://github.com/unjs/unimport/blob/main/src/presets/svelte.ts) to auto-imports
## Usage ## Usage
+23 -7
View File
@@ -1,6 +1,23 @@
{ {
"name": "@wxt-dev/module-svelte", "name": "@wxt-dev/module-svelte",
"version": "1.0.0", "description": "WXT module to enable Svelte support",
"repository": {
"type": "git",
"url": "git+https://github.com/wxt-dev/wxt.git",
"directory": "packages/module-svelte"
},
"homepage": "https://github.com/wxt-dev/wxt/blob/main/packages/module-svelte/README.md",
"keywords": [
"wxt",
"module",
"svelte"
],
"author": {
"name": "Aaron Klinker",
"email": "aaronklinker1+wxt@gmail.com"
},
"license": "MIT",
"version": "1.0.1",
"type": "module", "type": "module",
"main": "./dist/index.cjs", "main": "./dist/index.cjs",
"module": "./dist/index.mjs", "module": "./dist/index.mjs",
@@ -21,20 +38,19 @@
"dist" "dist"
], ],
"scripts": { "scripts": {
"build": "pnpm -s build-deps && unbuild", "build": "buildc -- unbuild",
"check": "pnpm -s build-deps && check", "check": "pnpm build && check"
"build-deps": "pnpm -ws build-deps @wxt-dev/module-svelte"
}, },
"peerDependencies": { "peerDependencies": {
"wxt": ">=0.18.5" "wxt": ">=0.18.6"
}, },
"dependencies": { "dependencies": {
"@sveltejs/vite-plugin-svelte": "^3.1.1" "@sveltejs/vite-plugin-svelte": "^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"@aklinker1/check": "^1.3.1", "@aklinker1/check": "^1.3.1",
"publint": "^0.2.8", "publint": "^0.2.9",
"typescript": "^5.4.5", "typescript": "^5.5.4",
"unbuild": "^2.0.0", "unbuild": "^2.0.0",
"wxt": "workspace:*" "wxt": "workspace:*"
} }
+26
View File
@@ -0,0 +1,26 @@
# Changelog
## v1.0.1
[compare changes](https://github.com/wxt-dev/wxt/compare/module-vue-v1.0.0...module-vue-v1.0.1)
### 🩹 Fixes
- Upgrade wxt peer to >= 0.18.6 ([7edf1c8](https://github.com/wxt-dev/wxt/commit/7edf1c8))
### 🏡 Chore
- Add changelog ([21e8ca0](https://github.com/wxt-dev/wxt/commit/21e8ca0))
- Extract build cache script to NPM package ([#737](https://github.com/wxt-dev/wxt/pull/737))
- **deps:** Upgrade non-major deps ([#778](https://github.com/wxt-dev/wxt/pull/778))
- **deps:** Bump all non-major dependencies ([#834](https://github.com/wxt-dev/wxt/pull/834))
- **deps:** Upgrade all dependencies ([#869](https://github.com/wxt-dev/wxt/pull/869))
- Add more metadata for npm ([#885](https://github.com/wxt-dev/wxt/pull/885))
### ❤️ Contributors
- Florian Metz ([@Timeraa](http://github.com/Timeraa))
## v1.0.0
Initial release 🎉
+24 -8
View File
@@ -1,6 +1,23 @@
{ {
"name": "@wxt-dev/module-vue", "name": "@wxt-dev/module-vue",
"version": "1.0.0", "description": "WXT module to enable Vue support",
"repository": {
"type": "git",
"url": "git+https://github.com/wxt-dev/wxt.git",
"directory": "packages/module-vue"
},
"homepage": "https://github.com/wxt-dev/wxt/blob/main/packages/module-vue/README.md",
"keywords": [
"wxt",
"module",
"vue"
],
"author": {
"name": "Aaron Klinker",
"email": "aaronklinker1+wxt@gmail.com"
},
"license": "MIT",
"version": "1.0.1",
"type": "module", "type": "module",
"main": "./dist/index.cjs", "main": "./dist/index.cjs",
"module": "./dist/index.mjs", "module": "./dist/index.mjs",
@@ -21,20 +38,19 @@
"dist" "dist"
], ],
"scripts": { "scripts": {
"build": "pnpm -s build-deps && unbuild", "build": "buildc -- unbuild",
"check": "pnpm -s build-deps && check", "check": "pnpm build && check"
"build-deps": "pnpm -ws build-deps @wxt-dev/module-vue"
}, },
"peerDependencies": { "peerDependencies": {
"wxt": ">=0.18.5" "wxt": ">=0.18.6"
}, },
"dependencies": { "dependencies": {
"@vitejs/plugin-vue": "^5.0.5" "@vitejs/plugin-vue": "^5.1.1"
}, },
"devDependencies": { "devDependencies": {
"@aklinker1/check": "^1.3.1", "@aklinker1/check": "^1.3.1",
"publint": "^0.2.8", "publint": "^0.2.9",
"typescript": "^5.4.5", "typescript": "^5.5.4",
"unbuild": "^2.0.0", "unbuild": "^2.0.0",
"wxt": "workspace:*" "wxt": "workspace:*"
} }
+12
View File
@@ -0,0 +1,12 @@
import autoImports from './.wxt/eslintrc-auto-import.js';
export default [
{
languageOptions: {
globals: {
...autoImports.globals,
},
sourceType: 'module',
},
},
];
+16 -10
View File
@@ -4,28 +4,34 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "pnpm -s build-deps && wxt", "dev": "buildc --deps-only -- wxt",
"build": "pnpm -s build-deps && wxt build", "build": "buildc --deps-only -- wxt build",
"build:all": "pnpm -s build-deps && run-s -s 'build:all:*'", "build:all": "buildc --deps-only -- run-s -s 'build:all:*'",
"build:all:chrome-mv3": "wxt build", "build:all:chrome-mv3": "wxt build",
"build:all:chrome-mv2": "wxt build --mv2", "build:all:chrome-mv2": "wxt build --mv2",
"build:all:firefox-mv3": "wxt build -b firefox --mv3", "build:all:firefox-mv3": "wxt build -b firefox --mv3",
"build:all:firefox-mv2": "wxt build -b firefox", "build:all:firefox-mv2": "wxt build -b firefox",
"test": "pnpm -s build-deps && vitest", "test": "buildc --deps-only -- vitest",
"zip": "pnpm -s build-deps && wxt zip", "zip": "buildc --deps-only -- wxt zip",
"check": "pnpm -s build-deps && check", "check": "buildc --deps-only -- check",
"postinstall": "pnpm -s build-deps && wxt prepare", "postinstall": "buildc --deps-only -- wxt prepare"
"build-deps": "pnpm -sw build-deps wxt-demo"
}, },
"dependencies": { "dependencies": {
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1" "react-dom": "^18.3.1"
}, },
"devDependencies": { "devDependencies": {
"@types/chrome": "^0.0.269",
"@types/react": "^18.3.3", "@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"sass": "^1.77.5", "@wxt-dev/auto-icons": "workspace:*",
"typescript": "^5.4.5", "sass": "^1.77.8",
"typescript": "^5.5.4",
"vitest": "^2.0.4",
"vitest-plugin-random-seed": "^1.1.0",
"wxt": "workspace:*" "wxt": "workspace:*"
},
"buildc": {
"outDir": ".output/chrome-mv3"
} }
} }
+11
View File
@@ -0,0 +1,11 @@
import { defineAppConfig } from 'wxt/sandbox';
declare module 'wxt/sandbox' {
export interface WxtAppConfig {
example: string;
}
}
export default defineAppConfig({
example: 'value',
});

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -15,10 +15,12 @@ export default defineBackground({
messages, messages,
}); });
console.log(useAppConfig());
// @ts-expect-error: should only accept entrypoints or public assets // @ts-expect-error: should only accept entrypoints or public assets
browser.runtime.getURL('/'); browser.runtime.getURL('/');
browser.runtime.getURL('/background.js'); browser.runtime.getURL('/background.js');
browser.runtime.getURL('/icon/128.png'); browser.runtime.getURL('/icons/128.png');
browser.runtime.getURL('/example.html#hash'); browser.runtime.getURL('/example.html#hash');
browser.runtime.getURL('/example.html?query=param'); browser.runtime.getURL('/example.html?query=param');
// @ts-expect-error: should only allow hashes/query params on HTML files // @ts-expect-error: should only allow hashes/query params on HTML files
@@ -13,7 +13,7 @@ export default defineContentScript({
anchor: 'form[role=search]', anchor: 'form[role=search]',
onMount: (container) => { onMount: (container) => {
const app = document.createElement('div'); const app = document.createElement('div');
app.textContent = 'Custom content script UI'; app.textContent = browser.i18n.getMessage('prompt_for_name');
container.append(app); container.append(app);
}, },
}); });
@@ -0,0 +1,3 @@
import autoIcons from '@wxt-dev/auto-icons';
export default autoIcons;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

+2 -1
View File
@@ -2,6 +2,7 @@
"extends": ["../../tsconfig.base.json", "./.wxt/tsconfig.json"], "extends": ["../../tsconfig.base.json", "./.wxt/tsconfig.json"],
"compilerOptions": { "compilerOptions": {
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"jsx": "react-jsx" "jsx": "react-jsx",
"types": ["vitest-plugin-random-seed/types"]
} }
} }
+3 -2
View File
@@ -2,6 +2,7 @@ import { defineConfig } from 'wxt';
export default defineConfig({ export default defineConfig({
srcDir: 'src', srcDir: 'src',
extensionApi: 'chrome',
manifest: { manifest: {
permissions: ['storage'], permissions: ['storage'],
default_locale: 'en', default_locale: 'en',
@@ -18,8 +19,8 @@ export default defineConfig({
analysis: { analysis: {
open: true, open: true,
}, },
experimental: { runner: {
viteRuntime: true, startUrls: ['https://duckduckgo.com'],
}, },
example: { example: {
a: 'a', a: 'a',
+285 -198
View File
@@ -1,5 +1,273 @@
# Changelog # Changelog
## v0.19.4
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.3...wxt-v0.19.4)
### 🚀 Enhancements
- Add `injectScript` helper ([#900](https://github.com/wxt-dev/wxt/pull/900))
### 🩹 Fixes
- Do not clear `.wxt/tsconfig.json` in `findEntrypoints` if it exists ([#898](https://github.com/wxt-dev/wxt/pull/898))
- **types:** `PublicPath` type resolution with `extensionApi: "chrome"` ([#901](https://github.com/wxt-dev/wxt/pull/901))
- Fix `createIframeUi` `page` option types ([3a8e613](https://github.com/wxt-dev/wxt/commit/3a8e613))
### ❤️ Contributors
- Hikiko4ern ([@hikiko4ern](http://github.com/hikiko4ern))
## v0.19.3
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.2...wxt-v0.19.3)
### 🩹 Fixes
- Add `consola` to `wxt` dependencies ([#892](https://github.com/wxt-dev/wxt/pull/892))
- **content-script-context:** Fix initialization logic for Firefox ([#895](https://github.com/wxt-dev/wxt/pull/895))
### 📖 Documentation
- Improve `prepare:types` hook JSDoc ([#886](https://github.com/wxt-dev/wxt/pull/886))
### ❤️ Contributors
- Hikiko4ern ([@hikiko4ern](http://github.com/hikiko4ern))
- Himanshu Patil ([@mehimanshupatil](https://github.com/mehimanshupatil))
## v0.19.2
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.1...wxt-v0.19.2)
### 🩹 Fixes
- Remove unused top-level functions and variables when loading entrypoints with the `vite-node` loader ([#875](https://github.com/wxt-dev/wxt/pull/875))
- Don't default to dev mode for production builds when using `vite-node` loader ([#877](https://github.com/wxt-dev/wxt/pull/877))
### 📖 Documentation
- Update README and homepage features with WXT modules ([ed07a49](https://github.com/wxt-dev/wxt/commit/ed07a49))
### 🏡 Chore
- **deps:** Upgrade all dependencies ([#869](https://github.com/wxt-dev/wxt/pull/869))
## v0.19.1
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.19.0...wxt-v0.19.1)
### 🚀 Enhancements
- Auto Icons Module ([#851](https://github.com/wxt-dev/wxt/pull/851))
### 🔥 Performance
- Tree-shake unrelated code inside `vite-node` entrypoint loader ([#867](https://github.com/wxt-dev/wxt/pull/867))
### 🩹 Fixes
- Define web globals when importing entrypoints ([#865](https://github.com/wxt-dev/wxt/pull/865))
### ❤️ Contributors
- Florian Metz ([@Timeraa](http://github.com/Timeraa))
## v0.19.0
[⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.15...wxt-v0.19.0)
### 🚀 Enhancements
- **experimental:** First-class support for excluding `webextension-polyfill` ([#847](https://github.com/wxt-dev/wxt/pull/847))
- **storage:** `init` option and rename `defaultValue` to `fallback` ([#827](https://github.com/wxt-dev/wxt/pull/827))
- **hooks:** Add `prepare:publicPaths` hook ([#858](https://github.com/wxt-dev/wxt/pull/858))
- ⚠️ Use `vite-node` to load entrypoints by default ([#859](https://github.com/wxt-dev/wxt/pull/859))
### 🔥 Performance
- **size:** ⚠️ Switch from `tsup` to `unbuild` for building WXT ([#848](https://github.com/wxt-dev/wxt/pull/848))
### 🩹 Fixes
- Wrong module hook type ([#849](https://github.com/wxt-dev/wxt/pull/849))
### 📖 Documentation
- Update labels in content script UI positioning screenshot ([2b6ff8d](https://github.com/wxt-dev/wxt/commit/2b6ff8d))
- Add upgrade guide and breaking changes ([#860](https://github.com/wxt-dev/wxt/pull/860))
### 🏡 Chore
- **deps:** Bump all non-major dependencies ([#834](https://github.com/wxt-dev/wxt/pull/834))
- **dev-deps:** Upgrade `vitest` from 1.6 to 2.0 ([#836](https://github.com/wxt-dev/wxt/pull/836))
- **deps:** Upgrade `async-mutex` from 0.4.1 to 0.5.0 ([#837](https://github.com/wxt-dev/wxt/pull/837))
- **deps:** Upgrade `esbuild` from 0.19.12 to 0.23.0 ([#838](https://github.com/wxt-dev/wxt/pull/838))
- **deps:** Upgrade `vite-node` from 1.6 to 2.0 ([#839](https://github.com/wxt-dev/wxt/pull/839))
- **deps:** Upgrade `ora` from 7 to 8 ([#841](https://github.com/wxt-dev/wxt/pull/841))
- **deps:** Upgrade `webextension-polyfill` from 0.10 to 0.12 ([#842](https://github.com/wxt-dev/wxt/pull/842))
- **deps:** Upgrade `minimatch` from 9 to 10 ([#840](https://github.com/wxt-dev/wxt/pull/840))
- **dev-deps:** Upgrade `happy-dom` from 13 to 14 ([#843](https://github.com/wxt-dev/wxt/pull/843))
### ❤️ Contributors
- Florian Metz ([@Timeraa](http://github.com/Timeraa))
## v0.18.15
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.14...wxt-v0.18.15)
### 🩹 Fixes
- Don't throw error if localization file is missing ([#832](https://github.com/wxt-dev/wxt/pull/832))
- Build latest version of package before packing ([88a1244](https://github.com/wxt-dev/wxt/commit/88a1244))
- Externalize app config during dependency optimization ([#833](https://github.com/wxt-dev/wxt/pull/833))
### 📖 Documentation
- Fix links to Guide pages ([#821](https://github.com/wxt-dev/wxt/pull/821))
### ❤️ Contributors
- Eetann ([@eetann](http://github.com/eetann))
## v0.18.14
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.13...wxt-v0.18.14)
### 🩹 Fixes
- **modules:** Add types from all wxt node_modules, not just ones with config ([#817](https://github.com/wxt-dev/wxt/pull/817))
## v0.18.13
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.12...wxt-v0.18.13)
### 🚀 Enhancements
- **config:** `dev.server.hostname` ([#807](https://github.com/wxt-dev/wxt/pull/807))
- Add XPath support to getAnchor() ([#813](https://github.com/wxt-dev/wxt/pull/813))
### 🩹 Fixes
- Add debug logs for vite builder ([#816](https://github.com/wxt-dev/wxt/pull/816))
### ❤️ Contributors
- Ayub Kokabi ([@sir-kokabi](http://github.com/sir-kokabi))
## v0.18.12
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.11...wxt-v0.18.12)
### 🚀 Enhancements
- Support runtime config in `app.config.ts` ([#792](https://github.com/wxt-dev/wxt/pull/792))
### 🔥 Performance
- Create zip using streams ([#793](https://github.com/wxt-dev/wxt/pull/793))
### 🩹 Fixes
- Add missing name to ESLint v9 autoImports config ([#801](https://github.com/wxt-dev/wxt/pull/801))
### 📖 Documentation
- Update README ([#802](https://github.com/wxt-dev/wxt/pull/802))
### 🏡 Chore
- **deps:** Upgrade `web-ext-run` (0.2.0 to 0.2.1) ([#804](https://github.com/wxt-dev/wxt/pull/804))
### ❤️ Contributors
- Ntnyq ([@ntnyq](http://github.com/ntnyq))
- Florian Metz ([@Timeraa](http://github.com/Timeraa))
## v0.18.11
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.10...wxt-v0.18.11)
### 🚀 Enhancements
- Add eslint 9 config support ([#762](https://github.com/wxt-dev/wxt/pull/762))
### 🩹 Fixes
- Respect custom `outDir` when cleaning and zipping ([#774](https://github.com/wxt-dev/wxt/pull/774))
- **dev:** Catch error when attempting to reload a tab in a saved tab group ([#786](https://github.com/wxt-dev/wxt/pull/786))
### 🏡 Chore
- Replace consola with wxt.logger ([#776](https://github.com/wxt-dev/wxt/pull/776))
- **deps:** Upgrade non-major deps ([#778](https://github.com/wxt-dev/wxt/pull/778))
### ❤️ Contributors
- KnightYoshi ([@KnightYoshi](http://github.com/KnightYoshi))
- Asakura Mizu ([@AsakuraMizu](http://github.com/AsakuraMizu))
## v0.18.10
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.9...wxt-v0.18.10)
### 🚀 Enhancements
- Add `prepare:types` hook to extend `.wxt/` directory generation ([#767](https://github.com/wxt-dev/wxt/pull/767))
- **modules:** Allow adding generated public files ([#769](https://github.com/wxt-dev/wxt/pull/769))
### 🩹 Fixes
- Await `prepare:types` hook ([b29d49c](https://github.com/wxt-dev/wxt/commit/b29d49c))
### 🏡 Chore
- Refactor package manager test fixtures ([39f6c29](https://github.com/wxt-dev/wxt/commit/39f6c29))
- Consolidate `unimport` code into a built-in module ([#771](https://github.com/wxt-dev/wxt/pull/771))
## v0.18.9
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.8...wxt-v0.18.9)
### 🚀 Enhancements
- **experimental:** Replace `viteRuntime` option with `entrypointImporter` option, and implement `vite-node` importer ([#761](https://github.com/wxt-dev/wxt/pull/761))
## v0.18.8
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.7...wxt-v0.18.8)
### 🚀 Enhancements
- **dev:** Reload extension when public files change ([#752](https://github.com/wxt-dev/wxt/pull/752))
### 🩹 Fixes
- Don't load plugins twice in HTML pages ([#746](https://github.com/wxt-dev/wxt/pull/746))
- Ignore .wxt file changes in dev ([#755](https://github.com/wxt-dev/wxt/pull/755))
- **modules:** `addViteConfig` ignored user vite config ([#760](https://github.com/wxt-dev/wxt/pull/760))
### 🏡 Chore
- Refactor client web socket util ([#753](https://github.com/wxt-dev/wxt/pull/753))
- Add E2E test for `addImportPreset` ([9fc6408](https://github.com/wxt-dev/wxt/commit/9fc6408))
## v0.18.7
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.6...wxt-v0.18.7)
### 🩹 Fixes
- **dev:** Fix CSP error loading HTML plugins ([#723](https://github.com/wxt-dev/wxt/pull/723))
- Generalize react-refresh preamble logic to virtualize all inline scripts ([#728](https://github.com/wxt-dev/wxt/pull/728))
- **zip:** Revert dotfile changes from #674 ([#742](https://github.com/wxt-dev/wxt/pull/742), [#674](https://github.com/wxt-dev/wxt/issues/674))
### 🏡 Chore
- **deps:** Upgrade and sync all dependencies ([#725](https://github.com/wxt-dev/wxt/pull/725))
- Extract build cache script to NPM package ([#737](https://github.com/wxt-dev/wxt/pull/737))
## v0.18.6 ## v0.18.6
[compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.5...wxt-v0.18.6) [compare changes](https://github.com/wxt-dev/wxt/compare/wxt-v0.18.5...wxt-v0.18.6)
@@ -143,7 +411,7 @@
## v0.18.0 ## v0.18.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.17.12...v0.18.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.17.12...v0.18.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -178,12 +446,6 @@
- Refactor repo to a standard monorepo ([#646](https://github.com/wxt-dev/wxt/pull/646)) - Refactor repo to a standard monorepo ([#646](https://github.com/wxt-dev/wxt/pull/646))
- Fix formatting after monorepo refactor ([6ca3767](https://github.com/wxt-dev/wxt/commit/6ca3767)) - Fix formatting after monorepo refactor ([6ca3767](https://github.com/wxt-dev/wxt/commit/6ca3767))
#### ⚠️ Breaking Changes
- ⚠️ Automatically move `host_permissions` to `permissions` for MV2 ([#626](https://github.com/wxt-dev/wxt/pull/626))
Out of an abundance of caution, I've marked this as a breaking change because permission generation has changed. **_If you list `host_permissions` in your `wxt.config.ts`'s manifest and have released your extension_**, double check that your `permissions` and `host_permissions` have not changed for all browsers you target in your `.output/*/manifest.json` files. Permission changes can cause the extension to be disabled on update, and can cause a drop in users, so be sure to double check for differences compared to the previous manifest version.
### ❤️ Contributors ### ❤️ Contributors
- Alegal200 ([@alegal200](https://github.com/alegal200)) - Alegal200 ([@alegal200](https://github.com/alegal200))
@@ -450,7 +712,7 @@
## v0.17.0 ## v0.17.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.16.11...v0.17.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.16.11...v0.17.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -465,70 +727,6 @@
- **storage:** Update docs ([91fc41c](https://github.com/wxt-dev/wxt/commit/91fc41c)) - **storage:** Update docs ([91fc41c](https://github.com/wxt-dev/wxt/commit/91fc41c))
#### ⚠️ Breaking Changes
`v0.17.0` introduces several breaking changes to `wxt/storage`.
First, if you were using `defineItem` with versioning and no default value, you will need to add `defaultValue: null` to the options and update the first type parameter:
```ts
// < 0.17
const item = storage.defineItem<number>("local:count", {
version: ...,
migrations: ...,
})
// >= 0.17
const item = storage.defineItem<number | null>("local:count", {
defaultValue: null,
version: ...,
migrations: ...,
})
```
The `defaultValue` property is now required if passing in the second options argument.
If you exclude the second options argument, it will default to being nullable, as before.
```ts
const item: WxtStorageItem<number | null> =
storage.defineItem<number>('local:count');
const value: number | null = await item.getValue();
```
> If you don't use typescript, there aren't any breaking changes, this is just a type change.
For storage items that are not nullable, the `watch` callback types has improved and will use the default value instead of `null` when the value is missing:
```ts
// >=0.17
const item = storage.defineItem<number>('local:count', { defaultValue: 0 });
item.watch((newValue: number | null, oldValue: number | null) => {
// ...
});
// >=0.17
const item = storage.defineItem<number>('local:count', { defaultValue: 0 });
item.watch((newValue: number, oldValue: number) => {
// ...
});
```
You can also access the default value directly off the item:
```ts
console.log(item.defaultValue); // 0
```
The second breaking change is that migrations for versioned items only run when the extension is updated. Before, they were ran whenever the storage item was created, in any entrypoint (background, popup, content script, etc). Now, in v0.17, storage items will only run migrations when the `browser.runtime.onInstalled` event is fired with `reason = "update"` in the background. See the updated docs to make sure they run correctly: https://wxt.dev/guide/storage.html#running-migrations. TLDR: you need to import all storage items into the background entrypoint for the `onInstalled` hook to fire properly and thus run the migrations.
To keep the old behavior, call the new `migrate` function to run migrations as soon as an item is defined:
```ts
const item = storage.defineItem(...);
item.migrate();
```
## v0.16.11 ## v0.16.11
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.16.10...v0.16.11) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.16.10...v0.16.11)
@@ -734,7 +932,7 @@ item.migrate();
## v0.16.0 ## v0.16.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.15.4...v0.16.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.15.4...v0.16.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -750,31 +948,6 @@ item.migrate();
- **deps-dev:** Bump p-map from 7.0.0 to 7.0.1 ([#396](https://github.com/wxt-dev/wxt/pull/396)) - **deps-dev:** Bump p-map from 7.0.0 to 7.0.1 ([#396](https://github.com/wxt-dev/wxt/pull/396))
- **deps-dev:** Bump @vitest/coverage-v8 from 1.0.1 to 1.2.2 ([#397](https://github.com/wxt-dev/wxt/pull/397)) - **deps-dev:** Bump @vitest/coverage-v8 from 1.0.1 to 1.2.2 ([#397](https://github.com/wxt-dev/wxt/pull/397))
#### ⚠️ Breaking Changes
In [#398](https://github.com/wxt-dev/wxt/pull/398), HTML pages' JS entrypoints in the output directory have been moved. Unless you're doing some kind of post-build work referencing files, you don't have to make any changes.
- Before:
```
.output/
<target>/
chunks/
some-shared-chunk-<hash>.js
popup-<hash>.js
popup.html
```
- After:
```
.output/
<target>/
chunks/
some-shared-chunk-<hash>.js
popup.html
popup.js
```
This effects all HTML files, not just the Popup. The hash has been removed, and it's been moved to the root of the build target folder, not inside the `chunks/` directory. Moving files like this has not historically increased review times or triggered in-depth reviews when submitting updates to the stores.
## v0.15.4 ## v0.15.4
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.15.3...v0.15.4) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.15.3...v0.15.4)
@@ -833,7 +1006,7 @@ This effects all HTML files, not just the Popup. The hash has been removed, and
## v0.15.0 ## v0.15.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.14.7...v0.15.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.14.7...v0.15.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -853,21 +1026,6 @@ This effects all HTML files, not just the Popup. The hash has been removed, and
- Update contributor docs ([eb758bd](https://github.com/wxt-dev/wxt/commit/eb758bd)) - Update contributor docs ([eb758bd](https://github.com/wxt-dev/wxt/commit/eb758bd))
#### ⚠️ Breaking Changes
Renamed `zip.ignoredSources` to `zip.excludeSources` in [#378](https://github.com/wxt-dev/wxt/pull/378)
Renamed undocumented constants for detecting the build config at runtime in [#380](https://github.com/wxt-dev/wxt/pull/380). Now documented here: https://wxt.dev/guide/multiple-browsers.html#runtime
- `__BROWSER__` &rarr; `import.meta.env.BROWSER`
- `__COMMAND__` &rarr; `import.meta.env.COMMAND`
- `__MANIFEST_VERSION__` &rarr; `import.meta.env.MANIFEST_VERSION`
- `__IS_CHROME__` &rarr; `import.meta.env.CHROME`
- `__IS_FIREFOX__` &rarr; `import.meta.env.FIREFOX`
- `__IS_SAFARI__` &rarr; `import.meta.env.SAFARI`
- `__IS_EDGE__` &rarr; `import.meta.env.EDGE`
- `__IS_OPERA__` &rarr; `import.meta.env.OPERA`
### ❤️ Contributors ### ❤️ Contributors
- Nenad Novaković ([@dvlden](https://github.com/dvlden)) - Nenad Novaković ([@dvlden](https://github.com/dvlden))
@@ -988,22 +1146,12 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.14.0 ## v0.14.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.13.5...v0.14.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.13.5...v0.14.0)
### 🚀 Enhancements ### 🚀 Enhancements
- ⚠️ Refactor content script UI functions and add helper for "integrated" UIs ([#333](https://github.com/wxt-dev/wxt/pull/333)) - ⚠️ Refactor content script UI functions and add helper for "integrated" UIs ([#333](https://github.com/wxt-dev/wxt/pull/333))
#### ⚠️ Breaking Changes
`createContentScriptUi` and `createContentScriptIframe`, and some of their options, have been renamed:
- `createContentScriptUi({ ... })` &rarr; `createShadowRootUi({ ... })`
- `createContentScriptIframe({ ... })` &rarr; `createIframeUi({ ... })`
- `type: "inline" | "overlay" | "modal"` has been changed to `position: "inline" | "overlay" | "modal"`
- `onRemove` is now called **_before_** the UI is removed from the DOM, previously it was called after the UI was removed
- `mount` option has been renamed to `onMount`, to better match the related option, `onRemove`.
## v0.13.5 ## v0.13.5
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.13.4...v0.13.5) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.13.4...v0.13.5)
@@ -1093,16 +1241,12 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.13.0 ## v0.13.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.12.5...v0.13.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.12.5...v0.13.0)
### 🚀 Enhancements ### 🚀 Enhancements
- ⚠️ New `wxt/storage` APIs ([#300](https://github.com/wxt-dev/wxt/pull/300)) - ⚠️ New `wxt/storage` APIs ([#300](https://github.com/wxt-dev/wxt/pull/300))
#### ⚠️ Breaking Changes
- `wxt/storage` no longer relies on [`unstorage`](https://www.npmjs.com/package/unstorage). Some `unstorage` APIs, like `prefixStorage`, have been removed, while others, like `snapshot`, are methods on the new `storage` object. Most of the standard usage remains the same. See https://wxt.dev/guide/storage and https://wxt.dev/api/reference/wxt/storage/ for more details ([#300](https://github.com/wxt-dev/wxt/pull/300))
## v0.12.5 ## v0.12.5
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.12.4...v0.12.5) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.12.4...v0.12.5)
@@ -1150,7 +1294,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.12.0 ## v0.12.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.11.2...v0.12.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.11.2...v0.12.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -1170,17 +1314,6 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- Convert WXT CLI to an ESM binary ([#279](https://github.com/wxt-dev/wxt/pull/279)) - Convert WXT CLI to an ESM binary ([#279](https://github.com/wxt-dev/wxt/pull/279))
#### ⚠️ Breaking Changes
`defineContentScript` and `defineBackground` are now exported from `wxt/sandbox` instead of `wxt/client`. ([#284](https://github.com/wxt-dev/wxt/pull/284))
- If you use auto-imports, no changes are required.
- If you have disabled auto-imports, you'll need to manually update your import statements:
```diff
- import { defineBackground, defineContentScript } from 'wxt/client';
+ import { defineBackground, defineContentScript } from 'wxt/sandbox';
```
## v0.11.2 ## v0.11.2
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.11.1...v0.11.2) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.11.1...v0.11.2)
@@ -1213,7 +1346,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.11.0 ## v0.11.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.10.4...v0.11.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.10.4...v0.11.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -1228,10 +1361,6 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- Speed up CI using `pnpm` instead of `npm` ([#259](https://github.com/wxt-dev/wxt/pull/259)) - Speed up CI using `pnpm` instead of `npm` ([#259](https://github.com/wxt-dev/wxt/pull/259))
- Abstract vite from WXT's core logic ([#242](https://github.com/wxt-dev/wxt/pull/242)) - Abstract vite from WXT's core logic ([#242](https://github.com/wxt-dev/wxt/pull/242))
#### ⚠️ Breaking Changes
- You will need to update any other Vite plugins to a version that supports Vite 5 ([#261](https://github.com/wxt-dev/wxt/pull/261))
### ❤️ Contributors ### ❤️ Contributors
- Ítalo Brasil ([@italodeverdade](http://github.com/italodeverdade)) - Ítalo Brasil ([@italodeverdade](http://github.com/italodeverdade))
@@ -1304,7 +1433,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.10.0 ## v0.10.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.9.2...v0.10.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.9.2...v0.10.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -1377,7 +1506,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.9.0 ## v0.9.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.8.7...v0.9.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.8.7...v0.9.0)
### 🩹 Fixes ### 🩹 Fixes
@@ -1392,18 +1521,6 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- Fix Svelte and React template READMEs ([#207](https://github.com/wxt-dev/wxt/pull/207)) - Fix Svelte and React template READMEs ([#207](https://github.com/wxt-dev/wxt/pull/207))
#### ⚠️ Breaking Changes
- ⚠️ Removed [`"WebWorker"` types](https://www.typescriptlang.org/tsconfig/lib.html) from `.wxt/tsconfig.json` ([#209](https://github.com/wxt-dev/wxt/pull/209)). These types are useful for MV3 projects using a service worker. To add them back to your project, add the following to your project's TSConfig:
```diff
{
"extends": "./.wxt/tsconfig.json",
+ "compilerOptions": {
+ "lib": ["ESNext", "DOM", "WebWorker"]
+ }
}
```
### ❤️ Contributors ### ❤️ Contributors
- yyyanghj ([@yyyanghj](https://github.com/yyyanghj)) - yyyanghj ([@yyyanghj](https://github.com/yyyanghj))
@@ -1512,7 +1629,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.8.0 ## v0.8.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.7.5...v0.8.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.7.5...v0.8.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -1526,11 +1643,6 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- ⚠️ Rename `BackgroundScriptDefintition` to `BackgroundDefinition` ([446f265](https://github.com/wxt-dev/wxt/commit/446f265)) - ⚠️ Rename `BackgroundScriptDefintition` to `BackgroundDefinition` ([446f265](https://github.com/wxt-dev/wxt/commit/446f265))
#### ⚠️ Breaking Changes
- ⚠️ Unlisted scripts must now `export default defineUnlistedScript(...)` ([#167](https://github.com/wxt-dev/wxt/pull/167))
- ⚠️ Rename `BackgroundScriptDefintition` to `BackgroundDefinition` ([446f265](https://github.com/wxt-dev/wxt/commit/446f265))
### ❤️ Contributors ### ❤️ Contributors
- 渣渣120 [@WOSHIZHAZHA120](https://github.com/WOSHIZHAZHA120) - 渣渣120 [@WOSHIZHAZHA120](https://github.com/WOSHIZHAZHA120)
@@ -1613,7 +1725,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.7.0 ## v0.7.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.6.6...v0.7.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.6.6...v0.7.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -1629,10 +1741,6 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- Store user config metadata in memory ([0591050](https://github.com/wxt-dev/wxt/commit/0591050)) - Store user config metadata in memory ([0591050](https://github.com/wxt-dev/wxt/commit/0591050))
#### ⚠️ Breaking Changes
- ⚠️ Content script CSS used to be output to `assets/<name>.css`, but is now `content-scripts/<name>.css` to match the docs. ([#140](https://github.com/wxt-dev/wxt/pull/140))
## v0.6.6 ## v0.6.6
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.6.5...v0.6.6) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.6.5...v0.6.6)
@@ -1715,7 +1823,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.6.0 ## v0.6.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.5.6...v0.6.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.5.6...v0.6.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -1727,10 +1835,6 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- Use the same mode for each build step ([1f6a931](https://github.com/wxt-dev/wxt/commit/1f6a931)) - Use the same mode for each build step ([1f6a931](https://github.com/wxt-dev/wxt/commit/1f6a931))
- Disable dev logs in production ([3f260ee](https://github.com/wxt-dev/wxt/commit/3f260ee)) - Disable dev logs in production ([3f260ee](https://github.com/wxt-dev/wxt/commit/3f260ee))
#### ⚠️ Breaking Changes
- ⚠️ The `vite` config option must now be a function. If you were using an object before, change it from `vite: { ... }` to `vite: () => ({ ... })`. ([#121](https://github.com/wxt-dev/wxt/pull/121))
## v0.5.6 ## v0.5.6
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.5.5...v0.5.6) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.5.5...v0.5.6)
@@ -1791,7 +1895,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.5.0 ## v0.5.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.4.1...v0.5.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.4.1...v0.5.0)
### 🩹 Fixes ### 🩹 Fixes
@@ -1814,10 +1918,6 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- **deps-dev:** Bump @types/node from 20.5.0 to 20.5.9 ([#110](https://github.com/wxt-dev/wxt/pull/110)) - **deps-dev:** Bump @types/node from 20.5.0 to 20.5.9 ([#110](https://github.com/wxt-dev/wxt/pull/110))
- Add entrypoints debug log ([dbd84c8](https://github.com/wxt-dev/wxt/commit/dbd84c8)) - Add entrypoints debug log ([dbd84c8](https://github.com/wxt-dev/wxt/commit/dbd84c8))
#### ⚠️ Breaking Changes
- ⚠️ Change default `publicDir` to `<srcDir>/public` ([5f15f9c](https://github.com/wxt-dev/wxt/commit/5f15f9c))
## v0.4.1 ## v0.4.1
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.4.0...v0.4.1) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.4.0...v0.4.1)
@@ -1832,7 +1932,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.4.0 ## v0.4.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.3.2...v0.4.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.3.2...v0.4.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -1875,10 +1975,6 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- Remove explicit icon config from templates ([93bfee0](https://github.com/wxt-dev/wxt/commit/93bfee0)) - Remove explicit icon config from templates ([93bfee0](https://github.com/wxt-dev/wxt/commit/93bfee0))
- Use import aliases in Vue template ([#104](https://github.com/wxt-dev/wxt/pull/104)) - Use import aliases in Vue template ([#104](https://github.com/wxt-dev/wxt/pull/104))
#### ⚠️ Breaking Changes
- ⚠️ Use relative path aliases inside `.wxt/tsconfig.json` ([#102](https://github.com/wxt-dev/wxt/pull/102))
## v0.3.2 ## v0.3.2
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.3.1...v0.3.2) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.3.1...v0.3.2)
@@ -1945,7 +2041,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.3.0 ## v0.3.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.2.5...v0.3.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.2.5...v0.3.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -1969,11 +2065,6 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- Improve checks against `demo/` extension ([9cc464f](https://github.com/wxt-dev/wxt/commit/9cc464f)) - Improve checks against `demo/` extension ([9cc464f](https://github.com/wxt-dev/wxt/commit/9cc464f))
#### ⚠️ Breaking Changes
- ⚠️ Add type safety to `browser.runtime.getURL` ([58a84ec](https://github.com/wxt-dev/wxt/commit/58a84ec))
- ⚠️ Change default `publicDir` to `<rootDir>/public` ([19c0948](https://github.com/wxt-dev/wxt/commit/19c0948))
## v0.2.5 ## v0.2.5
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.2.4...v0.2.5) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.2.4...v0.2.5)
@@ -2036,7 +2127,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
## v0.2.0 ## v0.2.0
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.6...v0.2.0) [⚠️ breaking changes](https://wxt.dev/guide/upgrade-guide/wxt) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.6...v0.2.0)
### 🚀 Enhancements ### 🚀 Enhancements
@@ -2054,10 +2145,6 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- Run `wxt prepare` on `postinstall` ([c1ea9ba](https://github.com/wxt-dev/wxt/commit/c1ea9ba)) - Run `wxt prepare` on `postinstall` ([c1ea9ba](https://github.com/wxt-dev/wxt/commit/c1ea9ba))
- Don't format lockfile ([5c7e041](https://github.com/wxt-dev/wxt/commit/5c7e041)) - Don't format lockfile ([5c7e041](https://github.com/wxt-dev/wxt/commit/5c7e041))
#### ⚠️ Breaking Changes
- ⚠️ Rename `defineBackgroundScript` to `defineBackground` ([5b48ae9](https://github.com/wxt-dev/wxt/commit/5b48ae9))
## v0.1.6 ## v0.1.6
[compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.5...v0.1.6) [compare changes](https://github.com/wxt-dev/wxt/compare/v0.1.5...v0.1.6)
+6 -5
View File
@@ -1,5 +1,5 @@
<h1 align="center"> <h1 align="center">
<img style="vertical-align:middle" width="44" src="./docs/public/hero-logo.svg" alt="WXT Logo"> <img style="vertical-align:middle" width="44" src="https://raw.githubusercontent.com/wxt-dev/wxt/HEAD/docs/public/hero-logo.svg" alt="WXT Logo">
<span>WXT</span> <span>WXT</span>
</h1> </h1>
@@ -22,18 +22,18 @@
</p> </p>
<p align="center"> <p align="center">
<a href="https://wxt.dev" target="_blank">Get Started</a> <a href="https://wxt.dev/guide/installation.html" target="_blank">Get Started</a>
&bull;
<a href="https://wxt.dev/guide/installation.html" target="_blank">Installation</a>
&bull; &bull;
<a href="https://wxt.dev/api/config.html" target="_blank">Configuration</a> <a href="https://wxt.dev/api/config.html" target="_blank">Configuration</a>
&bull; &bull;
<a href="https://wxt.dev/examples.html" target="_blank">Examples</a> <a href="https://wxt.dev/examples.html" target="_blank">Examples</a>
&bull; &bull;
<a href="https://github.com/wxt-dev/wxt/blob/main/packages/wxt/CHANGELOG.md" target="_blank">Changelog</a>
&bull;
<a href="https://discord.gg/ZFsZqGery9" target="_blank">Discord</a> <a href="https://discord.gg/ZFsZqGery9" target="_blank">Discord</a>
</p> </p>
![Example CLI Output](./docs/assets/cli-output.png) ![Example CLI Output](https://raw.githubusercontent.com/wxt-dev/wxt/HEAD/docs/assets/cli-output.png)
## Demo ## Demo
@@ -59,6 +59,7 @@ Or see the [installation guide](https://wxt.dev/guide/installation.html) to get
- 🦾 Auto-imports - 🦾 Auto-imports
- 🤖 Automated publishing - 🤖 Automated publishing
- 🎨 Frontend framework agnostic: works with Vue, React, Svelte, etc - 🎨 Frontend framework agnostic: works with Vue, React, Svelte, etc
- 📦 Modular architecture with [WXT modules](https://wxt.dev/guide/go-further/reusable-modules.html#overview)
- 🖍️ Quickly bootstrap a new project - 🖍️ Quickly bootstrap a new project
- 📏 Bundle analysis - 📏 Bundle analysis
- ⬇️ Download and bundle remote URL imports - ⬇️ Download and bundle remote URL imports
+1 -1
View File
@@ -1,2 +1,2 @@
#!/usr/bin/env node #!/usr/bin/env node
import '../dist/cli.js'; import '../dist/cli/index.mjs';
+49
View File
@@ -0,0 +1,49 @@
import { defineBuildConfig } from 'unbuild';
import { version } from './package.json';
import { readFile, writeFile } from 'fs/promises';
import {
virtualEntrypointModuleNames,
virtualModuleNames,
} from './src/core/utils/virtual-modules';
export default defineBuildConfig([
// Non-virtual modules can be transpiled with mkdist
{
entries: [
{
builder: 'mkdist',
input: 'src',
pattern: ['**/*', '!**/__tests__', '!**/*.md', '!virtual', '!@types'],
declaration: true,
},
],
hooks: {
async 'build:done'() {
// Replace any template variables in output files
await replaceVars('dist/version.mjs', { version });
},
},
},
// Virtual modules must be bundled individually
...virtualModuleNames.map((moduleName) => ({
entries: [`src/virtual/${moduleName}.ts`],
externals: [
...virtualEntrypointModuleNames.map((name) => `virtual:user-${name}`),
'virtual:wxt-plugins',
'virtual:app-config',
'wxt/browser',
'wxt/sandbox',
'wxt/client',
'wxt/testing',
],
})),
]);
async function replaceVars(file: string, vars: Record<string, string>) {
let text = await readFile(file, 'utf8');
Object.entries(vars).forEach(([name, value]) => {
text = text.replaceAll(`{{${name}}}`, value);
});
await writeFile(file, text, 'utf8');
}
@@ -0,0 +1,115 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Auto Imports > eslintrc > "enabled: 8" should output a JSON config file compatible with ESlint 8 1`] = `
".wxt/eslintrc-auto-import.json
----------------------------------------
{
"globals": {
"ContentScriptContext": true,
"InvalidMatchPattern": true,
"MatchPattern": true,
"browser": true,
"createIframeUi": true,
"createIntegratedUi": true,
"createShadowRootUi": true,
"defineAppConfig": true,
"defineBackground": true,
"defineConfig": true,
"defineContentScript": true,
"defineUnlistedScript": true,
"defineWxtPlugin": true,
"fakeBrowser": true,
"injectScript": true,
"storage": true,
"useAppConfig": true
}
}
"
`;
exports[`Auto Imports > eslintrc > "enabled: 9" should output a flat config file compatible with ESlint 9 1`] = `
".wxt/eslint-auto-imports.mjs
----------------------------------------
const globals = {
"ContentScriptContext": true,
"InvalidMatchPattern": true,
"MatchPattern": true,
"browser": true,
"createIframeUi": true,
"createIntegratedUi": true,
"createShadowRootUi": true,
"defineAppConfig": true,
"defineBackground": true,
"defineConfig": true,
"defineContentScript": true,
"defineUnlistedScript": true,
"defineWxtPlugin": true,
"fakeBrowser": true,
"injectScript": true,
"storage": true,
"useAppConfig": true
}
export default {
name: "wxt/auto-imports",
languageOptions: {
globals,
sourceType: "module",
},
};
"
`;
exports[`Auto Imports > eslintrc > "enabled: true" should output a JSON config file compatible with ESlint 8 1`] = `
".wxt/eslintrc-auto-import.json
----------------------------------------
{
"globals": {
"ContentScriptContext": true,
"InvalidMatchPattern": true,
"MatchPattern": true,
"browser": true,
"createIframeUi": true,
"createIntegratedUi": true,
"createShadowRootUi": true,
"defineAppConfig": true,
"defineBackground": true,
"defineConfig": true,
"defineContentScript": true,
"defineUnlistedScript": true,
"defineWxtPlugin": true,
"fakeBrowser": true,
"injectScript": true,
"storage": true,
"useAppConfig": true
}
}
"
`;
exports[`Auto Imports > eslintrc > should allow customizing the output 1`] = `
"example.json
----------------------------------------
{
"globals": {
"ContentScriptContext": "readonly",
"InvalidMatchPattern": "readonly",
"MatchPattern": "readonly",
"browser": "readonly",
"createIframeUi": "readonly",
"createIntegratedUi": "readonly",
"createShadowRootUi": "readonly",
"defineAppConfig": "readonly",
"defineBackground": "readonly",
"defineConfig": "readonly",
"defineContentScript": "readonly",
"defineUnlistedScript": "readonly",
"defineWxtPlugin": "readonly",
"fakeBrowser": "readonly",
"injectScript": "readonly",
"storage": "readonly",
"useAppConfig": "readonly"
}
}
"
`;
+1 -1
View File
@@ -1,6 +1,6 @@
import { describe, it, expect, beforeEach, vi } from 'vitest'; import { describe, it, expect, beforeEach, vi } from 'vitest';
import { TestProject } from '../utils'; import { TestProject } from '../utils';
import { resetBundleIncrement } from '~/core/builders/vite/plugins'; import { resetBundleIncrement } from '../../src/core/builders/vite/plugins';
import open from 'open'; import open from 'open';
vi.mock('open'); vi.mock('open');
+159 -50
View File
@@ -1,5 +1,6 @@
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { TestProject } from '../utils'; import { TestProject } from '../utils';
import { execaCommand } from 'execa';
describe('Auto Imports', () => { describe('Auto Imports', () => {
describe('imports: { ... }', () => { describe('imports: { ... }', () => {
@@ -23,13 +24,16 @@ describe('Auto Imports', () => {
const createIframeUi: typeof import('wxt/client')['createIframeUi'] const createIframeUi: typeof import('wxt/client')['createIframeUi']
const createIntegratedUi: typeof import('wxt/client')['createIntegratedUi'] const createIntegratedUi: typeof import('wxt/client')['createIntegratedUi']
const createShadowRootUi: typeof import('wxt/client')['createShadowRootUi'] const createShadowRootUi: typeof import('wxt/client')['createShadowRootUi']
const defineAppConfig: typeof import('wxt/sandbox')['defineAppConfig']
const defineBackground: typeof import('wxt/sandbox')['defineBackground'] const defineBackground: typeof import('wxt/sandbox')['defineBackground']
const defineConfig: typeof import('wxt')['defineConfig'] const defineConfig: typeof import('wxt')['defineConfig']
const defineContentScript: typeof import('wxt/sandbox')['defineContentScript'] const defineContentScript: typeof import('wxt/sandbox')['defineContentScript']
const defineUnlistedScript: typeof import('wxt/sandbox')['defineUnlistedScript'] const defineUnlistedScript: typeof import('wxt/sandbox')['defineUnlistedScript']
const defineWxtPlugin: typeof import('wxt/sandbox')['defineWxtPlugin'] const defineWxtPlugin: typeof import('wxt/sandbox')['defineWxtPlugin']
const fakeBrowser: typeof import('wxt/testing')['fakeBrowser'] const fakeBrowser: typeof import('wxt/testing')['fakeBrowser']
const injectScript: typeof import('wxt/client')['injectScript']
const storage: typeof import('wxt/storage')['storage'] const storage: typeof import('wxt/storage')['storage']
const useAppConfig: typeof import('wxt/client')['useAppConfig']
} }
" "
`); `);
@@ -47,10 +51,10 @@ describe('Auto Imports', () => {
---------------------------------------- ----------------------------------------
// Generated by wxt // Generated by wxt
/// <reference types="wxt/vite-builder-env" /> /// <reference types="wxt/vite-builder-env" />
/// <reference types="./types/imports.d.ts" />
/// <reference types="./types/paths.d.ts" /> /// <reference types="./types/paths.d.ts" />
/// <reference types="./types/i18n.d.ts" /> /// <reference types="./types/i18n.d.ts" />
/// <reference types="./types/globals.d.ts" /> /// <reference types="./types/globals.d.ts" />
/// <reference types="./types/imports.d.ts" />
" "
`); `);
}); });
@@ -96,7 +100,7 @@ describe('Auto Imports', () => {
}); });
describe('eslintrc', () => { describe('eslintrc', () => {
it('should output the globals list for ESLint to consume', async () => { it('"enabled: true" should output a JSON config file compatible with ESlint 8', async () => {
const project = new TestProject(); const project = new TestProject();
project.addFile('entrypoints/popup.html', `<html></html>`); project.addFile('entrypoints/popup.html', `<html></html>`);
@@ -108,30 +112,43 @@ describe('Auto Imports', () => {
}, },
}); });
expect(await project.serializeFile('.wxt/eslintrc-auto-import.json')) expect(
.toMatchInlineSnapshot(` await project.serializeFile('.wxt/eslintrc-auto-import.json'),
".wxt/eslintrc-auto-import.json ).toMatchSnapshot();
---------------------------------------- });
{
"globals": { it('"enabled: 8" should output a JSON config file compatible with ESlint 8', async () => {
"ContentScriptContext": true, const project = new TestProject();
"InvalidMatchPattern": true, project.addFile('entrypoints/popup.html', `<html></html>`);
"MatchPattern": true,
"browser": true, await project.prepare({
"createIframeUi": true, imports: {
"createIntegratedUi": true, eslintrc: {
"createShadowRootUi": true, enabled: 8,
"defineBackground": true, },
"defineConfig": true, },
"defineContentScript": true, });
"defineUnlistedScript": true,
"defineWxtPlugin": true, expect(
"fakeBrowser": true, await project.serializeFile('.wxt/eslintrc-auto-import.json'),
"storage": true ).toMatchSnapshot();
} });
}
" it('"enabled: 9" should output a flat config file compatible with ESlint 9', async () => {
`); const project = new TestProject();
project.addFile('entrypoints/popup.html', `<html></html>`);
await project.prepare({
imports: {
eslintrc: {
enabled: 9,
},
},
});
expect(
await project.serializeFile('.wxt/eslint-auto-imports.mjs'),
).toMatchSnapshot();
}); });
it('should allow customizing the output', async () => { it('should allow customizing the output', async () => {
@@ -148,30 +165,122 @@ describe('Auto Imports', () => {
}, },
}); });
expect(await project.serializeFile('example.json')) expect(await project.serializeFile('example.json')).toMatchSnapshot();
.toMatchInlineSnapshot(` });
"example.json
---------------------------------------- describe('Actual linting results', () => {
{ async function runEslint(
"globals": { project: TestProject,
"ContentScriptContext": "readonly", version: boolean | 'auto' | 8 | 9,
"InvalidMatchPattern": "readonly", ) {
"MatchPattern": "readonly", project.addFile(
"browser": "readonly", 'entrypoints/background.js',
"createIframeUi": "readonly", `export default defineBackground(() => {})`,
"createIntegratedUi": "readonly", );
"createShadowRootUi": "readonly", await project.prepare({
"defineBackground": "readonly", imports: { eslintrc: { enabled: version } },
"defineConfig": "readonly", });
"defineContentScript": "readonly", return await execaCommand('pnpm eslint entrypoints/background.js', {
"defineUnlistedScript": "readonly", cwd: project.root,
"defineWxtPlugin": "readonly", });
"fakeBrowser": "readonly", }
"storage": "readonly"
} describe('ESLint 9', () => {
} it('should have lint errors when not extending generated config', async () => {
" const project = new TestProject({
`); devDependencies: {
'@eslint/js': '9.5.0',
eslint: '9.5.0',
},
});
project.addFile(
'eslint.config.mjs',
`
import eslint from "@eslint/js";
export default [
eslint.configs.recommended,
];
`,
);
await expect(runEslint(project, 9)).rejects.toMatchObject({
message: expect.stringContaining(
"'defineBackground' is not defined",
),
});
});
it('should not have any lint errors when configured', async () => {
const project = new TestProject({
devDependencies: {
'@eslint/js': '9.5.0',
eslint: '9.5.0',
},
});
project.addFile(
'eslint.config.mjs',
`
import eslint from "@eslint/js";
import autoImports from "./.wxt/eslint-auto-imports.mjs";
export default [
eslint.configs.recommended,
autoImports,
];
`,
);
const res = await runEslint(project, 9);
expect(res).toBeDefined();
});
});
describe('ESLint 8', () => {
it('should have lint errors when not extending generated config', async () => {
const project = new TestProject({
devDependencies: {
eslint: '8.57.0',
},
});
project.addFile(
'.eslintrc',
JSON.stringify({
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
env: { es6: true },
extends: ['eslint:recommended'],
}),
);
await expect(runEslint(project, 8)).rejects.toMatchObject({
message: expect.stringContaining(
"'defineBackground' is not defined",
),
});
});
it('should not have any lint errors when configured', async () => {
const project = new TestProject({
devDependencies: {
eslint: '8.57.0',
},
});
project.addFile(
'.eslintrc',
JSON.stringify({
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
env: { es6: true },
extends: [
'eslint:recommended',
'./.wxt/eslintrc-auto-import.json',
],
}),
);
const res = await runEslint(project, 8);
expect(res).toBeDefined();
});
});
}); });
}); });
}); });
+11 -1
View File
@@ -1,9 +1,11 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'; import { describe, it, expect, vi, beforeEach } from 'vitest';
import { TestProject } from '../utils'; import { TestProject } from '../utils';
import { WxtHooks } from '~/types'; import { WxtHooks } from '../../src/types';
const hooks: WxtHooks = { const hooks: WxtHooks = {
ready: vi.fn(), ready: vi.fn(),
'prepare:types': vi.fn(),
'prepare:publicPaths': vi.fn(),
'build:before': vi.fn(), 'build:before': vi.fn(),
'build:done': vi.fn(), 'build:done': vi.fn(),
'build:manifestGenerated': vi.fn(), 'build:manifestGenerated': vi.fn(),
@@ -41,6 +43,8 @@ describe('Hooks', () => {
expectHooksToBeCalled({ expectHooksToBeCalled({
ready: true, ready: true,
'prepare:types': true,
'prepare:publicPaths': true,
'build:before': false, 'build:before': false,
'build:done': false, 'build:done': false,
'build:publicAssets': false, 'build:publicAssets': false,
@@ -60,6 +64,8 @@ describe('Hooks', () => {
expectHooksToBeCalled({ expectHooksToBeCalled({
ready: true, ready: true,
'prepare:types': true,
'prepare:publicPaths': true,
'build:before': true, 'build:before': true,
'build:done': true, 'build:done': true,
'build:publicAssets': true, 'build:publicAssets': true,
@@ -79,6 +85,8 @@ describe('Hooks', () => {
expectHooksToBeCalled({ expectHooksToBeCalled({
ready: true, ready: true,
'prepare:types': true,
'prepare:publicPaths': true,
'build:before': true, 'build:before': true,
'build:done': true, 'build:done': true,
'build:publicAssets': true, 'build:publicAssets': true,
@@ -104,6 +112,8 @@ describe('Hooks', () => {
expectHooksToBeCalled({ expectHooksToBeCalled({
ready: true, ready: true,
'prepare:types': true,
'prepare:publicPaths': true,
'build:before': true, 'build:before': true,
'build:done': true, 'build:done': true,
'build:publicAssets': true, 'build:publicAssets': true,
+1 -2
View File
@@ -1,9 +1,8 @@
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { TestProject } from '../utils'; import { TestProject, WXT_PACKAGE_DIR } from '../utils';
import { execaCommand } from 'execa'; import { execaCommand } from 'execa';
import glob from 'fast-glob'; import glob from 'fast-glob';
import { mkdir, writeJson } from 'fs-extra'; import { mkdir, writeJson } from 'fs-extra';
import { WXT_PACKAGE_DIR } from '../utils';
describe('Init command', () => { describe('Init command', () => {
it('should download and create a template', async () => { it('should download and create a template', async () => {
@@ -1,9 +1,9 @@
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { TestProject } from '../utils'; import { TestProject } from '../utils';
describe.each([true, false])( describe.each(['vite-node', 'jiti'] as const)(
'Manifest Content (Vite runtime? %s)', 'Manifest Content (Vite runtime? %s)',
(viteRuntime) => { (entrypointImporter) => {
it.each([ it.each([
{ browser: undefined, outDir: 'chrome-mv3', expected: undefined }, { browser: undefined, outDir: 'chrome-mv3', expected: undefined },
{ browser: 'chrome', outDir: 'chrome-mv3', expected: undefined }, { browser: 'chrome', outDir: 'chrome-mv3', expected: undefined },
@@ -24,7 +24,7 @@ describe.each([true, false])(
main: () => {}, main: () => {},
})`, })`,
); );
await project.build({ browser, experimental: { viteRuntime } }); await project.build({ browser, experimental: { entrypointImporter } });
const safariManifest = await project.getOutputManifest( const safariManifest = await project.getOutputManifest(
`.output/${outDir}/manifest.json`, `.output/${outDir}/manifest.json`,
+43 -18
View File
@@ -2,7 +2,7 @@ import { describe, it, expect, vi } from 'vitest';
import { TestProject } from '../utils'; import { TestProject } from '../utils';
import type { GenericEntrypoint, InlineConfig } from '../../src/types'; import type { GenericEntrypoint, InlineConfig } from '../../src/types';
import { readFile } from 'fs-extra'; import { readFile } from 'fs-extra';
import { normalizePath } from '~/core/utils/paths'; import { normalizePath } from '../../src/core/utils/paths';
describe('Module Helpers', () => { describe('Module Helpers', () => {
describe('options', () => { describe('options', () => {
@@ -101,7 +101,13 @@ describe('Module Helpers', () => {
export default defineWxtModule((wxt) => { export default defineWxtModule((wxt) => {
addPublicAssets(wxt, "${normalizePath(dir)}") addPublicAssets(wxt, "${normalizePath(dir)}")
}) wxt.hooks.hook("build:publicAssets", (_, assets) => {
assets.push({
relativeDest: "example/generated.txt",
contents: "",
});
});
});
`, `,
); );
@@ -114,6 +120,9 @@ describe('Module Helpers', () => {
await expect( await expect(
project.fileExists('.output/chrome-mv3/module.txt'), project.fileExists('.output/chrome-mv3/module.txt'),
).resolves.toBe(true); ).resolves.toBe(true);
await expect(
project.fileExists('.output/chrome-mv3/example/generated.txt'),
).resolves.toBe(true);
}); });
it("should not overwrite the user's public files", async () => { it("should not overwrite the user's public files", async () => {
@@ -183,10 +192,8 @@ describe('Module Helpers', () => {
const expectedText = addPluginModule(project); const expectedText = addPluginModule(project);
await project.build({ await project.build({
experimental: { // reduce build output when comparing test failures
// reduce build output when comparing test failures extensionApi: 'chrome',
includeBrowserPolyfill: false,
},
}); });
await expect(project.serializeOutput()).resolves.toContain(expectedText); await expect(project.serializeOutput()).resolves.toContain(expectedText);
@@ -205,10 +212,8 @@ describe('Module Helpers', () => {
const expectedText = addPluginModule(project); const expectedText = addPluginModule(project);
await project.build({ await project.build({
experimental: { // reduce build output when comparing test failures
// reduce build output when comparing test failures extensionApi: 'chrome',
includeBrowserPolyfill: false,
},
}); });
await expect(project.serializeOutput()).resolves.toContain(expectedText); await expect(project.serializeOutput()).resolves.toContain(expectedText);
@@ -228,10 +233,8 @@ describe('Module Helpers', () => {
const expectedText = addPluginModule(project); const expectedText = addPluginModule(project);
await project.build({ await project.build({
experimental: { // reduce build output when comparing test failures
// reduce build output when comparing test failures extensionApi: 'chrome',
includeBrowserPolyfill: false,
},
}); });
await expect(project.serializeOutput()).resolves.toContain(expectedText); await expect(project.serializeOutput()).resolves.toContain(expectedText);
@@ -246,10 +249,8 @@ describe('Module Helpers', () => {
const expectedText = addPluginModule(project); const expectedText = addPluginModule(project);
await project.build({ await project.build({
experimental: { // reduce build output when comparing test failures
// reduce build output when comparing test failures extensionApi: 'chrome',
includeBrowserPolyfill: false,
},
}); });
await expect(project.serializeOutput()).resolves.toContain(expectedText); await expect(project.serializeOutput()).resolves.toContain(expectedText);
@@ -287,5 +288,29 @@ describe('Module Helpers', () => {
await expect(project.serializeOutput()).resolves.toContain(expectedText); await expect(project.serializeOutput()).resolves.toContain(expectedText);
}); });
it('should add preset', async () => {
const project = new TestProject();
project.addFile(
'entrypoints/background.ts',
`export default defineBackground(() => {
customImport();
});`,
);
project.addFile(
'modules/test.ts',
`import { defineWxtModule, addImportPreset } from 'wxt/modules';
export default defineWxtModule((wxt) => {
addImportPreset(wxt, "vue");
})`,
);
await project.build();
await expect(
project.serializeFile('.wxt/types/imports.d.ts'),
).resolves.toContain("const ref: typeof import('vue')['ref']");
});
}); });
}); });
+26 -18
View File
@@ -262,10 +262,9 @@ describe('Output Directory Structure', () => {
project.addFile('entrypoints/popup/main.ts', `logHello('popup')`); project.addFile('entrypoints/popup/main.ts', `logHello('popup')`);
await project.build({ await project.build({
experimental: { // Simplify the build output for comparison
// Simplify the build output for comparison extensionApi: 'chrome',
includeBrowserPolyfill: false,
},
vite: () => ({ vite: () => ({
build: { build: {
// Make output for snapshot readible // Make output for snapshot readible
@@ -278,9 +277,10 @@ describe('Output Directory Structure', () => {
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
".output/chrome-mv3/background.js ".output/chrome-mv3/background.js
---------------------------------------- ----------------------------------------
var _a, _b;
import { l as logHello, i as initPlugins } from "./chunks/_virtual_wxt-plugins-OjKtWpmY.js"; import { l as logHello, i as initPlugins } from "./chunks/_virtual_wxt-plugins-OjKtWpmY.js";
function defineBackground(arg) { function defineBackground(arg) {
if (typeof arg === "function") return { main: arg }; if (arg == null || typeof arg === "function") return { main: arg };
return arg; return arg;
} }
const definition = defineBackground({ const definition = defineBackground({
@@ -289,17 +289,21 @@ describe('Output Directory Structure', () => {
logHello("background"); logHello("background");
} }
}); });
chrome; // @ts-expect-error
((_b = (_a = globalThis.browser) == null ? void 0 : _a.runtime) == null ? void 0 : _b.id) == null ? globalThis.chrome : (
// @ts-expect-error
globalThis.browser
);
function print(method, ...args) { function print(method, ...args) {
return; return;
} }
var logger = { const logger = {
debug: (...args) => print(console.debug, ...args), debug: (...args) => print(console.debug, ...args),
log: (...args) => print(console.log, ...args), log: (...args) => print(console.log, ...args),
warn: (...args) => print(console.warn, ...args), warn: (...args) => print(console.warn, ...args),
error: (...args) => print(console.error, ...args) error: (...args) => print(console.error, ...args)
}; };
var result; let result;
try { try {
initPlugins(); initPlugins();
result = definition.main(); result = definition.main();
@@ -343,10 +347,9 @@ describe('Output Directory Structure', () => {
project.addFile('entrypoints/popup/main.ts', `logHello('popup')`); project.addFile('entrypoints/popup/main.ts', `logHello('popup')`);
await project.build({ await project.build({
experimental: { // Simplify the build output for comparison
// Simplify the build output for comparison extensionApi: 'chrome',
includeBrowserPolyfill: false,
},
vite: () => ({ vite: () => ({
build: { build: {
// Make output for snapshot readible // Make output for snapshot readible
@@ -361,8 +364,9 @@ describe('Output Directory Structure', () => {
---------------------------------------- ----------------------------------------
var _background = function() { var _background = function() {
"use strict"; "use strict";
var _a, _b;
function defineBackground(arg) { function defineBackground(arg) {
if (typeof arg === "function") return { main: arg }; if (arg == null || typeof arg === "function") return { main: arg };
return arg; return arg;
} }
function logHello(name) { function logHello(name) {
@@ -377,17 +381,21 @@ describe('Output Directory Structure', () => {
_background; _background;
function initPlugins() { function initPlugins() {
} }
chrome; // @ts-expect-error
((_b = (_a = globalThis.browser) == null ? void 0 : _a.runtime) == null ? void 0 : _b.id) == null ? globalThis.chrome : (
// @ts-expect-error
globalThis.browser
);
function print(method, ...args) { function print(method, ...args) {
return; return;
} }
var logger = { const logger = {
debug: (...args) => print(console.debug, ...args), debug: (...args) => print(console.debug, ...args),
log: (...args) => print(console.log, ...args), log: (...args) => print(console.log, ...args),
warn: (...args) => print(console.warn, ...args), warn: (...args) => print(console.warn, ...args),
error: (...args) => print(console.error, ...args) error: (...args) => print(console.error, ...args)
}; };
var result; let result;
try { try {
initPlugins(); initPlugins();
result = definition.main(); result = definition.main();
@@ -400,8 +408,8 @@ describe('Output Directory Structure', () => {
logger.error("The background crashed on startup!"); logger.error("The background crashed on startup!");
throw err; throw err;
} }
var background_entrypoint_default = result; const result$1 = result;
return background_entrypoint_default; return result$1;
}(); }();
_background; _background;
" "
+2 -2
View File
@@ -3,7 +3,7 @@ import { TestProject } from '../utils';
describe('Remote Code', () => { describe('Remote Code', () => {
it('should download "url:*" modules and include them in the final bundle', async () => { it('should download "url:*" modules and include them in the final bundle', async () => {
const url = 'https://code.jquery.com/jquery-3.7.1.slim.min.js'; const url = 'https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js';
const project = new TestProject(); const project = new TestProject();
project.addFile( project.addFile(
'entrypoints/popup.ts', 'entrypoints/popup.ts',
@@ -16,7 +16,7 @@ describe('Remote Code', () => {
const output = await project.serializeFile('.output/chrome-mv3/popup.js'); const output = await project.serializeFile('.output/chrome-mv3/popup.js');
expect(output).toContain( expect(output).toContain(
// Some text that will hopefully be in future versions of this script // Some text that will hopefully be in future versions of this script
'jQuery v3.7.1', 'lodash.com',
); );
expect(output).not.toContain(url); expect(output).not.toContain(url);
expect( expect(
@@ -53,7 +53,7 @@ describe('TypeScript Project', () => {
| "/popup.html" | "/popup.html"
| "/sandbox.html" | "/sandbox.html"
type HtmlPublicPath = Extract<PublicPath, \`\${string}.html\`> type HtmlPublicPath = Extract<PublicPath, \`\${string}.html\`>
export interface WxtRuntime extends Runtime.Static { export interface WxtRuntime {
getURL(path: PublicPath): string; getURL(path: PublicPath): string;
getURL(path: \`\${HtmlPublicPath}\${string}\`): string; getURL(path: \`\${HtmlPublicPath}\${string}\`): string;
} }
@@ -233,10 +233,10 @@ describe('TypeScript Project', () => {
---------------------------------------- ----------------------------------------
// Generated by wxt // Generated by wxt
/// <reference types="wxt/vite-builder-env" /> /// <reference types="wxt/vite-builder-env" />
/// <reference types="./types/imports.d.ts" />
/// <reference types="./types/paths.d.ts" /> /// <reference types="./types/paths.d.ts" />
/// <reference types="./types/i18n.d.ts" /> /// <reference types="./types/i18n.d.ts" />
/// <reference types="./types/globals.d.ts" /> /// <reference types="./types/globals.d.ts" />
/// <reference types="./types/imports.d.ts" />
" "
`); `);
}); });
+3 -5
View File
@@ -1,6 +1,6 @@
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { TestProject } from '../utils'; import { TestProject } from '../utils';
import { InlineConfig } from '~/types'; import { InlineConfig } from '../../src/types';
describe('User Config', () => { describe('User Config', () => {
// Root directory is tested with all tests. // Root directory is tested with all tests.
@@ -88,7 +88,7 @@ describe('User Config', () => {
`); `);
}); });
it('should exclude the polyfill when the experimental setting is set to false', async () => { it('should exclude the polyfill when extensionApi="chrome"', async () => {
const buildBackground = async (config?: InlineConfig) => { const buildBackground = async (config?: InlineConfig) => {
const background = `export default defineBackground(() => console.log(browser.runtime.id));`; const background = `export default defineBackground(() => console.log(browser.runtime.id));`;
const projectWithPolyfill = new TestProject(); const projectWithPolyfill = new TestProject();
@@ -101,9 +101,7 @@ describe('User Config', () => {
const withPolyfill = await buildBackground(); const withPolyfill = await buildBackground();
const withoutPolyfill = await buildBackground({ const withoutPolyfill = await buildBackground({
experimental: { extensionApi: 'chrome',
includeBrowserPolyfill: false,
},
}); });
expect(withoutPolyfill).not.toBe(withPolyfill); expect(withoutPolyfill).not.toBe(withPolyfill);
}); });
+4 -2
View File
@@ -97,7 +97,8 @@ describe('Zipping', () => {
expect(await project.fileExists(sourcesZip)).toBe(true); expect(await project.fileExists(sourcesZip)).toBe(true);
}); });
it('should not zip hidden files into sources by default', async () => { // TODO: Fix #738 and re-enable
it.skip('should not zip hidden files into sources by default', async () => {
const project = new TestProject({ const project = new TestProject({
name: 'test', name: 'test',
version: '1.0.0', version: '1.0.0',
@@ -117,7 +118,8 @@ describe('Zipping', () => {
expect(await project.fileExists(unzipDir, '.env')).toBe(false); expect(await project.fileExists(unzipDir, '.env')).toBe(false);
}); });
it('should allow zipping hidden files into sources when explicitly listed', async () => { // TODO: Fix #738 and re-enable
it.skip('should allow zipping hidden files into sources when explicitly listed', async () => {
const project = new TestProject({ const project = new TestProject({
name: 'test', name: 'test',
version: '1.0.0', version: '1.0.0',
+57 -64
View File
@@ -1,7 +1,7 @@
{ {
"name": "wxt", "name": "wxt",
"type": "module", "type": "module",
"version": "0.18.6", "version": "0.19.4",
"description": "Next gen framework for developing web extensions", "description": "Next gen framework for developing web extensions",
"repository": { "repository": {
"type": "git", "type": "git",
@@ -30,75 +30,55 @@
"wxt": "./bin/wxt.mjs", "wxt": "./bin/wxt.mjs",
"wxt-publish-extension": "./bin/wxt-publish-extension.cjs" "wxt-publish-extension": "./bin/wxt-publish-extension.cjs"
}, },
"main": "./dist/index.cjs", "module": "./dist/index.mjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"exports": { "exports": {
".": { ".": {
"import": { "types": "./dist/index.d.ts",
"types": "./dist/index.d.ts", "default": "./dist/index.mjs"
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}, },
"./client": { "./client": {
"types": "./dist/client.d.ts", "types": "./dist/client/index.d.ts",
"import": "./dist/client.js" "default": "./dist/client/index.mjs"
}, },
"./sandbox": { "./sandbox": {
"types": "./dist/sandbox.d.ts", "types": "./dist/sandbox/index.d.ts",
"import": "./dist/sandbox.js" "default": "./dist/sandbox/index.mjs"
}, },
"./browser": { "./browser": {
"types": "./dist/browser.d.ts", "types": "./dist/browser/index.d.ts",
"import": "./dist/browser.js" "default": "./dist/browser/index.mjs"
},
"./browser/chrome": {
"types": "./dist/browser/chrome.d.ts",
"import": "./dist/browser/chrome.mjs"
}, },
"./testing": { "./testing": {
"import": { "types": "./dist/testing/index.d.ts",
"types": "./dist/testing.d.ts", "default": "./dist/testing/index.mjs"
"default": "./dist/testing.js"
},
"require": {
"types": "./dist/testing.d.cts",
"default": "./dist/testing.cjs"
}
}, },
"./storage": { "./storage": {
"import": { "types": "./dist/storage.d.ts",
"types": "./dist/storage.d.ts", "default": "./dist/storage.mjs"
"default": "./dist/storage.js"
},
"require": {
"types": "./dist/storage.d.cts",
"default": "./dist/storage.cjs"
}
}, },
"./vite-builder-env": { "./vite-builder-env": {
"types": "./dist/vite-builder-env.d.ts" "types": "./dist/vite-builder-env.d.ts"
}, },
"./modules": { "./modules": {
"import": { "types": "./dist/modules.d.ts",
"types": "./dist/modules.d.ts", "default": "./dist/modules.mjs"
"default": "./dist/modules.js"
},
"require": {
"types": "./dist/modules.d.cts",
"default": "./dist/modules.cjs"
}
} }
}, },
"scripts": { "scripts": {
"wxt": "tsx src/cli/index.ts", "wxt": "tsx src/cli/index.ts",
"build": "tsx scripts/build.ts", "build": "buildc -- unbuild",
"check": "run-s -c check:*", "check": "pnpm build && run-s -c check:*",
"check:default": "check", "check:default": "check",
"check:tsc-virtual": "tsc --noEmit -p src/virtual", "check:tsc-virtual": "tsc --noEmit -p src/virtual",
"test": "vitest", "test": "buildc --deps-only -- vitest",
"test:e2e": "vitest -r e2e", "test:coverage": "pnpm test -- run --coverage",
"sync-releases": "pnpx changelogen@latest gh release" "sync-releases": "pnpx changelogen@latest gh release",
"prepack": "pnpm build"
}, },
"dependencies": { "dependencies": {
"@aklinker1/rollup-plugin-visualizer": "5.12.0", "@aklinker1/rollup-plugin-visualizer": "5.12.0",
@@ -106,16 +86,17 @@
"@webext-core/fake-browser": "^1.3.1", "@webext-core/fake-browser": "^1.3.1",
"@webext-core/isolated-element": "^1.1.2", "@webext-core/isolated-element": "^1.1.2",
"@webext-core/match-patterns": "^1.0.3", "@webext-core/match-patterns": "^1.0.3",
"async-mutex": "^0.4.1", "async-mutex": "^0.5.0",
"c12": "^1.11.1", "c12": "^1.11.1",
"cac": "^6.7.14", "cac": "^6.7.14",
"chokidar": "^3.6.0", "chokidar": "^3.6.0",
"ci-info": "^4.0.0", "ci-info": "^4.0.0",
"consola": "^3.2.3",
"defu": "^6.1.4", "defu": "^6.1.4",
"dequal": "^2.0.3", "dequal": "^2.0.3",
"esbuild": "^0.19.12", "esbuild": "^0.23.0",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"filesize": "^10.1.2", "filesize": "^10.1.4",
"fs-extra": "^11.2.0", "fs-extra": "^11.2.0",
"get-port": "^7.1.0", "get-port": "^7.1.0",
"giget": "^1.2.3", "giget": "^1.2.3",
@@ -124,40 +105,52 @@
"jiti": "^1.21.6", "jiti": "^1.21.6",
"json5": "^2.2.3", "json5": "^2.2.3",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"linkedom": "^0.18.3", "linkedom": "^0.18.4",
"magicast": "^0.3.4", "magicast": "^0.3.4",
"minimatch": "^9.0.4", "minimatch": "^10.0.1",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"normalize-path": "^3.0.0", "normalize-path": "^3.0.0",
"nypm": "^0.3.8", "nypm": "^0.3.9",
"ohash": "^1.1.3", "ohash": "^1.1.3",
"open": "^10.1.0", "open": "^10.1.0",
"ora": "^7.0.1", "ora": "^8.0.1",
"picocolors": "^1.0.1", "picocolors": "^1.0.1",
"prompts": "^2.4.2", "prompts": "^2.4.2",
"publish-browser-extension": "^2.1.3", "publish-browser-extension": "^2.1.3",
"unimport": "^3.7.2", "unimport": "^3.9.1",
"vite": "^5.3.0", "vite": "^5.3.5",
"web-ext-run": "^0.2.0", "vite-node": "^2.0.4",
"webextension-polyfill": "^0.10.0" "web-ext-run": "^0.2.1",
"webextension-polyfill": "^0.12.0"
}, },
"devDependencies": { "devDependencies": {
"@aklinker1/check": "^1.3.1", "@aklinker1/check": "^1.3.1",
"@faker-js/faker": "^8.4.1", "@faker-js/faker": "^8.4.1",
"@types/chrome": "^0.0.269",
"@types/fs-extra": "^11.0.4", "@types/fs-extra": "^11.0.4",
"@types/lodash.merge": "^4.6.9", "@types/lodash.merge": "^4.6.9",
"@types/natural-compare": "^1.4.3", "@types/natural-compare": "^1.4.3",
"@types/node": "^20.14.2", "@types/node": "^20.14.12",
"@types/normalize-path": "^3.0.2", "@types/normalize-path": "^3.0.2",
"@types/prompts": "^2.4.9", "@types/prompts": "^2.4.9",
"execa": "^9.2.0", "execa": "^9.3.0",
"extract-zip": "^2.0.1", "extract-zip": "^2.0.1",
"happy-dom": "^13.10.1", "happy-dom": "^14.12.3",
"lodash.merge": "^4.6.2", "lodash.merge": "^4.6.2",
"p-map": "^7.0.2", "p-map": "^7.0.2",
"publint": "^0.2.8", "publint": "^0.2.9",
"tsup": "^8.1.0", "tsx": "4.15.7",
"tsx": "^4.15.4", "typescript": "^5.5.4",
"typescript": "^5.4.5" "unbuild": "^2.0.0",
"vitest": "^2.0.4",
"vitest-plugin-random-seed": "^1.1.0"
},
"peerDependencies": {
"@types/chrome": "*"
},
"peerDependenciesMeta": {
"@types/chrome": {
"optional": true
}
} }
} }

Some files were not shown because too many files have changed in this diff Show More