From 1fe01290c0a1e923e1acfbe1bf0205feff8f1e2c Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 18 Oct 2024 09:28:26 -0500 Subject: [PATCH] docs: Rewrite and restructure the documentation website (#933) Co-authored-by: aklinker1 --- README.md | 2 +- docs/.old/development.md | 116 ---- .../components/EntrypointPatterns.vue | 6 +- docs/.vitepress/config.ts | 175 +++--- docs/.vitepress/theme/custom.css | 17 - docs/.vitepress/utils/menus.ts | 43 +- docs/assets/init-demo.gif | Bin 139656 -> 140670 bytes docs/auto-icons.md | 1 + docs/get-started/assets.md | 33 -- docs/get-started/compare.md | 47 -- docs/get-started/configuration.md | 57 -- docs/get-started/entrypoints.md | 60 -- docs/get-started/installation.md | 120 ---- docs/get-started/introduction.md | 47 -- docs/guide/directory-structure/app-config.md | 61 -- docs/guide/directory-structure/assets.md | 42 -- docs/guide/directory-structure/components.md | 5 - docs/guide/directory-structure/composables.md | 5 - .../entrypoints/background.md | 47 -- .../entrypoints/bookmarks.md | 31 - .../entrypoints/content-scripts.md | 107 ---- .../directory-structure/entrypoints/css.md | 44 -- .../entrypoints/devtools.md | 40 -- .../entrypoints/history.md | 31 - .../directory-structure/entrypoints/newtab.md | 31 - .../entrypoints/options.md | 36 -- .../directory-structure/entrypoints/popup.md | 43 -- .../entrypoints/sandbox.md | 37 -- .../entrypoints/sidepanel.md | 49 -- .../entrypoints/unlisted-pages.md | 49 -- .../entrypoints/unlisted-scripts.md | 37 -- docs/guide/directory-structure/env.md | 5 - docs/guide/directory-structure/hooks.md | 5 - docs/guide/directory-structure/output.md | 5 - docs/guide/directory-structure/package.md | 5 - .../guide/directory-structure/public/index.md | 35 -- .../directory-structure/public/locales.md | 5 - docs/guide/directory-structure/tsconfig.md | 5 - docs/guide/directory-structure/utils.md | 5 - .../directory-structure/web-ext-config.md | 65 --- docs/guide/directory-structure/wxt-config.md | 5 - docs/guide/directory-structure/wxt.md | 5 - docs/guide/essentials/assets.md | 82 +++ docs/guide/essentials/config/auto-imports.md | 112 ++++ .../essentials/config/browser-startup.md | 85 +++ docs/guide/essentials/config/build-mode.md | 29 + .../essentials/config/entrypoint-loaders.md | 79 +++ .../config/environment-variables.md | 54 ++ docs/guide/essentials/config/hooks.md | 22 + docs/guide/essentials/config/manifest.md | 258 +++++++++ docs/guide/essentials/config/runtime.md | 56 ++ docs/guide/essentials/config/typescript.md | 65 +++ docs/guide/essentials/config/vite.md | 68 +++ .../content-scripts.md} | 235 +++++++- docs/guide/essentials/e2e-testing.md | 9 + docs/guide/essentials/entrypoints.md | 535 ++++++++++++++++++ docs/guide/essentials/es-modules.md | 38 ++ docs/guide/essentials/extension-apis.md | 92 +++ .../frontend-frameworks.md | 51 +- docs/guide/essentials/i18n.md | 86 +++ docs/guide/essentials/messaging.md | 16 + docs/guide/essentials/project-structure.md | 101 ++++ .../essentials}/publishing.md | 34 +- .../{go-further => essentials}/remote-code.md | 0 .../scripting.md | 8 +- docs/guide/essentials/storage.md | 15 + .../essentials/target-different-browsers.md | 69 +++ docs/guide/essentials/testing-updates.md | 28 + docs/guide/essentials/unit-testing.md | 80 +++ docs/guide/essentials/wxt-modules.md | 242 ++++++++ docs/guide/extension-apis/i18n.md | 56 -- docs/guide/extension-apis/messaging.md | 36 -- docs/guide/extension-apis/others.md | 5 - docs/guide/go-further/custom-events.md | 5 - docs/guide/go-further/debugging.md | 5 - docs/guide/go-further/entrypoint-loaders.md | 120 ---- docs/guide/go-further/es-modules.md | 40 -- docs/guide/go-further/handling-updates.md | 77 --- docs/guide/go-further/reusable-modules.md | 186 ------ docs/guide/go-further/testing.md | 27 - docs/guide/go-further/vite.md | 39 -- docs/guide/i18n/build-integrations.md | 82 --- docs/guide/i18n/editor-support.md | 48 -- docs/guide/i18n/installation.md | 81 --- docs/guide/i18n/introduction.md | 22 - docs/guide/i18n/messages-file-format.md | 170 ------ docs/guide/installation.md | 123 ++++ docs/guide/introduction.md | 26 + docs/guide/key-concepts/auto-imports.md | 117 ---- docs/guide/key-concepts/manifest.md | 249 -------- docs/guide/key-concepts/multiple-browsers.md | 133 ----- .../key-concepts/web-extension-polyfill.md | 108 ---- docs/guide/key-concepts/wxt-submit.md | 9 - docs/guide/resources/compare.md | 57 ++ docs/guide/resources/faq.md | 21 + .../how-wxt-works.md | 0 .../resources/migrate.md} | 41 +- .../wxt.md => resources/upgrading.md} | 29 +- docs/i18n.md | 5 + docs/index.md | 26 +- docs/public/_redirects | 69 +++ docs/{guide/extension-apis => }/storage.md | 31 +- packages/auto-icons/README.md | 2 + packages/i18n/README.md | 369 +++++++++++- packages/wxt/README.md | 2 +- packages/wxt/src/browser/chrome.ts | 2 + .../src/client/content-scripts/ui/index.ts | 6 +- packages/wxt/src/core/builders/vite/index.ts | 2 +- packages/wxt/src/core/generate-wxt-dir.ts | 2 +- packages/wxt/src/virtual/README.md | 2 +- 110 files changed, 3347 insertions(+), 3196 deletions(-) delete mode 100644 docs/.old/development.md create mode 100644 docs/auto-icons.md delete mode 100644 docs/get-started/assets.md delete mode 100644 docs/get-started/compare.md delete mode 100644 docs/get-started/configuration.md delete mode 100644 docs/get-started/entrypoints.md delete mode 100644 docs/get-started/installation.md delete mode 100644 docs/get-started/introduction.md delete mode 100644 docs/guide/directory-structure/app-config.md delete mode 100644 docs/guide/directory-structure/assets.md delete mode 100644 docs/guide/directory-structure/components.md delete mode 100644 docs/guide/directory-structure/composables.md delete mode 100644 docs/guide/directory-structure/entrypoints/background.md delete mode 100644 docs/guide/directory-structure/entrypoints/bookmarks.md delete mode 100644 docs/guide/directory-structure/entrypoints/content-scripts.md delete mode 100644 docs/guide/directory-structure/entrypoints/css.md delete mode 100644 docs/guide/directory-structure/entrypoints/devtools.md delete mode 100644 docs/guide/directory-structure/entrypoints/history.md delete mode 100644 docs/guide/directory-structure/entrypoints/newtab.md delete mode 100644 docs/guide/directory-structure/entrypoints/options.md delete mode 100644 docs/guide/directory-structure/entrypoints/popup.md delete mode 100644 docs/guide/directory-structure/entrypoints/sandbox.md delete mode 100644 docs/guide/directory-structure/entrypoints/sidepanel.md delete mode 100644 docs/guide/directory-structure/entrypoints/unlisted-pages.md delete mode 100644 docs/guide/directory-structure/entrypoints/unlisted-scripts.md delete mode 100644 docs/guide/directory-structure/env.md delete mode 100644 docs/guide/directory-structure/hooks.md delete mode 100644 docs/guide/directory-structure/output.md delete mode 100644 docs/guide/directory-structure/package.md delete mode 100644 docs/guide/directory-structure/public/index.md delete mode 100644 docs/guide/directory-structure/public/locales.md delete mode 100644 docs/guide/directory-structure/tsconfig.md delete mode 100644 docs/guide/directory-structure/utils.md delete mode 100644 docs/guide/directory-structure/web-ext-config.md delete mode 100644 docs/guide/directory-structure/wxt-config.md delete mode 100644 docs/guide/directory-structure/wxt.md create mode 100644 docs/guide/essentials/assets.md create mode 100644 docs/guide/essentials/config/auto-imports.md create mode 100644 docs/guide/essentials/config/browser-startup.md create mode 100644 docs/guide/essentials/config/build-mode.md create mode 100644 docs/guide/essentials/config/entrypoint-loaders.md create mode 100644 docs/guide/essentials/config/environment-variables.md create mode 100644 docs/guide/essentials/config/hooks.md create mode 100644 docs/guide/essentials/config/manifest.md create mode 100644 docs/guide/essentials/config/runtime.md create mode 100644 docs/guide/essentials/config/typescript.md create mode 100644 docs/guide/essentials/config/vite.md rename docs/guide/{key-concepts/content-script-ui.md => essentials/content-scripts.md} (58%) create mode 100644 docs/guide/essentials/e2e-testing.md create mode 100644 docs/guide/essentials/entrypoints.md create mode 100644 docs/guide/essentials/es-modules.md create mode 100644 docs/guide/essentials/extension-apis.md rename docs/guide/{key-concepts => essentials}/frontend-frameworks.md (56%) create mode 100644 docs/guide/essentials/i18n.md create mode 100644 docs/guide/essentials/messaging.md create mode 100644 docs/guide/essentials/project-structure.md rename docs/{get-started => guide/essentials}/publishing.md (84%) rename docs/guide/{go-further => essentials}/remote-code.md (100%) rename docs/guide/{extension-apis => essentials}/scripting.md (70%) create mode 100644 docs/guide/essentials/storage.md create mode 100644 docs/guide/essentials/target-different-browsers.md create mode 100644 docs/guide/essentials/testing-updates.md create mode 100644 docs/guide/essentials/unit-testing.md create mode 100644 docs/guide/essentials/wxt-modules.md delete mode 100644 docs/guide/extension-apis/i18n.md delete mode 100644 docs/guide/extension-apis/messaging.md delete mode 100644 docs/guide/extension-apis/others.md delete mode 100644 docs/guide/go-further/custom-events.md delete mode 100644 docs/guide/go-further/debugging.md delete mode 100644 docs/guide/go-further/entrypoint-loaders.md delete mode 100644 docs/guide/go-further/es-modules.md delete mode 100644 docs/guide/go-further/handling-updates.md delete mode 100644 docs/guide/go-further/reusable-modules.md delete mode 100644 docs/guide/go-further/testing.md delete mode 100644 docs/guide/go-further/vite.md delete mode 100644 docs/guide/i18n/build-integrations.md delete mode 100644 docs/guide/i18n/editor-support.md delete mode 100644 docs/guide/i18n/installation.md delete mode 100644 docs/guide/i18n/introduction.md delete mode 100644 docs/guide/i18n/messages-file-format.md create mode 100644 docs/guide/installation.md create mode 100644 docs/guide/introduction.md delete mode 100644 docs/guide/key-concepts/auto-imports.md delete mode 100644 docs/guide/key-concepts/manifest.md delete mode 100644 docs/guide/key-concepts/multiple-browsers.md delete mode 100644 docs/guide/key-concepts/web-extension-polyfill.md delete mode 100644 docs/guide/key-concepts/wxt-submit.md create mode 100644 docs/guide/resources/compare.md create mode 100644 docs/guide/resources/faq.md rename docs/guide/{go-further => resources}/how-wxt-works.md (100%) rename docs/{get-started/migrate-to-wxt.md => guide/resources/migrate.md} (67%) rename docs/guide/{upgrade-guide/wxt.md => resources/upgrading.md} (89%) create mode 100644 docs/i18n.md rename docs/{guide/extension-apis => }/storage.md (96%) diff --git a/README.md b/README.md index 3808327c..295b4d77 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Or see the [installation guide](https://wxt.dev/guide/installation.html) to get - 🦾 Auto-imports - 🤖 Automated publishing - 🎨 Frontend framework agnostic: works with Vue, React, Svelte, etc -- 📦 Modular architecture with [WXT modules](https://wxt.dev/guide/go-further/reusable-modules.html#overview) +- 📦 [Module system](https://wxt.dev/guide/essentials/wxt-modules.html#overview) for reusing code between extensions - 🖍️ Quickly bootstrap a new project - 📏 Bundle analysis - ⬇️ Download and bundle remote URL imports diff --git a/docs/.old/development.md b/docs/.old/development.md deleted file mode 100644 index 50098add..00000000 --- a/docs/.old/development.md +++ /dev/null @@ -1,116 +0,0 @@ -# Development - -WXT's main goal is providing the best DX it possibly can. When running your extension in dev mode, each part of your extension is reloaded separately when possible. - -| | HMR | Reloaded individually | Reload extension | Restart browser | -| ------------------- | :-: | :-------------------: | :--------------: | :----------------------------------------------------: | -| HTML File | | ✅ | -| HTML Dependency | ✅ | -| MV3 Content Script | | ✅ | -| MV2 Content Script | | | ✅ | -| Background | | | ✅ | -| manifest.json | | | | 🟡 See [#16](https://github.com/wxt-dev/wxt/issues/16) | -| `wxt.config.ts` | | | | 🟡 See [#10](https://github.com/wxt-dev/wxt/issues/10) | -| `web-ext.config.ts` | | | | 🟡 See [#10](https://github.com/wxt-dev/wxt/issues/10) | - -## Dev Mode vs Production Builds - -There are some notable differences between the development and production versions of an extension. During development: - -1. **Content scripts are not listed in the `manifest.json`** when targeting MV3. Instead, the [`scripting`](https://developer.chrome.com/docs/extensions/reference/api/scripting) permission is used to register content scripts at runtime so they can be reloaded individually. - - To get the list of content scripts during development, run the following in the background's console: - - ```ts - await chrome.scripting.getRegisteredContentScripts(); - ``` - -2. **The CSP is modified to allow loading scripts from the dev server**. Make sure you're using Chrome v110 or above for HMR to work. - -3. If you don't include a background script/service worker, one will be created to perform various tasks in dev mode, mostly related to reloading different parts of the extension on change. - -For production builds, none of the above modifications will be applied, and you're extension/manifest will only include what you have defined. - -## Configure Browser Startup - -WXT uses [`web-ext` by Mozilla](https://github.com/mozilla/web-ext) to automatically open a browser with the extension installed. You can configure the runner's behavior via the [`runner`](/api/reference/wxt/interfaces/InlineConfig#runner) option, or in a separate gitignored file, `web-ext.config.ts`. - -:::code-group - -```ts [wxt.config.ts] -import { defineConfig } from 'wxt'; - -export default defineConfig({ - runner: { - // Runner config - }, -}); -``` - -```ts [web-ext.config.ts] -import { defineRunnerConfig } from 'wxt'; - -export default defineRunnerConfig({ - // Runner config -}); -``` - -::: - -### Browser Binaries - -`web-ext`'s browser discovery is very limited. By default, it only guesses at where Chrome and Firefox are installed. If you've customized your install locations, you may need to tell `web-ext` where the binaries/executables are located using the [`binaries` option](/api/reference/wxt/interfaces/ExtensionRunnerConfig#binaries). For other Chromium based browsers, like Edge or Opera, you'll need to explicitly list them in the `binaries` option as well, otherwise they will open in Chrome by default. - -```ts -// ~/web-ext.config.ts -import { defineRunnerConfig } from 'wxt'; - -export default defineRunnerConfig({ - binaries: { - chrome: '/path/to/chrome-beta', // Use Chrome Beta instead of regular Chrome - firefox: 'firefoxdeveloperedition', // Use Firefox Developer Edition instead of regular Firefox - edge: '/path/to/edge', // Open MS Edge when running "wxt -b edge" - }, -}); -``` - -:::tip -When configuring browser binaries, it's helpful to put them in `~/web-ext.config.ts` instead of the project directory's `web-ext.config.ts` file. When placed in your home directory (`~/`), this config will be used by all WXT projects, so you only need to configure the binaries once. -::: - -### Other options - -You can customize other options as well, like startup URLs, profiles, or additional command line arguments: - -```ts -// web-ext.config.ts -import { defineRunnerConfig } from 'wxt'; - -export default defineRunnerConfig({ - startUrls: ['https://google.com', 'https://duckduckgo.com'], - chromiumProfile: '/path/to/profile/to/use', - chromiumArgs: ['--window-size=400,300'], -}); -``` - -For a full list of options, see the [API Reference](/api/reference/wxt/interfaces/ExtensionRunnerConfig). - -## Reload the Extension - -Normally, to manually reload an extension, you have to visit `chrome://extensions` and click the reload button for your extension. - -When running `wxt` command to start the dev server, WXT adds a keyboard shortcut `Alt+R`, that reloads the extension when pressed, without visiting `chrome://extensions`. This can also be customized or disabled: - -```ts [wxt.config.ts] -import { defineConfig } from 'wxt'; - -export default defineConfig({ - dev: { - reloadCommand: 'Alt+T', // false, to disable - }, -}); -``` - -:::info -This shortcut is only available during development, and is not be added to your extension when running `wxt build` or `wxt-zip`. -::: diff --git a/docs/.vitepress/components/EntrypointPatterns.vue b/docs/.vitepress/components/EntrypointPatterns.vue index 0600a066..8f73d7c2 100644 --- a/docs/.vitepress/components/EntrypointPatterns.vue +++ b/docs/.vitepress/components/EntrypointPatterns.vue @@ -8,14 +8,14 @@ const props = defineProps<{ - + - - diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 33a97536..87f398dc 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -8,6 +8,9 @@ import { prepareTypedocSidebar, } from './utils/menus'; import { meta, script } from './utils/head'; +import { version as wxtVersion } from '../../packages/wxt/package.json'; +import { version as i18nVersion } from '../../packages/i18n/package.json'; +import { version as autoIconsVersion } from '../../packages/auto-icons/package.json'; const title = 'Next-gen Web Extension Framework'; const titleSuffix = ' – WXT'; @@ -64,111 +67,93 @@ export default defineConfig({ ], nav: [ - navItem('Get Started', '/get-started/introduction'), - navItem('Guide', '/guide/key-concepts/manifest'), - navItem('API', '/api/reference/wxt'), + navItem('Guide', '/guide/installation'), navItem('Examples', '/examples'), + navItem('API', '/api/reference/wxt'), + navItem(`v${wxtVersion}`, [ + navItem('wxt', [ + navItem(`v${wxtVersion}`, '/'), + navItem( + `Changelog`, + 'https://github.com/wxt-dev/wxt/blob/main/packages/wxt/CHANGELOG.md', + ), + ]), + navItem('Other Packages', [ + navItem(`wxt/storage — ${wxtVersion}`, '/storage'), + navItem(`@wxt-dev/auto-icons — ${autoIconsVersion}`, '/auto-icons'), + navItem(`@wxt-dev/i18n — ${i18nVersion}`, '/i18n'), + ]), + ]), ], sidebar: { - '/get-started/': menuRoot([ - menuGroup('Get Started', '/get-started/', [ - menuItem('Introduction', 'introduction'), - menuItem('Installation', 'installation'), - menuItem('Configuration', 'configuration'), - menuItem('Entrypoints', 'entrypoints'), - menuItem('Assets', 'assets'), - menuItem('Publishing', 'publishing'), - menuItem('Migrate to WXT', 'migrate-to-wxt'), - menuItem('Compare', 'compare'), - ]), - ]), '/guide/': menuRoot([ - menuGroup('Key Concepts', '/guide/key-concepts/', [ - menuItem('Manifest', 'manifest'), - menuItem('Auto-imports', 'auto-imports'), - menuItem('Web Extension Polyfill', 'web-extension-polyfill'), - menuItem('Frontend Frameworks', 'frontend-frameworks'), - menuItem('Content Script UI', 'content-script-ui'), - ]), - menuGroup('Directory Structure', '/guide/directory-structure/', [ - // Folders - menuItem('.output/', 'output'), - menuItem('.wxt/', 'wxt'), - menuItem('assets/', 'assets'), - menuItem('components/', 'components'), - menuItem('composables/', 'composables'), - menuGroup('entrypoints/', '/guide/directory-structure/entrypoints/', [ - menuItem('background', 'background.md'), - menuItem('bookmarks', 'bookmarks.md'), - menuItem('*.content.ts', 'content-scripts.md'), - menuItem('*.css', 'css.md'), - menuItem('devtools', 'devtools.md'), - menuItem('history', 'history.md'), - menuItem('newtab', 'newtab.md'), - menuItem('options', 'options.md'), - menuItem('popup', 'popup.md'), - menuItem('sandbox', 'sandbox.md'), - menuItem('sidepanel', 'sidepanel.md'), - menuItem('*.html', 'unlisted-pages.md'), - menuItem('*.ts', 'unlisted-scripts.md'), - ]), - menuItem('hooks/', 'hooks'), - menuItem('public/', 'public/', [ - menuItem('_locales/', 'public/locales'), - ]), - menuItem('utils/', 'utils'), - - // Files - menuItem('.env', 'env'), - menuItem('app.config.ts', 'app-config'), - menuItem('package.json', 'package'), - menuItem('tsconfig.json', 'tsconfig'), - menuItem('web-ext.config.ts', 'web-ext-config'), - menuItem('wxt.config.ts', 'wxt-config'), - ]), - menuGroup('Extension APIs', '/guide/extension-apis/', [ - menuItem('Storage', 'storage'), - menuItem('Messaging', 'messaging'), - menuItem('I18n', 'i18n'), - menuItem('Scripting', 'scripting'), - menuItem('Others', 'others'), - ]), - menuGroup('Go Further', '/guide/go-further/', [ - menuItem('Testing', 'testing'), - menuItem('ES Modules', 'es-modules'), - menuItem('Debugging', 'debugging'), - menuItem('Handling Updates', 'handling-updates'), - menuItem('Vite', 'vite'), - menuItem('Custom Events', 'custom-events'), - menuItem('Reusable Modules', 'reusable-modules'), - menuItem('Remote Code', 'remote-code'), - menuItem('Entrypoint Loaders', 'entrypoint-loaders'), - menuItem('How WXT Works', 'how-wxt-works'), - ]), - menuGroup('Upgrade Guide', '/guide/upgrade-guide/', [ - menuItem('wxt', 'wxt'), - ]), - menuGroup('@wxt-dev/i18n', '/guide/i18n/', [ + menuGroup('Get Started', '/guide/', [ menuItem('Introduction', 'introduction.md'), menuItem('Installation', 'installation.md'), - menuItem('Messages File Format', 'messages-file-format.md'), - menuItem('Build Integrations', 'build-integrations.md'), - menuItem('Editor Support', 'editor-support.md'), + ]), + menuGroup('Essentials', '/guide/essentials/', [ + menuItem('Project Structure', 'project-structure.md'), + menuItem('Entrypoints', 'entrypoints.md'), + menuGroup( + 'Configuration', + '/guide/essentials/config/', + [ + menuItem('Manifest', 'manifest.md'), + menuItem('Browser Startup', 'browser-startup.md'), + menuItem('Auto-imports', 'auto-imports.md'), + menuItem('Environment Variables', 'environment-variables.md'), + menuItem('Runtime Config', 'runtime.md'), + menuItem('Vite', 'vite.md'), + menuItem('Build Mode', 'build-mode.md'), + menuItem('TypeScript', 'typescript.md'), + menuItem('Hooks', 'hooks.md'), + menuItem('Entrypoint Loaders', 'entrypoint-loaders.md'), + ], + true, + ), + menuItem('Extension APIs', 'extension-apis.md'), + menuItem('Assets', 'assets.md'), + menuItem('Target Different Browsers', 'target-different-browsers.md'), + menuItem('Content Scripts', 'content-scripts.md'), + menuItem('Storage', 'storage.md'), + menuItem('Messaging', 'messaging.md'), + menuItem('I18n', 'i18n.md'), + menuItem('Scripting', 'scripting.md'), + menuItem('WXT Modules', 'wxt-modules.md'), + menuItem('Frontend Frameworks', 'frontend-frameworks.md'), + menuItem('ES Modules', 'es-modules.md'), + menuItem('Remote Code', 'remote-code.md'), + menuItem('Unit Testing', 'unit-testing.md'), + menuItem('E2E Testing', 'e2e-testing.md'), + menuItem('Publishing', 'publishing.md'), + menuItem('Testing Updates', 'testing-updates.md'), + ]), + menuGroup('Resources', '/guide/resources/', [ + menuItem('Compare', 'compare.md'), + menuItem('FAQ', 'faq.md'), + menuItem('Upgrading WXT', 'upgrading.md'), + menuItem('Migrate to WXT', 'migrate.md'), + menuItem('How WXT Works', 'how-wxt-works.md'), ]), ]), '/api/': menuRoot([ - menuGroup('CLI', '/api/cli/', [ - menuItem('wxt', 'wxt.md'), - menuItem('wxt build', 'wxt-build.md'), - menuItem('wxt zip', 'wxt-zip.md'), - menuItem('wxt prepare', 'wxt-prepare.md'), - menuItem('wxt clean', 'wxt-clean.md'), - menuItem('wxt init', 'wxt-init.md'), - menuItem('wxt submit', 'wxt-submit.md'), - menuItem('wxt submit init', 'wxt-submit-init.md'), - ]), - menuGroup('API Reference', prepareTypedocSidebar(typedocSidebar)), + menuGroup( + 'CLI Reference', + '/api/cli/', + [ + menuItem('wxt', 'wxt.md'), + menuItem('wxt build', 'wxt-build.md'), + menuItem('wxt zip', 'wxt-zip.md'), + menuItem('wxt prepare', 'wxt-prepare.md'), + menuItem('wxt clean', 'wxt-clean.md'), + menuItem('wxt init', 'wxt-init.md'), + menuItem('wxt submit', 'wxt-submit.md'), + menuItem('wxt submit init', 'wxt-submit-init.md'), + ], + true, + ), + menuGroup('API Reference', prepareTypedocSidebar(typedocSidebar), true), ]), }, }, diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css index 1d249f5a..a7aa5980 100644 --- a/docs/.vitepress/theme/custom.css +++ b/docs/.vitepress/theme/custom.css @@ -85,23 +85,6 @@ body { user-select: none; } -.VPSidebarItem.level-0.collapsible { - padding-bottom: 0.5rem; -} - -.VPSidebarItem.level-0.collapsible .items { - /*border-left: 1px solid var(--vp-c-divider);*/ -} - -.VPSidebarItem.level-1 { - padding-left: 0.75rem; -} - -.VPSidebar .group + .group { - border-top: none; - padding-top: 0; -} - .VPSidebarItem .badge { display: inline-block; min-width: 1.6em; diff --git a/docs/.vitepress/utils/menus.ts b/docs/.vitepress/utils/menus.ts index aad00c56..8395cabb 100644 --- a/docs/.vitepress/utils/menus.ts +++ b/docs/.vitepress/utils/menus.ts @@ -2,9 +2,20 @@ import { DefaultTheme } from 'vitepress'; type SidebarItem = DefaultTheme.SidebarItem; type NavItem = DefaultTheme.NavItem; +type NavItemWithLink = DefaultTheme.NavItemWithLink; +type NavItemWithChildren = DefaultTheme.NavItemWithChildren; +type NavItemChildren = DefaultTheme.NavItemChildren; -export function navItem(text: string, link: string): NavItem { - return { text, link }; +export function navItem(text: string): NavItemChildren; +export function navItem(text: string, link: string): NavItemChildren; +export function navItem(text: string, items: any[]): NavItemWithChildren; +export function navItem(text: string, arg2?: unknown): any { + if (typeof arg2 === 'string') { + return { text, link: arg2 }; + } else if (Array.isArray(arg2)) { + return { text, items: arg2 }; + } + return { text }; } export function menuRoot(items: SidebarItem[]) { @@ -14,31 +25,39 @@ export function menuRoot(items: SidebarItem[]) { }); } -export function menuGroup(text: string, items: SidebarItem[]): SidebarItem; +export function menuGroup( + text: string, + items: SidebarItem[], + collapsable?: boolean, +): SidebarItem; export function menuGroup( text: string, base: string, items: SidebarItem[], + collapsable?: boolean, ): SidebarItem; export function menuGroup( text: string, a: string | SidebarItem[], - b?: SidebarItem[], + b?: SidebarItem[] | boolean, + c?: boolean, ): SidebarItem { - const collapsed = true; - if (typeof a === 'string') { + if (typeof a === 'string' && Array.isArray(b)) { return { text, base: a, items: b, - collapsed, + collapsed: c, }; } - return { - text, - items: a, - collapsed, - }; + if (typeof a !== 'string' && !Array.isArray(b)) + return { + text, + items: a, + collapsed: b, + }; + + throw Error('Unknown overload'); } export function menuItems(items: SidebarItem[]) { diff --git a/docs/assets/init-demo.gif b/docs/assets/init-demo.gif index 474db34c2e2bf5c7a3d456c330fddd6e33b41a1b..353c8b73aaa92ed97061b187bfbc35bca429b93f 100644 GIT binary patch delta 129730 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�vd046 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 @ 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 RFV1H)rAm$1_(~GcRAxrp3x` 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�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

P%+h6TR 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

PO= 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

dO@#QTs8+qdUo>M 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 diff --git a/docs/auto-icons.md b/docs/auto-icons.md new file mode 100644 index 00000000..474e842c --- /dev/null +++ b/docs/auto-icons.md @@ -0,0 +1 @@ + diff --git a/docs/get-started/assets.md b/docs/get-started/assets.md deleted file mode 100644 index f8ef639a..00000000 --- a/docs/get-started/assets.md +++ /dev/null @@ -1,33 +0,0 @@ -# Assets - -WXT has two directories for storing assets like CSS, images, or fonts. - -- [public directory](/guide/directory-structure/public/): Store files that will be copied into the output directory as-is -- [assets directory](/guide/directory-structure/assets): Store files that will be processed by Vite during the build process - -To learn more about how to use assets at runtime from either of these directories, visit their guides linked above. - -## Public Directory - -Place static files like the extension icon or `_locales/` directory here. These files will be copied over to the output directory without being transformed by Vite. - -``` - -└─ public/ - ├─ icon-16.png - ├─ icon-32.png - ├─ icon-48.png - ├─ icon-96.png - └─ icon-128.png -``` - -## Assets Directory - -Files in the assets directory will be processed by Vite. They are imported in your source code, and will be transformed or renamed in the output directory. - -``` - -└─ assets/ - ├─ tailwind.css - └─ illustration.svg -``` diff --git a/docs/get-started/compare.md b/docs/get-started/compare.md deleted file mode 100644 index 37e9e9ea..00000000 --- a/docs/get-started/compare.md +++ /dev/null @@ -1,47 +0,0 @@ -# Compare - -Lets compare the features of WXT vs [Plasmo](https://docs.plasmo.com/framework) (another framework) and [CRXJS](https://crxjs.dev/vite-plugin) (a bundler plugin). - -## Overview - -| Features | WXT | Plasmo | CRXJS | -| ---------------------------------------------------- | :--------------: | :-------------: | :--------------: | -| Supports all browsers | ✅ | ✅ | 🟡 10 | -| MV2 Support | ✅ | ✅ | 🟡 1 | -| MV3 Support | ✅ | ✅ | 🟡 1 | -| Create Extension ZIPs | ✅ | ✅ | ❌ | -| Create Firefox Sources ZIP | ✅ | ❌ | ❌ | -| First-class TypeScript support | ✅ | ✅ | ✅ | -| Entrypoint discovery | ✅ 2 | ✅ 2 | ❌ | -| Inline entrypoint config | ✅ | ✅ | ❌ 9 | -| Auto-imports | ✅ | ❌ | ❌ | -| Supports all frontend frameworks | ✅ | 🟡 3 | ✅ | -| Framework specific entrypoints (like `Popup.tsx`) | 🟡 4 | ✅ 5 | ❌ | -| Automated publishing | ✅ | ✅ | ❌ | -| Remote Code Bundling (Google Analytics) | ✅ | ✅ | ❌ | -| Dev Mode | | | -| `.env` Files | ✅ | ✅ | ✅ | -| Opens browser with extension installed | ✅ | ❌ | ❌ | -| HMR for UIs | ✅ | 🟡 6 | ✅ | -| Reload HTML Files on Change | ✅ | 🟡 7 | ✅ | -| Reload Content Scripts on Change | ✅ | 🟡 7 | ✅ | -| Reload Background on Change | 🟡 7 | 🟡 7 | 🟡 7 | -| Respects Content Script `run_at` | ✅ | ✅ | ❌ 8 | -| Built-in Utils | | | | -| Storage | ✅ | ✅ | ❌ 11 | -| Messaging | ❌ 11 | ✅ | ❌ 11 | -| Content Script UI | ✅ | ✅ | ❌ 11 | - - - 1: Either MV2 or MV3, not both. -
2: File based. -
3: Only React, Vue, and Svelte. -
4: .html .ts .tsx. -
5: .html .ts .tsx. .vue .svelte. -
6: React only. -
7: Reloads entire extension. -
8: ESM-style loaders run asynchronously. -
9: Entrypoint options all configured in `manifest.json`. -
10: As of v2.0.0-beta.23, but v2 stable hasn't been released yet. -
11: There is no built-in wrapper around this API. However, you can still access the standard APIs via chrome/browser globals or use any 3rd party NPM package. -
diff --git a/docs/get-started/configuration.md b/docs/get-started/configuration.md deleted file mode 100644 index 04cb62ef..00000000 --- a/docs/get-started/configuration.md +++ /dev/null @@ -1,57 +0,0 @@ -# Configuration - -By default, WXT provides sensible configuration for bundling web extensions with Vite. - -## Config File - -To configure WXT, create a `wxt.config.ts` file in your project root. It should have the following contents: - -```ts -import { defineConfig } from 'wxt'; - -export default defineConfig({ - // My WXT config -}); -``` - -:::info -For more information on configuring WXT via the `wxt.config.ts` file, read the dedicated [`wxt.config.ts` guide](/guide/directory-structure/wxt-config). -::: - -## Manifest.json - -WXT generates your extension's `manifest.json` based on the project structure. To add additional properties, like permissions, use the [`manifest` property](/api/reference/wxt/interfaces/InlineConfig#manifest). - -```ts -import { defineConfig } from 'wxt'; - -export default defineConfig({ - manifest: { - permissions: ['storage'], - }, -}); -``` - -:::info -For more information on configuring the manifest, read the dedicated [Manifest guide](/guide/key-concepts/manifest). -::: - -## Environment - -WXT can read `.env` files, and variables are accessible via `import.meta.env.*`. - -:::code-group - -```sh [.env] -VITE_OAUTH_CLIENT_ID=abc123 -``` - -```ts [JS] -import.meta.env.VITE_OAUTH_CLIENT_ID; -``` - -::: - -:::info -For more information on using .env files, read the dedicated [`.env` guide](/guide/directory-structure/env). -::: diff --git a/docs/get-started/entrypoints.md b/docs/get-started/entrypoints.md deleted file mode 100644 index 65b7bf08..00000000 --- a/docs/get-started/entrypoints.md +++ /dev/null @@ -1,60 +0,0 @@ -# Entrypoints - -An "entrypoint" is any HTML, JS, or CSS file that needs to be bundled and included with your extension, which will be loaded and executed by the browser. - -## Defining Entrypoints - -In WXT, you create an entrypoint by adding a file to the `entrypoints/` directory. - -``` - -└─ entrypoints/ - ├─ background.ts - ├─ content.ts - ├─ injected.ts - └─ popup.html -``` - -Some entrypoint filesname patterns are reserved by WXT and effect how the manifest is generated. - -- `popup` adds an `action` to the manifest -- `background` adds a background script/service worker -- `*.content.ts` adds a content script -- ... - -> For a full list of recognized filenames, see the the [Entrypoints Directory guide](/guide/directory-structure/entrypoints/background). - -Any other files, whether JS, CSS, or HTML, is considered "unlisted". Unlisted files, like `injected.ts` from above, are just bundled to the output directory and not added to the manifest. You can still access or load them at runtime. - -## Entrypoint Options - -Most entrypoints allow customizing their options in the file you define them in. This differs from regular web extension development, where all options are placed in the `manifest.json`. - -WXT looks for custom options in the entrypoint, and adds them to the manifest when generated. - -In HTML files, options are listed as `meta` tags: - -```html - - - - - - -``` - -In TS files, options are apart of the file's default export: - -```ts -export default defineContentScript({ - matches: ['*://*.google.com/*'], - runAt: 'document_start', - main() { - // ... - }, -}); -``` - -:::info -All options for each entrypoint type is listed in the [entrypoints directory docs](/guide/directory-structure/entrypoints/background). -::: diff --git a/docs/get-started/installation.md b/docs/get-started/installation.md deleted file mode 100644 index 7bf4765c..00000000 --- a/docs/get-started/installation.md +++ /dev/null @@ -1,120 +0,0 @@ -# Installation - -Bootstrap a new project, start from scratch, or [migrate an existing project](/get-started/migrate-to-wxt). - -## Bootstrap Project - -:::code-group - -```sh [pnpm] -pnpm dlx wxt@latest init -``` - -```sh [npm] -npx wxt@latest init -``` - -```sh [bun] -# 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 - -npx wxt@latest init -``` - -### Demo - -![wxt init demo](/assets/init-demo.gif) - -::: - -There are several starting templates available. - -| TypeScript | -| ------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [`vanilla`](https://github.com/wxt-dev/wxt/tree/main/templates/vanilla) | -| [`vue`](https://github.com/wxt-dev/wxt/tree/main/templates/vue) | -| [`react`](https://github.com/wxt-dev/wxt/tree/main/templates/react) | -| [`svelte`](https://github.com/wxt-dev/wxt/tree/main/templates/svelte) | -| [`solid`](https://github.com/wxt-dev/wxt/tree/main/templates/solid) | - -:::info -All templates default to TypeScript. Rename the file extensions to `.js` to use JavaScript instead. -::: - -## From Scratch - -Initialize a project and install `wxt`: - -:::code-group - -```sh [pnpm] -pnpm init -pnpm add -D wxt -``` - -```sh [npm] -npm init -npm i --save-dev wxt -``` - -```sh [yarn] -yarn init -yarn add --dev wxt -``` - -```sh [bun] -bun init -bun add --dev wxt -``` - -::: - -Add your first entrypoint: - -```ts -// entrypoints/background.ts -export default defineBackground(() => { - console.log(`Hello from ${browser.runtime.id}!`); -}); -``` - -And add scripts to your `package.json`: - -```json -{ - "scripts": { - "dev": "wxt", // [!code ++] - "dev:firefox": "wxt --browser firefox", // [!code ++] - "build": "wxt build", // [!code ++] - "build:firefox": "wxt build --browser firefox", // [!code ++] - "zip": "wxt zip", // [!code ++] - "zip:firefox": "wxt zip --browser firefox", // [!code ++] - "postinstall": "wxt prepare" // [!code ++] - } -} -``` - -## Development - -Once the project is setup, you can start the development server using the `dev` script. - -```sh -pnpm dev -``` - -:::tip 🎉 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. -::: - -## Next Steps - -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 [Guide](/guide/key-concepts/manifest) to learn in-depth about each feature WXT supports -- [Configure WXT](./configuration) by creating a `wxt.config.ts` file -- Checkout [example projects](https://github.com/wxt-dev/examples) to see how to perform common tasks with WXT diff --git a/docs/get-started/introduction.md b/docs/get-started/introduction.md deleted file mode 100644 index 1a66b8c6..00000000 --- a/docs/get-started/introduction.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -head: - - - link - - rel: canonical - href: https://wxt.dev ---- - -# Introduction - -## Overview - -WXT is a free and open source framework for building web extensions in a conventional, intuitive, and safe way **_for all browsers_**. - -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) - -## Conventions - -WXT is an opinionated framework. This helps keep projects consistent and easy to pick up. - -- **Generated manifest**: Based on your project's file structure -- **Entrypoint configuration**: Configure entrypoints from the same file they're declare in -- **Type-safety is a priority**: Out-of-the-box TypeScript support with improved browser API typing -- **Simple output file structure**: Output file paths minimize the path at runtime - -## Development - -WXT's dev server supports modern features like HMR to provide a lighting fast dev mode. - -When changes can't be hot-reloaded, like content scripts or background scripts, they're reloaded individually to prevent reloading the entire extension and slowing down your development cycle. - -## Production-ready - -Production builds are optimized for store review, changing as few files as possible between builds. - -In addition, WXT fully supports Firefox's source code requirements when using a bundler. It will automatically create and upload a ZIP file of your source code. - -:::info -See [Publishing](./publishing) for more info around production builds. -::: - -## New to Extension Development? - -Most of these docs assume you have a basic understanding of how to write a chrome or web extension. - -If you've never written a web extension before or need a refresher, follow Google's ["Hello, World!" tutorial](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world) to understand the basics. diff --git a/docs/guide/directory-structure/app-config.md b/docs/guide/directory-structure/app-config.md deleted file mode 100644 index e5c2582c..00000000 --- a/docs/guide/directory-structure/app-config.md +++ /dev/null @@ -1,61 +0,0 @@ -# `/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 -// /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 -// /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. diff --git a/docs/guide/directory-structure/assets.md b/docs/guide/directory-structure/assets.md deleted file mode 100644 index f28bac1a..00000000 --- a/docs/guide/directory-structure/assets.md +++ /dev/null @@ -1,42 +0,0 @@ -# `/assets` - -Files in the assets directory will be processed by Vite. They are imported in your source code, and will be transformed or renamed in the output directory. - -``` - -└─ assets/ - ├─ style.css - └─ illustration.svg -``` - -### Example - -:::code-group - -```html [popup.html] - - - - - - - - - - -``` - -```ts [content.ts] -import '~/assets/style.css'; -import illustration from '~/assets/style.svg'; - -defineContentScript({ - main() { - const image = document.createElement('img'); - image.src = illustration; - document.body.append(image); - }, -}); -``` - -::: diff --git a/docs/guide/directory-structure/components.md b/docs/guide/directory-structure/components.md deleted file mode 100644 index 0bb2f0b2..00000000 --- a/docs/guide/directory-structure/components.md +++ /dev/null @@ -1,5 +0,0 @@ -# `/components` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/directory-structure/composables.md b/docs/guide/directory-structure/composables.md deleted file mode 100644 index c1ada3ec..00000000 --- a/docs/guide/directory-structure/composables.md +++ /dev/null @@ -1,5 +0,0 @@ -# `/composables` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/directory-structure/entrypoints/background.md b/docs/guide/directory-structure/entrypoints/background.md deleted file mode 100644 index b5df3dd9..00000000 --- a/docs/guide/directory-structure/entrypoints/background.md +++ /dev/null @@ -1,47 +0,0 @@ -# Background - -[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/manifest/background/) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/background) - -For MV2, the background is added as a script to the background page. For MV3, the background becomes a service worker. - -## Filenames - - - -## Definition - -:::warning -The main function of the background **_CANNOT BE ASYNC_**. Event listeners must be added synchronously on background startup. If your main function returns a promise, WXT will log an error. -::: - -```ts -export default defineBackground(() => { - // Executed when background is loaded -}); -``` - -or - -```ts -export default defineBackground({ - // Set manifest options - persistent: undefined | true | false, - type: undefined | 'module', - - // Set include/exclude if the background should be removed from some builds - include: undefined | string[], - exclude: undefined | string[], - - // Executed when background is loaded - main() { - // ... - }, -}); -``` - -> All manifest options default to `undefined`. diff --git a/docs/guide/directory-structure/entrypoints/bookmarks.md b/docs/guide/directory-structure/entrypoints/bookmarks.md deleted file mode 100644 index 10434f3c..00000000 --- a/docs/guide/directory-structure/entrypoints/bookmarks.md +++ /dev/null @@ -1,31 +0,0 @@ -# Bookmarks - -[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/override/) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/chrome_url_overrides) - -## Filenames - - - -## Definition - -```html - - - - - - Title - - - - - - - - -``` diff --git a/docs/guide/directory-structure/entrypoints/content-scripts.md b/docs/guide/directory-structure/entrypoints/content-scripts.md deleted file mode 100644 index 5ad58331..00000000 --- a/docs/guide/directory-structure/entrypoints/content-scripts.md +++ /dev/null @@ -1,107 +0,0 @@ -# Content Scripts - -[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/content_scripts/) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts) - -When creating content script entrypoints, they are automatically included in the `manifest.json` along with any CSS files they import. - -## Filenames - - - -## Definition - -```ts -export default defineContentScript({ - // Set manifest options - matches: string[], - excludeMatches: undefined | [], - includeGlobs: undefined | [], - excludeGlobs: undefined | [], - allFrames: undefined | true | false, - runAt: undefined | 'document_start' | 'document_end' | 'document_idle', - matchAboutBlank: undefined | true | false, - matchOriginAsFallback: undefined | true | false, - world: undefined | 'ISOLATED' | 'MAIN', - - // Set include/exclude if the background should be removed from some builds - include: undefined | string[], - exclude: undefined | string[], - - // Configure how CSS is injected onto the page - cssInjectionMode: undefined | "manifest" | "manual" | "ui", - - // Configure how/when content script will be registered - registration: undefined | "manifest" | "runtime", - - main(ctx: ContentScriptContext) { - // Executed when content script is loaded - }, -}); -``` - -> All manifest options default to `undefined`. - -When defining multiple content scripts, content script entrypoints that have the same set of options will be merged into a single `content_script` item in the manifest. - -## CSS - -To include CSS with your content script, import the CSS file at the top of your entrypoint. - -``` - -/ -└─ entrypoints/ - └─ overlay.content/ - ├─ index.ts - └─ style.css -``` - -```ts -// entrypoints/overlay.content/index.ts -import './style.css'; - -export default defineContentScript({ - matches: ['*://google.com/*', '*://duckduckgo.com/*'], - - main(ctx) { - // ... - }, -}); -``` - -Any styles imported in your content script will be added to that content script's `css` array in your `manifest.json`: - -```json -// .output/chrome-mv3/manifest.json -{ - "content_scripts": [ - { - "matches": ["*://google.com/*", "*://duckduckgo.com/*"], - "js": ["content-scripts/overlay.js"], - "css": ["content-scripts/overlay.css"] - } - ] -} -``` - -To disable this behavior, set `cssInjectionMode` to `"manual"` or `"ui"`. - -```ts -export default defineContentScript({ - matches: ['*://google.com/*', '*://duckduckgo.com/*'], - cssInjectionMode: 'manual', - - main(ctx) { - // ... - }, -}); -``` - -See [Content Script UI](/guide/key-concepts/content-script-ui) for more info on creating UIs and including CSS in content scripts. diff --git a/docs/guide/directory-structure/entrypoints/css.md b/docs/guide/directory-structure/entrypoints/css.md deleted file mode 100644 index 0e38c46c..00000000 --- a/docs/guide/directory-structure/entrypoints/css.md +++ /dev/null @@ -1,44 +0,0 @@ -# CSS - -WXT can build CSS entrypoints individually. CSS entrypoints are always unlisted. - -See [Content Script CSS](/guide/directory-structure/entrypoints/content-scripts#css) documentation for the recommended approach to include CSS with a content script. - -:::info -If the recommended approach doesn't work for your use case, you can use any of the filename patterns below to build the styles separate from the JS and use the [`transformManifest` hook](/api/reference/wxt/interfaces/InlineConfig#transformmanifest) to manually add your CSS file to the manifest. -::: - -## Filenames - - - -## Definition - -```css -body { - /* Plain CSS file */ -} -``` - -Follow Vite's guide to setup a preprocessor: https://vitejs.dev/guide/features.html#css-pre-processors - -```sh -pnpm i sass -``` - -```scss -body { - h1 { - /* ...*/ - } -} -``` diff --git a/docs/guide/directory-structure/entrypoints/devtools.md b/docs/guide/directory-structure/entrypoints/devtools.md deleted file mode 100644 index da3cda04..00000000 --- a/docs/guide/directory-structure/entrypoints/devtools.md +++ /dev/null @@ -1,40 +0,0 @@ -# Devtools - -[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/devtools/) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/devtools_page) - -## Filenames - - - -## Definition - -```html - - - - - - - - - - - - - -``` - -## Adding UI Elements - -Chrome extensions allow you to add panels and side panes to the devtools window. - -![DevTools window showing Elements panel and Styles sidebar pane.](https://developer.chrome.com/static/docs/extensions/how-to/devtools/extend-devtools/image/devtools-window-showing-e-9051f7f0347cd_1920.png) - -See the WXT's examples for a full walkthrough of extending the devtools window: - -- [Devtools Setup](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vanilla-devtools#readme) diff --git a/docs/guide/directory-structure/entrypoints/history.md b/docs/guide/directory-structure/entrypoints/history.md deleted file mode 100644 index 9fc11a1b..00000000 --- a/docs/guide/directory-structure/entrypoints/history.md +++ /dev/null @@ -1,31 +0,0 @@ -# History - -[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/override/) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/chrome_url_overrides) - -## Filenames - - - -## Definition - -```html - - - - - - Title - - - - - - - - -``` diff --git a/docs/guide/directory-structure/entrypoints/newtab.md b/docs/guide/directory-structure/entrypoints/newtab.md deleted file mode 100644 index e15dcb2b..00000000 --- a/docs/guide/directory-structure/entrypoints/newtab.md +++ /dev/null @@ -1,31 +0,0 @@ -# Newtab - -[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/override/) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/chrome_url_overrides) - -## Filenames - - - -## Definition - -```html - - - - - - Title - - - - - - - - -``` diff --git a/docs/guide/directory-structure/entrypoints/options.md b/docs/guide/directory-structure/entrypoints/options.md deleted file mode 100644 index f4af0271..00000000 --- a/docs/guide/directory-structure/entrypoints/options.md +++ /dev/null @@ -1,36 +0,0 @@ -# Options - -[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/options/) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/options_ui) - -## Filenames - - - -## Definition - -```html - - - - - - Options Title - - - - - - - - - - - -``` - -> All manifest options default to `undefined` when the `meta` tag is not present. diff --git a/docs/guide/directory-structure/entrypoints/popup.md b/docs/guide/directory-structure/entrypoints/popup.md deleted file mode 100644 index 536742e4..00000000 --- a/docs/guide/directory-structure/entrypoints/popup.md +++ /dev/null @@ -1,43 +0,0 @@ -# Popup - -[Chrome Docs](https://developer.chrome.com/docs/extensions/reference/action/) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/action) - -## Filenames - - - -## Definition - -```html - - - - - - Default Popup Title - - - - - - - - - - - -``` - -> All manifest options default to `undefined` when the `meta` tag is not present. diff --git a/docs/guide/directory-structure/entrypoints/sandbox.md b/docs/guide/directory-structure/entrypoints/sandbox.md deleted file mode 100644 index 886c64dc..00000000 --- a/docs/guide/directory-structure/entrypoints/sandbox.md +++ /dev/null @@ -1,37 +0,0 @@ -# Sandbox - -[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/manifest/sandbox/) - -:::tip Chromium Only -Firefox does not support sandboxed pages. -::: - -## Filenames - - - -## Definition - -```html - - - - - - Title - - - - - - - - -``` diff --git a/docs/guide/directory-structure/entrypoints/sidepanel.md b/docs/guide/directory-structure/entrypoints/sidepanel.md deleted file mode 100644 index 8e61a07c..00000000 --- a/docs/guide/directory-structure/entrypoints/sidepanel.md +++ /dev/null @@ -1,49 +0,0 @@ -# Side Panel - -[Chrome Docs](https://developer.chrome.com/docs/extensions/reference/sidePanel/) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Sidebars) - -In Chrome, side panels use the "side_panel" API, while Firefox uses the "sidebar_action" API. - -:::warning -Chrome added support for sidepanels in Manifest V3, they are not available in Manifest V2. -::: - -## Filenames - - - -## Definition - -```html - - - - - - Default Side Panel Title - - - - - - - - - - - -``` diff --git a/docs/guide/directory-structure/entrypoints/unlisted-pages.md b/docs/guide/directory-structure/entrypoints/unlisted-pages.md deleted file mode 100644 index c9812e99..00000000 --- a/docs/guide/directory-structure/entrypoints/unlisted-pages.md +++ /dev/null @@ -1,49 +0,0 @@ -# Unlisted Pages - -HTML pages that are bundled and shipped with the extension, but are not included in the manifest. - -If you plan on using the page in an iframe, don't forget to add the page to [`web_accessible_resources`](https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources). - -### Examples - -- Onboarding -- Dashboard -- FAQ -- Help -- Changelog - -## Filenames - - - -Pages are accessible at `'/.html'`: - -```ts -const url = browser.runtime.getURL('/.html', ''); - -console.log(url); // "chrome-extension:///.html" -``` - -## Definition - -```html - - - - - - Title - - - - - - - - -``` diff --git a/docs/guide/directory-structure/entrypoints/unlisted-scripts.md b/docs/guide/directory-structure/entrypoints/unlisted-scripts.md deleted file mode 100644 index 89a2da53..00000000 --- a/docs/guide/directory-structure/entrypoints/unlisted-scripts.md +++ /dev/null @@ -1,37 +0,0 @@ -# Unlisted Scripts - -TypeScript files that are bundled and shipped with the extension, but are not included in the manifest. - -You are responsible for loading/running these scripts where needed. If necessary, don't forget to add the script and/or any related stylesheets to [`web_accessible_resources`](https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources). - -## Filenames - - - -## Definition - -```ts -export default defineUnlistedScript(() => { - // Executed when script is loaded -}); -``` - -or - -```ts -export default defineUnlistedScript({ - // Set include/exclude if the script should be removed from some builds - include: undefined | string[], - exclude: undefined | string[], - - // Executed when script is loaded - main() { - // ... - }, -}); -``` diff --git a/docs/guide/directory-structure/env.md b/docs/guide/directory-structure/env.md deleted file mode 100644 index 6a17fbce..00000000 --- a/docs/guide/directory-structure/env.md +++ /dev/null @@ -1,5 +0,0 @@ -# `/.env` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/directory-structure/hooks.md b/docs/guide/directory-structure/hooks.md deleted file mode 100644 index e6e19836..00000000 --- a/docs/guide/directory-structure/hooks.md +++ /dev/null @@ -1,5 +0,0 @@ -# `/hooks` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/directory-structure/output.md b/docs/guide/directory-structure/output.md deleted file mode 100644 index bb5ef417..00000000 --- a/docs/guide/directory-structure/output.md +++ /dev/null @@ -1,5 +0,0 @@ -# `/.output` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/directory-structure/package.md b/docs/guide/directory-structure/package.md deleted file mode 100644 index 79f23b57..00000000 --- a/docs/guide/directory-structure/package.md +++ /dev/null @@ -1,5 +0,0 @@ -# `/package.json` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/directory-structure/public/index.md b/docs/guide/directory-structure/public/index.md deleted file mode 100644 index 765e1a44..00000000 --- a/docs/guide/directory-structure/public/index.md +++ /dev/null @@ -1,35 +0,0 @@ -# `public/` - -Place static files like the extension icon or `_locales/` directory here. These files will be copied over to the output directory without being transformed by Vite. - -``` - -└─ public/ - ├─ icon-16.png - ├─ icon-32.png - ├─ icon-48.png - ├─ icon-96.png - └─ icon-128.png -``` - -### Example - -You can reference these files by using absolute paths in HTML files or `browser.runtime.getURL` in content scripts. - -:::code-group - -```html [popup.html] - -``` - -```ts [content.ts] -defineContentScript({ - main() { - const image = document.createElement('img'); - image.src = browser.runtime.getURL('/icon-128.png'); - document.body.append(image); - }, -}); -``` - -::: diff --git a/docs/guide/directory-structure/public/locales.md b/docs/guide/directory-structure/public/locales.md deleted file mode 100644 index 36a57303..00000000 --- a/docs/guide/directory-structure/public/locales.md +++ /dev/null @@ -1,5 +0,0 @@ -# `public/_locales/` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/directory-structure/tsconfig.md b/docs/guide/directory-structure/tsconfig.md deleted file mode 100644 index 81220e42..00000000 --- a/docs/guide/directory-structure/tsconfig.md +++ /dev/null @@ -1,5 +0,0 @@ -# `/tsconfig.json` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/directory-structure/utils.md b/docs/guide/directory-structure/utils.md deleted file mode 100644 index 54cd86e5..00000000 --- a/docs/guide/directory-structure/utils.md +++ /dev/null @@ -1,5 +0,0 @@ -# `/utils` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/directory-structure/web-ext-config.md b/docs/guide/directory-structure/web-ext-config.md deleted file mode 100644 index 88b33744..00000000 --- a/docs/guide/directory-structure/web-ext-config.md +++ /dev/null @@ -1,65 +0,0 @@ -# `web-ext.config.ts` - -This file lets you configure the browser startup when running `wxt dev`. - -```ts -import { defineRunnerConfig } from 'wxt'; - -export default defineRunnerConfig({ - startUrls: ['https://google.com', 'https://youtube.com'], -}); -``` - -There are three places you can customize the runner: - -- `/wxt.config.ts` - Use the `runner` option. Changes here will be committed and shared with everyone developing the project. -- `/web-ext.config.ts` - A gitignored file for you to customize the startup behavior to your liking without effecting others -- `$HOME/web-ext.config.ts` - Stores system-wide config effecting all projects running on your machine. - -See below examples on how to accomplish common configuration: - -[[toc]] - -## Configuring Binaries - -`web-ext`'s browser discovery is very limited. By default, it only guesses at where Chrome and Firefox are installed. If you've customized your install locations, you may need to tell `web-ext` where the binaries/executables are located using the [`binaries` option](/api/reference/wxt/interfaces/ExtensionRunnerConfig#binaries). For other Chromium based browsers, like Edge or Opera, you'll need to explicitly list them in the `binaries` option as well, otherwise they will open in Chrome by default. - -```ts -import { defineRunnerConfig } from 'wxt'; - -export default defineRunnerConfig({ - binaries: { - chrome: '/path/to/chrome-beta', // Use Chrome Beta instead of regular Chrome - firefox: 'firefoxdeveloperedition', // Use Firefox Developer Edition instead of regular Firefox - edge: '/path/to/edge', // Open MS Edge when running "wxt -b edge" - }, -}); -``` - -## Disable Opening Browser - -Disabling the browser can be useful if it's difficult to develop your extension with fresh profiles. Maybe you need to sign into a website to see a content script run, and a fresh profile isn't helpful because it doesn't save your login info. - -To disable opening the extension automatically in a new window, just disable the runner: - -```ts -export default defineRunnerConfig({ - disabled: true, -}); -``` - -## Profile Customization - -Another option, instead of disabling the runner, to stay logged into websites is to use a custom profile. - -`web-ext` comes with some built-in ways of using an existing profile, but it's not really using the same profile. It copies the profile to a temp directory, and uses that. - -Instead, I've found it's better to pass Chrome's `--user-data-dir` argument. This let's you use a fresh profile initially, and customize it to your liking. You can install devtool extensions, set custom flags, and log into websites. Next time you run the extension in dev mode, all that will be remembered! - -```ts -export default defineRunnerConfig({ - chromiumArgs: ['--user-data-dir=./chrome-data'], -}); -``` - -> This only works for Chrome. You'll have to use `firefoxProfile` option instead, which has the same limitations mentioned above, where you won't be signed into websites automatically. diff --git a/docs/guide/directory-structure/wxt-config.md b/docs/guide/directory-structure/wxt-config.md deleted file mode 100644 index 30c0e831..00000000 --- a/docs/guide/directory-structure/wxt-config.md +++ /dev/null @@ -1,5 +0,0 @@ -# `/wxt.config.ts` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/directory-structure/wxt.md b/docs/guide/directory-structure/wxt.md deleted file mode 100644 index 557ce148..00000000 --- a/docs/guide/directory-structure/wxt.md +++ /dev/null @@ -1,5 +0,0 @@ -# `.wxt/` - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/essentials/assets.md b/docs/guide/essentials/assets.md new file mode 100644 index 00000000..29638fd1 --- /dev/null +++ b/docs/guide/essentials/assets.md @@ -0,0 +1,82 @@ +# Assets + +## `/assets` Directory + +Any assets imported or referenced inside the `/assets/` directory will be processed by WXT's bundler. + +Here's how you access them: + +:::code-group + +```ts [JS] +import imageUrl from '~/assets/image.png'; + +const img = document.createElement('img'); +img.src = imageUrl; +``` + +```html [HTML] + +``` + +```css [CSS] +.bg-image { + background-image: url(~/assets/image.png); +} +``` + +::: + +## `/public` Directory + +Files inside `/public/` are copied into the output folder as-is, without being processed by WXT's bundler. + +Here's how you access them: + +:::code-group + +```ts [JS] +import imageUrl from '/image.png'; + +const img = document.createElement('img'); +img.src = imageUrl; +``` + +```html [HTML] + +``` + +```css [CSS] +.bg-image { + background-image: url(/image.png); +} +``` + +::: + +## Inside Content Scripts + +Assets inside content scripts are a little different. By default, when you import an asset, it returns just the path to the asset. This is because Vite assumes you're loading assets from the same hostname. + +But, inside content scripts, the hostname is whatever the tab is set to. So if you try to fetch the asset, manually or as an ``'s `src`, it will be loaded from the tab's website, not your extension. + +To fix this, you need to convert the image to a full URL using `browser.runtime.getURL`: + +```ts +// entrypoints/content.ts +import iconUrl from '/icon/128.png'; + +export default defineContentScript({ + matches: ['*://*.google.com/*'], + main() { + console.log(iconUrl); // "/icon/128.png" + console.log(browser.runtime.getURL(iconUrl)); // "chrome-extension:///icon/128.png" + }, +}); +``` + +## WASM + +:::warning 🚧 Under construction +These docs will be coming soon! +::: diff --git a/docs/guide/essentials/config/auto-imports.md b/docs/guide/essentials/config/auto-imports.md new file mode 100644 index 00000000..92aca6aa --- /dev/null +++ b/docs/guide/essentials/config/auto-imports.md @@ -0,0 +1,112 @@ +# Auto-imports + +WXT uses [`unimport`](https://www.npmjs.com/package/unimport), the same tool as Nuxt, to setup auto-imports. + +```ts +export default defineConfig({ + // See https://www.npmjs.com/package/unimport#configurations + imports: { + // ... + }, +}); +``` + +By default, WXT automatically setups up auto-imports for all of it's own APIs: + +- [`browser`](/api/reference/wxt/browser/variables/browser) from `wxt/browser` +- [`defineContentScript`](/api/reference/wxt/sandbox/functions/defineContentScript) from `wxt/sandbox` +- [`defineBackground`](/api/reference/wxt/sandbox/functions/defineBackground) from `wxt/sandbox` +- [`defineUnlistedScript`](/api/reference/wxt/sandbox/functions/defineUnlistedScript) from `wxt/sandbox` +- [`createIntegratedUi`](/api/reference/wxt/client/functions/createIntegratedUi) from `wxt/client` +- [`createShadowRootUi`](/api/reference/wxt/client/functions/createShadowRootUi) from `wxt/client` +- [`createIframeUi`](/api/reference/wxt/client/functions/createIframeUi) from `wxt/client` +- [`fakeBrowser`](/api/reference/wxt/testing/variables/fakeBrowser) from `wxt/testing` +- And more! + +WXT also adds some project directories as auto-import sources automatically: + +- `/components/*` +- `/composables/*` +- `/hooks/*` +- `/utils/*` + +All named and default exports from files in these directories are available everywhere else in your project without having to import them. + +## TypeScript + +For TypeScript and your editor to recognize auto-imported variables, you need to run the [`wxt prepare` command](/api/cli/wxt-prepare). + +Add this command to your `postinstall` script so your editor has everything it needs to report type errors after installing dependencies: + +```jsonc +// package.json +{ + "scripts": { + "postinstall": "wxt prepare", // [!code ++] + }, +} +``` + +## ESLint + +ESLint doesn't know about the auto-imported variables unless they are explicitly defined in the ESLint's `globals`. 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. + +:::code-group + +```ts [ESLint 9] +export default defineConfig({ + imports: { + eslintrc: { + enabled: 9, + }, + }, +}); +``` + +```ts [ESLint 8] +export default defineConfig({ + imports: { + eslintrc: { + enabled: 8, + }, + }, +}); +``` + +::: + +Then in your ESLint config, import and use the generated file: + +:::code-group + +```js [ESLint 9] +// eslint.config.mjs +import autoImports from './.wxt/eslint-auto-imports.mjs'; + +export default [ + autoImports, + { + // The rest of your config... + }, +]; +``` + +```js [ESLint 8] +// .eslintrc.mjs +export default { + extends: ['./.wxt/eslintrc-auto-import.json'], + // The rest of your config... +}; +``` + +::: + +## Disabling Auto-imports + +Not all developers like auto-imports. To disable them, set `imports` to `false`. + +```ts +export default defineConfig({ + imports: false, // [!code ++] +}); +``` diff --git a/docs/guide/essentials/config/browser-startup.md b/docs/guide/essentials/config/browser-startup.md new file mode 100644 index 00000000..676d5e22 --- /dev/null +++ b/docs/guide/essentials/config/browser-startup.md @@ -0,0 +1,85 @@ +--- +outline: deep +--- + +# Browser Startup + +> See the [API Reference](/api/reference/wxt/interfaces/ExtensionRunnerConfig) for a full list of config. + +During development WXT uses [`web-ext` by Mozilla](https://www.npmjs.com/package/web-ext) to automatically open a browser window with your extension installed. + +## Config Files + +You can configure browser startup in 3 places: + +1. `/web-ext.config.ts`: Ignored from version control, this file lets you configure your own options for a specific project without affecting other developers + + ```ts + import { defineRunnerConfig } from 'wxt'; + + export default defineRunnerConfig({ + // ... + }); + ``` + +2. `/wxt.config.ts`: Via the [`runner` config](/api/reference/wxt/interfaces/InlineConfig#runner), included in version control +3. `$HOME/web-ext.config.ts`: Provide default values for all WXT projects on your computer + +## Recipes + +### Set Browser Binaries + +To set or customize the browser opened during development: + +```ts +export default defineRunnerConfig({ + binaries: { + chrome: '/path/to/chrome-beta', // Use Chrome Beta instead of regular Chrome + firefox: 'firefoxdeveloperedition', // Use Firefox Developer Edition instead of regular Firefox + edge: '/path/to/edge', // Open MS Edge when running "wxt -b edge" + }, +}); +``` + +### Persist Data + +By default, to keep from modifying your browser's existing profiles, `web-ext` creates a brand new profile every time you run the `dev` script. + +Right now, Chromium based browsers are the only browsers that support overriding this behavior and persisting data when running the `dev` script multiple times. + +To persist data, set the `--user-data-dir` flag: + +:::code-group + +```ts [Mac/Linux] +export default defineRunnerConfig({ + chromiumArgs: ['--user-data-dir=./.wxt/chrome-data'], +}); +``` + +```ts [Windows] +import { resolve } from 'node:path'; + +export default defineRunnerConfig({ + // On Windows, the path must be absolute + chromiumArgs: [`--user-data-dir="${resolve(".wxt/chrome-data")}"` +}); +``` + +::: + +Now, next time you run the `dev` script, a persistent profile will be created in `.wxt/chrome-data/{profile-name}`. With a persistent profile, you can install devtools extensions to help with development, allow the browser to remember logins, etc, without worrying about the profile being reset the next time you run the `dev` script. + +:::tip +You can use any directory you'd like for `--user-data-dir`, the examples above create a persistent profile for each WXT project. To create a profile for all WXT projects, you can put the `chrome-data` directory inside you're user's home directory. +::: + +### Disable Opening Browser + +If you prefer to load the extension into your browser manually, you can disable the auto-open behavior: + +```ts +export default defineRunnerConfig({ + disabled: true, +}); +``` diff --git a/docs/guide/essentials/config/build-mode.md b/docs/guide/essentials/config/build-mode.md new file mode 100644 index 00000000..850f499f --- /dev/null +++ b/docs/guide/essentials/config/build-mode.md @@ -0,0 +1,29 @@ +# Build Modes + +Because WXT is powered by Vite, it supports [modes](https://vite.dev/guide/env-and-mode.html#modes) in the same way. + +When running any dev or build commands, pass the `--mode` flag: + +```sh +wxt --mode production +wxt build --mode development +wxt zip --mode testing +``` + +By default, `--mode` is `development` for the dev command and `production` for all other commands (build, zip, etc). + +## Get Mode at Runtime + +You can access the current mode in your extension using `import.meta.env.MODE`: + +```ts +switch (import.meta.env.MODE) { + case 'development': // ... + case 'production': // ... + + // Custom modes specified with --mode + case 'testing': // ... + case 'staging': // ... + // ... +} +``` diff --git a/docs/guide/essentials/config/entrypoint-loaders.md b/docs/guide/essentials/config/entrypoint-loaders.md new file mode 100644 index 00000000..a61708b4 --- /dev/null +++ b/docs/guide/essentials/config/entrypoint-loaders.md @@ -0,0 +1,79 @@ +# Entrypoint Loaders + +To generate the manifest and other files at build-time, WXT must import each entrypoint to get their options, like content script `matches`. For HTML files, this is easy. For JS/TS entrypoints, the process is more complicated. + +When loading your JS/TS entrypoints, they are imported into a NodeJS environment, not the `browser` environment that they normally run in. This can lead to issues commonly seen when running browser-only code in a NodeJS environment, like missing global variables. + +WXT does several pre-processing steps to try and prevent errors during this process: + +1. Use `linkedom` to make a small set of browser globals (`window`, `document`, etc) available. +2. Use `@webext-core/fake-browser` to create a fake version of the `chrome` and `browser` globals expected by extensions. +3. Pre-process the JS/TS code, stripping out the `main` function then tree-shaking unused code from the file + +However, this process is not perfect. It doesn't setup all the globals found in the browser and the APIs may behave differently. As such, **_you should avoid using browser or extension APIs outside the `main` function of your entrypoints!_** + +:::tip +If you're running into errors while importing entrypoints, run `wxt prepare --debug` to see more details about this process. When debugging, WXT will print out the pre-processed code to help you identify issues. +::: + +Once the environment has been polyfilled and your code pre-processed, it's up the entrypoint loader to import your code, extracting the options from the default export. + +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. It re-uses the same vite config used when building your extension, making it the most stable entrypoint loader. + +## jiti + +To enable `jiti`: + +```ts +export default defineConfig({ + entrypointLoader: 'jiti', +}); +``` + +This is the original method WXT used to import TS files. However, because it doesn't support vite plugins like `vite-node`, it does one additional pre-processing step: It removes **_ALL_** imports from your code. + +That means you cannot use imported variables outside the `main` function in JS entrypoints, like for content script `matches` or other options: + +```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. +``` + +Usually, this error occurs when you try to extract options into a shared file or when running 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() { + // ... + }, +}); +``` diff --git a/docs/guide/essentials/config/environment-variables.md b/docs/guide/essentials/config/environment-variables.md new file mode 100644 index 00000000..be97952f --- /dev/null +++ b/docs/guide/essentials/config/environment-variables.md @@ -0,0 +1,54 @@ +# Environment Variables + +## Dotenv Files + +WXT supports [dotenv files the same way as Vite](https://vite.dev/guide/env-and-mode.html#env-files). Create any of the following files: + +``` +.env +.env.local +.env.[mode] +.env.[mode].local +``` + +And any environment variables listed inside them will be available at runtime: + +```sh +# .env +VITE_API_KEY=... +``` + +```ts +await fetch(`/some-api?apiKey=${import.meta.env.VITE_API_KEY}`); +``` + +Remember to prefix any environment variables with `VITE_`, otherwise they won't be available at runtime, as per [Vite's convention](https://vite.dev/guide/env-and-mode.html#env-files). + +## Built-in Environment Variables + +WXT provides some custom environment variables based on the current command: + +| Usage | Type | Description | +| ---------------------------------- | --------- | ----------------------------------------------------- | +| `import.meta.env.MANIFEST_VERSION` | `2 │ 3` | The target manifest version | +| `import.meta.env.BROWSER` | `string` | The target browser | +| `import.meta.env.CHROME` | `boolean` | Equivalent to `import.meta.env.BROWSER === "chrome"` | +| `import.meta.env.FIREFOX` | `boolean` | Equivalent to `import.meta.env.BROWSER === "firefox"` | +| `import.meta.env.SAFARI` | `boolean` | Equivalent to `import.meta.env.BROWSER === "safari"` | +| `import.meta.env.EDGE` | `boolean` | Equivalent to `import.meta.env.BROWSER === "edge"` | +| `import.meta.env.OPERA` | `boolean` | Equivalent to `import.meta.env.BROWSER === "opera"` | + +You can also access all of [Vite's environment variables](https://vite.dev/guide/env-and-mode.html#env-variables): + +| Usage | Type | Description | +| ---------------------- | --------- | --------------------------------------------------------------------------- | +| `import.meta.env.MODE` | `string` | The [mode](/guide/essentials/config/build-mode) the extension is running in | +| `import.meta.env.PROD` | `boolean` | When `NODE_ENV='production'` | +| `import.meta.env.DEV` | `boolean` | Opposite of `import.meta.env.PROD` | + +:::details Other Vite Environment Variables +Vite provides two other environment variables, but they aren't useful in WXT projects: + +- `import.meta.env.BASE_URL`: Use `browser.runtime.getURL` instead. +- `import.meta.env.SSR`: Always `false`. + ::: diff --git a/docs/guide/essentials/config/hooks.md b/docs/guide/essentials/config/hooks.md new file mode 100644 index 00000000..930b8bdf --- /dev/null +++ b/docs/guide/essentials/config/hooks.md @@ -0,0 +1,22 @@ +# Hooks + +WXT includes a system that lets you hook into the build process and make changes. + +Here's an example hook that modifies the `manifest.json` file before it is written to the output directory: + +```ts +// wxt.config.ts +export default defineConfig({ + hooks: { + 'build:manifestGenerated': (wxt, manifest) => { + if (wxt.config.mode === 'development') { + manifest.title += ' (DEV)'; + } + }, + }, +}); +``` + +> Most hooks provide the `wxt` object as the first argument. It contains the resolved config and other info about the current build. + +Putting one-off hooks like this in your config file is simple, but if you find yourself writing lots of hooks, you should extract them into [WXT Modules](/guide/essentials/wxt-modules) instead. diff --git a/docs/guide/essentials/config/manifest.md b/docs/guide/essentials/config/manifest.md new file mode 100644 index 00000000..6aeab49d --- /dev/null +++ b/docs/guide/essentials/config/manifest.md @@ -0,0 +1,258 @@ +# Manifest + +In WXT, there is no `manifest.json` file in your source code. Instead, WXT generates it during the build process based off files in your project. + +## Manifest Config + +To manually add a property to the `manifest.json` output during builds, use the `manifest` config inside `wxt.config.ts`: + +```ts +export default defineConfig({ + manifest: { + // Put manual changes here + }, +}); +``` + +You can also define the manifest as a function, and use JS to generate it based on the target browser, mode, and more. + +```ts +export default defineConfig({ + manifest: ({ browser, manifestVersion, mode, command }) => { + return { + // ... + }; + }, +}); +``` + +### MV2 and MV3 Compatibility + +When adding properties to the manifest, always define the property in it's MV3 format when possible. When targeting MV2, WXT will automatically convert these properties to their MV2 format. + +For example, for this config: + +```ts +export default defineConfig({ + manifest: { + action: { + default_title: 'Some Title', + }, + web_accessible_resources: [ + { + matches: ['*://*.google.com/*'], + resources: ['icon/*.png'], + }, + ], + }, +}); +``` + +WXT will generate the following manifests: + +:::code-group + +```json [MV2] +{ + "manifest_version": 2, + // ... + "browser_action": { + "default_title": "Some Title" + }, + "web_accessible_resources": ["icon/*.png"] +} +``` + +```json [MV3] +{ + "manifest_version": 3, + // ... + "action": { + "default_title": "Some Title" + }, + "web_accessible_resources": [ + { + "matches": ["*://*.google.com/*"], + "resources": ["icon/*.png"] + } + ] +} +``` + +::: + +You can also specify properties specific to a single manifest version, and they will be stripped out when targeting the other manifest version. + +## Name + +> [Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/manifest/name/) + +If not provided via the `manifest` config, the manifest's `name` property defaults to your `package.json`'s `name` property. + +## Version and Version Name + +> [Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/manifest/version/) + +Your extension's `version` and `version_name` is based on the `version` from your `package.json`. + +- `version_name` is the exact string listed +- `version` is the string cleaned up, with any invalid suffixes removed + +Example: + +```json +// package.json +{ + "version": "1.3.0-alpha2" +} +``` + +```json +// .output//manifest.json +{ + "version": "1.3.0", + "version_name": "1.3.0-alpha2" +} +``` + +If a version is not present in your `package.json`, it defaults to `"0.0.0"`. + +## Icons + +WXT automatically discovers your extension's icon by looking at files in the `public/` directory: + +``` +public/ +├─ icon-16.png +├─ icon-24.png +├─ icon-48.png +├─ icon-96.png +└─ icon-128.png +``` + +Specifically, if an icon must match one of these regex to be discovered: + +<<< @/../packages/wxt/src/core/utils/manifest.ts#snippet + +If you don't like these filename or you're migrating to WXT and don't want to rename the files, you can manually specify an `icon` in your manifest: + +```ts +export default defineConfig({ + manifest: { + icons: { + 16: '/extension-icon-16.png', + 24: '/extension-icon-24.png', + 48: '/extension-icon-48.png', + 96: '/extension-icon-96.png', + 128: '/extension-icon-128.png', + }, + }, +}); +``` + +Alternatively, you can use [`@wxt-dev/auto-icons`](https://www.npmjs.com/package/@wxt-dev/auto-icons) to let WXT generate your icon at the required sizes. + +## Permissions + +> [Chrome docs](https://developer.chrome.com/docs/extensions/reference/permissions/) + +```ts +export default defineConfig({ + manifest: { + permissions: ['storage', 'tabs'], + }, +}); +``` + +## Host Permissions + +> [Chrome docs](https://developer.chrome.com/docs/extensions/develop/concepts/declare-permissions#host-permissions) + +```ts +export default defineConfig({ + manifest: { + permissions: ['storage', 'tabs'], + }, +}); +``` + +:::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 ? [...] : [...], + }), +}); +``` + +::: + +## Default Locale + +```ts +export default defineConfig({ + manifest: { + name: '__MSG_extName__', + description: '__MSG_extDescription__', + default_locale: 'en', + }, +}); +``` + +> See [I18n docs](/guide/essentials/i18n) for a full guide on internationalizing your extension. + +## Actions + +In MV2, you have two options: [`browser_action`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action) and [`page_action`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/page_action). In MV3, they were merged into a single [`action`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/action) API. + +By default, whenever an `action` is generated, WXT falls back to `browser_action` when targeting MV2. + +### Action With Popup + +To generate a manifest where a UI appears after clicking the icon, just create a [Popup entrypoint](/guide/essentials/entrypoints#popup). + +```ts +export default defineConfig({ + hooks: { + build: { + manifestGenerated(manifest) { + // Update the manifest variable by reference + manifest.name = 'Overriden name'; + }, + }, + }, +}); +``` + +If you want to use a `page_action` for MV2, add the following meta tag to the HTML document's head: + +```html + +``` + +### Action Without Popup + +If you want to use the `activeTab` permission or the `browser.action.onClicked` event, but don't want to show a popup: + +1. Delete the [Popup entrypoint](/guide/essentials/entrypoints#popup) if it exists +2. Add the `action` key to your manifest: + ```ts + export default defineConfig({ + manifest: { + action: {}, + }, + }); + ``` + +Same as an action with a popup, WXT will fallback on using `browser_action` for MV2. To use a `page_action` instead, add that key as well: + +```ts +export default defineConfig({ + manifest: { + action: {}, + page_action: {}, + }, +}); +``` diff --git a/docs/guide/essentials/config/runtime.md b/docs/guide/essentials/config/runtime.md new file mode 100644 index 00000000..084a43f5 --- /dev/null +++ b/docs/guide/essentials/config/runtime.md @@ -0,0 +1,56 @@ +# Runtime Config + +> This API is still a WIP, with more features coming soon! + +Define runtime configuration in a single place, `/app.config.ts`: + +```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', +}); +``` + +:::warning +This file is committed to the repo, so don't put any secrets here. Instead, use [Environment Variables](#environment-variables) +::: + +To access runtime config, WXT provides the `useAppConfig` function: + +```ts +import { useAppConfig } from 'wxt/sandbox'; + +console.log(useAppConfig()); // { theme: "dark" } +``` + +## Environment Variables in App Config + +You can use environment variables in the `app.config.ts` file. + +```ts +declare module 'wxt/sandbox' { + export interface WxtAppConfig { + apiKey?: string; + skipWelcome: boolean; + } +} + +export default defineAppConfig({ + apiKey: import.meta.env.VITE_API_KEY, + skipWelcome: import.meta.env.VITE_SKIP_WELCOME === 'true', +}); +``` + +This has several advantages: + +- Define all expected environment variables in a single file +- Convert strings to other types, like booleans or arrays +- Provide default values if an environment variable is not provided diff --git a/docs/guide/essentials/config/typescript.md b/docs/guide/essentials/config/typescript.md new file mode 100644 index 00000000..be220883 --- /dev/null +++ b/docs/guide/essentials/config/typescript.md @@ -0,0 +1,65 @@ +# TypeScript Configuration + +When you run [`wxt prepare`](/api/cli/wxt-prepare), WXT generates a base TSConfig file for your project at `/.wxt/tsconfig.json`. + +At a minimum, you need to create a TSConfig in your root directory that looks like this: + +```jsonc +// /tsconfig.json +{ + "extends": ".wxt/tsconfig.json", +} +``` + +Or if you're in a monorepo, you may not want to extend the config. If you don't extend it, you need to add `.wxt/wxt.d.ts` to the TypeScript project: + +```ts +/// +``` + +## Compiler Options + +To specify custom compiler options, add them in `/tsconfig.json`: + +```jsonc +// /tsconfig.json +{ + "extends": ".wxt/tsconfig.json", + "compilerOptions": { + "jsx": "preserve", + }, +} +``` + +## TSConfig Paths + +WXT provides a default set of path aliases. + +| Alias | To | Example | +| ----- | ------------- | ----------------------------------------------- | +| `~~` | `/*` | `import "~~/scripts"` | +| `@@` | `/*` | `import "@@/scripts"` | +| `~` | `/*` | `import { toLowerCase } from "~/utils/strings"` | +| `@` | `/*` | `import { toLowerCase } from "@/utils/strings"` | + +To add your own, DO NOT add them to your `tsconfig.json`! Instead, use the [`alias` option](/api/reference/wxt/interfaces/InlineConfig#alias) in `wxt.config.ts`. + +This will add your custom aliases to `/.wxt/tsconfig.json` next time you run `wxt prepare`. It also adds your alias to the bundler so it can resolve imports. + +```ts +import { resolve } from 'node:path'; + +export default defineConfig({ + alias: { + // Directory: + testing: resolve('utils/testing'), + // File: + strings: resolve('utils/strings.ts'), + }, +}); +``` + +```ts +import { fakeTab } from 'testing/fake-objects'; +import { toLowerCase } from 'strings'; +``` diff --git a/docs/guide/essentials/config/vite.md b/docs/guide/essentials/config/vite.md new file mode 100644 index 00000000..47bb8eff --- /dev/null +++ b/docs/guide/essentials/config/vite.md @@ -0,0 +1,68 @@ +# Vite + +WXT uses [Vite](https://vitejs.dev/) under the hood to bundle your extension. + +This page explains how to customize your project's Vite config. Refer to [Vite's documentation](https://vite.dev/config/) to learn more about configuring the bundler. + +:::tip +In most cases, you shouldn't change Vite's build settings. WXT provides sensible defaults that output a valid extension accepted by all stores when publishing. +::: + +## Change Vite Config + +You can change Vite's config via the `wxt.config.ts` file: + +```ts +// wxt.config.ts +import { defineConfig } from 'wxt'; + +export default defineConfig({ + vite: () => ({ + // Override config here, same as `defineConfig({ ... })` + // inside vite.config.ts files + }), +}); +``` + +## Add Vite Plugins + +To add a plugin, install the NPM package and add it to the Vite config: + +```ts +// wxt.config.ts +import { defineConfig } from 'wxt'; +import VueRouter from 'unplugin-vue-router/vite'; + +export default defineConfig({ + vite: () => ({ + plugins: [ + VueRouter({ + /* ... */ + }), + ], + }), +}); +``` + +:::warning +Due to the way WXT orchestrates Vite builds, some plugins may not work as expected. For example, `vite-plugin-remove-console` normally only runs when you build for production (`vite build`). However, WXT uses a combination of dev server and builds during development, so you need to manually tell it when to run: + +```ts +// wxt.config.ts +import { defineConfig } from 'wxt'; +import removeConsole from 'vite-plugin-remove-console'; + +export default defineConfig({ + vite: (configEnv) => ({ + plugins: + configEnv.mode === 'production' + ? [removeConsole({ includes: ['log'] })] + : [], + }), +}); +``` + +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 an issue doesn't exist for your plugin, [open a new one](https://github.com/wxt-dev/wxt/issues/new/choose). +::: diff --git a/docs/guide/key-concepts/content-script-ui.md b/docs/guide/essentials/content-scripts.md similarity index 58% rename from docs/guide/key-concepts/content-script-ui.md rename to docs/guide/essentials/content-scripts.md index c75935ee..caf74255 100644 --- a/docs/guide/key-concepts/content-script-ui.md +++ b/docs/guide/essentials/content-scripts.md @@ -1,8 +1,102 @@ -# Content Script UI +--- +outline: deep +--- -There are three ways to mount a UI inside a content script: +# Content Scripts -[[toc]] +## Context + +The first argument to a content script's `main` function is it's "context". + +```ts +// entrypoints/content.ts +export default defineContentScript({ + main(ctx) {}, +}); +``` + +This object is responsible for tracking whether or not the content script's context is "invalidated". Most browsers, by default, do not stop content scripts if the extension is uninstalled, updated, or disabled. When this happens, content scripts start reporting this error: + +``` +Error: Extension context invalidated. +``` + +The `ctx` object provides several helpers to stop asynchronous code from running once the context is invalidated: + +```ts +ctx.addEventListener(...); +ctx.setTimeout(...); +ctx.setInterval(...); +ctx.requestAnimationFrame(...); +// and more +``` + +You can also check if the context is invalidated manually: + +```ts +if (ctx.isValid) { + // do something +} +// OR +if (ctx.isInvalid) { + // do something +} +``` + +## CSS + +In regular web extensions, CSS for content scripts is usually a separate CSS file, that is added to a CSS array in the manifest: + +```json +{ + "content_scripts": [ + { + "css": ["content/style.css"], + "js": ["content/index.js"], + "matches": ["*://*/*"] + } + ] +} +``` + +In WXT, to add CSS to a content script, simply import the CSS file into your JS entrypoint, and WXT will automatically add the bundled CSS output to the `css` array. + +```ts +// entrypoints/content/index.ts +import './style.css'; + +export default defineContentScript({ + // ... +}); +``` + +To create a standalone content script that only includes a CSS file: + +1. Create the CSS file: `entrypoints/example.content.css` +2. Use the `build:manifestGenerated` hook to add the content script to the manifest: + ```ts + // wxt.config.ts + export default defineConfig({ + hooks: { + "build:manifestGenerated": (wxt, manifest) => { + manifest.content_scripts ??= []; + manifest.content_scripts.push({ + // Build extension once to see where your CSS get's written to + css: ["content-scripts/example.css"], + matches: ["*://*/*"] + ) + } + } + }) + ``` + +## UI + +WXT provides 3 built-in utilities for adding UIs to a page from a content script: + +- [Integrated](#integrated) - `createIntegratedUi` +- [Shadow Root](#shadow-root) -`createShadowRootUi` +- [IFrame](#iframe) - `createIframeUi` Each has their own set of advantages and disadvantages. @@ -12,7 +106,7 @@ Each has their own set of advantages and disadvantages. | Shadow Root | ✅ | ✅ (off by default) | ❌ | ✅ | | IFrame | ✅ | ✅ | ✅ | ❌ | -## Integrated +### Integrated Integrated content script UIs are injected alongside the content of a page. This means that they are affected by CSS on that page. @@ -26,6 +120,7 @@ export default defineContentScript({ main(ctx) { const ui = createIntegratedUi(ctx, { position: 'inline', + anchor: 'body', onMount: (container) => { // Append children to the container const app = document.createElement('p'); @@ -51,6 +146,7 @@ export default defineContentScript({ main(ctx) { const ui = createIntegratedUi(ctx, { position: 'inline', + anchor: 'body', onMount: (container) => { // Create the app and mount it to the UI container const app = createApp(App); @@ -80,6 +176,7 @@ export default defineContentScript({ main(ctx) { const ui = createIntegratedUi(ctx, { position: 'inline', + anchor: 'body', onMount: (container) => { // Create a root on the UI container and render a component const root = ReactDOM.createRoot(container); @@ -108,6 +205,7 @@ export default defineContentScript({ main(ctx) { const ui = createIntegratedUi(ctx, { position: 'inline', + anchor: 'body', onMount: (container) => { // Create the Svelte app inside the UI container const app = new App({ @@ -137,6 +235,7 @@ export default defineContentScript({ main(ctx) { const ui = createIntegratedUi(ctx, { position: 'inline', + anchor: 'body', onMount: (container) => { // Render your app to the UI container const unmount = render(() =>

...
, container); @@ -157,13 +256,11 @@ export default defineContentScript({ See the [API Reference](/api/reference/wxt/client/functions/createIntegratedUi) for the complete list of options. -You can control how CSS is injected for an integrated content script UI with the [`cssInjectionMode`](/api/reference/wxt/interfaces/BaseContentScriptEntrypointOptions#cssinjectionmode) property. Usually, you'll want to leave it as `"manifest"`, the default, so the UI inherits its style from the website's CSS. - -## Shadow Root +### Shadow Root Often in web extensions, you don't want your content script's CSS affecting the page, or vise-versa. The [`ShadowRoot`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot) API is ideal for this. -WXT's [`createShadowRootUi`](/api/reference/wxt/client/functions/createShadowRootUi) abstracts all the `ShadowRoot` setup away, making it easy to create UIs with isolated CSS. It also supports an optional `isolateEvents` parameter to further isolate user interactions. +WXT's [`createShadowRootUi`](/api/reference/wxt/client/functions/createShadowRootUi) abstracts all the `ShadowRoot` setup away, making it easy to create UIs whose styles are isolated from the page. It also supports an optional `isolateEvents` parameter to further isolate user interactions. To use `createShadowRootUi`, follow these steps: @@ -188,6 +285,7 @@ export default defineContentScript({ const ui = await createShadowRootUi(ctx, { name: 'example-ui', position: 'inline', + anchor: 'body', onMount(container) { // Define how your UI will be mounted inside the container const app = document.createElement('p'); @@ -218,6 +316,7 @@ export default defineContentScript({ const ui = await createShadowRootUi(ctx, { name: 'example-ui', position: 'inline', + anchor: 'body', onMount: (container) => { // Define how your UI will be mounted inside the container const app = createApp(App); @@ -252,6 +351,7 @@ export default defineContentScript({ const ui = await createShadowRootUi(ctx, { name: 'example-ui', position: 'inline', + anchor: 'body', onMount: (container) => { // Container is a body, and React warns when creating a root on the body, so create a wrapper div const app = document.createElement('div'); @@ -289,6 +389,7 @@ export default defineContentScript({ const ui = await createShadowRootUi(ctx, { name: 'example-ui', position: 'inline', + anchor: 'body', onMount: (container) => { // Create the Svelte app inside the UI container const app = new App({ @@ -323,6 +424,7 @@ export default defineContentScript({ const ui = await createShadowRootUi(ctx, { name: 'example-ui', position: 'inline', + anchor: 'body', onMount: (container) => { // Render your app to the UI container const unmount = render(() =>
...
, container); @@ -343,17 +445,18 @@ export default defineContentScript({ See the [API Reference](/api/reference/wxt/client/functions/createShadowRootUi) for the complete list of options. -:::info TailwindCSS -`createShadowRootUi` supports TailwindCSS out of the box! When importing the styles, just import the main CSS file containing the `@tailwind` directives, and everything will just work :+1:. -::: +Full examples: -## IFrame +- [react-content-script-ui](https://github.com/wxt-dev/examples/tree/main/examples/react-content-script-ui) +- [tailwindcss](https://github.com/wxt-dev/examples/tree/main/examples/tailwindcss) + +### IFrame If you don't need to run your UI in the same frame as the content script, you can use an IFrame to host your UI instead. Since an IFrame just hosts an HTML page, **_HMR is supported_**. WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/functions/createIframeUi), which simplifies setting up the IFrame. -1. Create an HTML page that will be loaded into your IFrame +1. Create an HTML page that will be loaded into your IFrame: ```html @@ -368,7 +471,7 @@ WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/fun ``` -1. Add the page to the manifest's `web_accessible_resources` +1. Add the page to the manifest's `web_accessible_resources`: ```ts // wxt.config.ts export default defineConfig({ @@ -382,7 +485,7 @@ WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/fun }, }); ``` -1. Create and mount the IFrame +1. Create and mount the IFrame: ```ts export default defineContentScript({ @@ -393,6 +496,7 @@ WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/fun const ui = createIframeUi(ctx, { page: '/example-iframe.html', position: 'inline', + anchor: 'body', onMount: (wrapper, iframe) => { // Add styles to the iframe like width iframe.width = '123'; @@ -406,3 +510,104 @@ WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/fun ``` See the [API Reference](/api/reference/wxt/client/functions/createIframeUi) for the complete list of options. + +## Isolated World vs Main World + +By default, all content scripts run in an isolated context where only the DOM is shared with the webpage it is running on - an "isolated world". In MV3, Chromium introduced the ability to run content scripts in the "main" world - where everything, not just the DOM, is available to the content script, just like if the script were loaded by the webpage. + +You can enable this for a content script by setting the `world` option: + +```ts +export default defineContentScript({ + world: 'MAIN', +}); +``` + +However, this approach has several notable drawbacks: + +- Doesn't support MV2 +- `world: "MAIN"` is only supported by Chromium browsers +- Main world content scripts don't have access to the extension API + +Instead, WXT recommends injecting a script into the main world manually using it's `injectScript` function. This will address the drawbacks mentioned before. + +- `injectScript` supports both MV2 and MV3 +- `injectScript` supports all browsers +- Having a "parent" content script means you can send messages back and forth, making it possible to access the extension API + +To use `injectScript`, we need two entrypoints, one content script and one unlisted script: + + +```html +📂 entrypoints/ + 📄 example.content.ts + 📄 example-main-world.ts +``` + +```ts +// entrypoints/example-main-world.ts +export default defineUnlistedScript(() => { + console.log('Hello from the main world!'); +}); +``` + +```ts +// entrypoints/example.content.ts +export default defineContentScript(async () => { + await injectScript('/example-main-world.js', { + keepInDom: true, + }); +}); +``` + +`injectScript` works by creating a `script` element on the page pointing to your script. This loads the script into the page's context so it runs in the main world. + +`injectScript` returns a promise, that when resolved, means the script has been evaluated by the browser and you can start communicating with it. + +:::warning Warning: `run_at` Caveat +For MV3, `injectScript` is synchronous and the injected script will be evaluated at the same time as your the content script's `run_at`. + +However for MV2, `injectScript` has to `fetch` the script's text content and create an inline ` + +``` + +## Background + +In your background script, set `type: "module"`: + +```ts +export default defineBackground({ + type: 'module', // !code ++ + main() { + // ... + }, +}); +``` + +:::warning +Only MV3 supports ESM background scripts/service workers. When targeting MV2, the `type` option is ignored and the background is always bundled into a single file as IIFE. +::: + +## Content Scripts + +WXT does not yet include built-in support for ESM content scripts. The plan is to add support for chunking to reduce bundle size, but not support HMR for now. There are several technical issues that make implementing a generic solution for HMR impossible. See [Content Script ESM Support #357](https://github.com/wxt-dev/wxt/issues/357) for details. + +If you can't wait, and need ESM support right now, you can implement ESM support manually. See the [ESM Content Script UI](https://github.com/wxt-dev/examples/tree/main/examples/esm-content-script-ui) example to get started. diff --git a/docs/guide/essentials/extension-apis.md b/docs/guide/essentials/extension-apis.md new file mode 100644 index 00000000..529558d8 --- /dev/null +++ b/docs/guide/essentials/extension-apis.md @@ -0,0 +1,92 @@ +# Extension APIs + +[Chrome Docs](https://developer.chrome.com/docs/extensions/reference/api) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs) + +Different browsers provide different global variables for accessing the extension APIs (chrome provides `chrome`, firefox provides `browser`, etc). + +WXT simplifies this - always use `browser`: + +```ts +browser.action.onClicked.addListener(() => { + // ... +}); +``` + +Other than that, refer to Chrome and Mozilla's documentation for how to use specific APIs. Everything a normal extension can do, WXT can do as well, just via `browser` instead of `chrome`. + +## Webextension Polyfill + +> Since `v0.1.0` + +By default, WXT uses the [`webextension-polyfill` by Mozilla](https://www.npmjs.com/package/webextension-polyfill) to make the extension API consistent between browsers. + +To access types, you should import the relevant namespace from `wxt/browser`: + +```ts +import { Runtime } from 'wxt/browser'; + +function handleMessage(message: any, sender: Runtime.Sender) { + // ... +} +``` + +### Disabling the polyfill + +> Since `v0.19.0` + +After the release of MV3 and Chrome's official deprecation of MV2 in June 2024, the polyfill isn't really doing anything useful anymore. + +You can disable it with a single line: + +```ts +// wxt.config.ts +export default defineConfig({ + extensionApi: 'chrome', +}); +``` + +This will change `wxt/browser` to simply export the `browser` or `chrome` globals based on browser at runtime: + +<<< @/../packages/wxt/src/browser/chrome.ts#snippet + +Accessing types is a little different with the polyfill disabled. They do not need to be imported; they're available on the `browser` object itself: + +```ts +function handleMessage(message: any, sender: browser.runtime.Sender) { + // ... +} +``` + +## Feature Detection + +Depending on the manifest version and browser, some APIs are not available at runtime. If an API is not available, it will be `undefined`. + +:::warning +Types will not help you here. The types WXT provides for `browser` assume all APIs exist. You are responsible for knowing whether an API is available or not. +::: + +To check if an API is available, use feature detection: + +```ts +if (browser.runtime.onSuspend != null) { + browser.runtime.onSuspend.addListener(() => { + // ... + }); +} +``` + +Here, [optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) is your best friend: + +```ts +browser.runtime.onSuspend?.addListener(() => { + // ... +}); +``` + +Alternatively, if you're trying to use similar APIs under different names (to support MV2 and MV3), you can do something like this: + +```ts +(browser.action ?? browser.browser_action).onClicked.addListener(() => { + // +}); +``` diff --git a/docs/guide/key-concepts/frontend-frameworks.md b/docs/guide/essentials/frontend-frameworks.md similarity index 56% rename from docs/guide/key-concepts/frontend-frameworks.md rename to docs/guide/essentials/frontend-frameworks.md index c5295310..27657a35 100644 --- a/docs/guide/key-concepts/frontend-frameworks.md +++ b/docs/guide/essentials/frontend-frameworks.md @@ -2,7 +2,7 @@ ## Built-in Modules -WXT has preconfigured modules for 4 frameworks: +WXT has preconfigured modules for the most popular frontend frameworks: - [`@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) @@ -64,45 +64,36 @@ export default defineConfig({ }); ``` -The WXT modules just simplify the configuration and add auto-imports. They're not much different than the above. +> The WXT modules just simplify the configuration and add auto-imports. They're not much different than the above. ## Multiple Apps -Since web extensions usually contain multiple UIs as separate HTML files (popup, options, changelog, side panel, etc), you'll need to create individual app instances, one per HTML page. +Since web extensions usually contain multiple UIs across multiple entrypoints (popup, options, changelog, side panel, content scripts, etc), you'll need to create individual app instances, one per entrypoint. -Usually, this means each entrypoint should be a directory with it's own files inside it: +Usually, this means each entrypoint should be a directory with it's own files inside it. Here's the recommended folder structure: -``` -/ - ├ assets/ <------------------ Put shared assets here - │ ├ style.css <------------ Like styles all your pages share - │ └ ... - ├ components/ <-------------- Put shared components here - │ └ ... - └ entrypoints/ - ├ popup/ <--------------- Use a folder with an index.html file in it - │ ├ index.html - │ ├ main.tsx <--------- Create and mount your app here - │ ├ style.css <-------- Have some global styles to apply? - │ └ ... <--------------- Rest of the files can be named whatever - └ options/ - ├ pages/ <------------ A good place to put your router pages - │ ├ [id]/ - │ │ └ details.tsx - │ ├ index.tsx - │ └... - ├ index.html - ├ App.vue - ├ main.ts - ├ style.css - └ router.ts + +```html +📂 {srcDir}/ + 📂 assets/ <---------- Put shared assets here + 📄 tailwind.css + 📂 components/ + 📄 Button.tsx + 📂 entrypoints/ + 📂 options/ <--------- Use a folder with an index.html file in it + 📁 pages/ <--------- A good place to put your router pages if you have them + 📄 index.html + 📄 App.tsx + 📄 main.tsx <--------- Create and mount your app here + 📄 style.css <--------- Entrypoint-specific styles + 📄 router.ts ``` ## Configuring Routers -Lots of frameworks come with routers for building a multi-page app using the URL's path. Chrome extensions 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. +All frameworks come with routers for building a multi-page app using the URL's path... But web extensions 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 a part 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: diff --git a/docs/guide/essentials/i18n.md b/docs/guide/essentials/i18n.md new file mode 100644 index 00000000..9c012986 --- /dev/null +++ b/docs/guide/essentials/i18n.md @@ -0,0 +1,86 @@ +# I18n + +[Chrome Docs](https://developer.chrome.com/docs/extensions/reference/api/i18n) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n) + +This page discusses how to setup internationalization using the vanilla `browser.i18n` APIs and mentions some alternatives if you want to use something else. + +[[toc]] + +## Usage + +1. Add `default_locale` to your manifest: + ```ts + export default defineConfig({ + manifest: { + default_locale: 'en', + }, + }); + ``` +2. Create `messages.json` files in the `public/` directory: + + + ```html + 📂 {srcDir}/ + 📂 public/ + 📂 _locales/ + 📂 en/ + 📄 messages.json + 📂 de/ + 📄 messages.json + 📂 ko/ + 📄 messages.json + ``` + + ```jsonc + // public/_locales/en/messages.json + { + "helloWorld": { + "message": "Hello world!", + }, + } + ``` + +3. Get the translation: + ```ts + browser.i18n.getMessage('helloWorld'); + ``` +4. _Optional_: Add translations for extension name and description: + +```json +{ + "extName": { + "message": "..." + }, + "extDescription": { + "message": "..." + }, + "helloWorld": { + "message": "Hello world!" + } +} +``` + +```ts +export default defineConfig({ + manifest: { + name: '__MSG_extName__', + description: '__MSG_extDescription__', + default_locale: 'en', + }, +}); +``` + +## Alternatives + +The vanilla API has very few features, which is why you may want to consider using third-party NPM packages like `i18next`, `react-i18n`, `vue-i18n`, etc. + +However, it is recommended you stick with the vanilla API (or a package based on top of the vanilla API, like [`@wxt-dev/i18n`](/i18n)), because: + +- They can localize text in your manifest and CSS files +- Translations are loaded synchronously +- Translations are not bundled multiple times, keeping your extension small +- Zero configuration + +Here are some examples of how to setup a third party i18n library: + +- [vue-i18n](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vue-i18n) diff --git a/docs/guide/essentials/messaging.md b/docs/guide/essentials/messaging.md new file mode 100644 index 00000000..2cb8d5bd --- /dev/null +++ b/docs/guide/essentials/messaging.md @@ -0,0 +1,16 @@ +# Messaging + +[Chrome Docs](https://developer.chrome.com/docs/extensions/develop/concepts/messaging) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#communicating_with_background_scripts) + +Read the docs linked above to learn more about using the vanilla messaging APIs. + +## Alternatives + +The vanilla APIs are difficult to use and are a pain point to many new extension developers. For this reason, WXT recommends installing an NPM package that wraps around the vanilla APIs. + +Here are some popular messaging libraries that support all browsers and work with WXT: + +- [`trpc-chrome`](https://www.npmjs.com/package/trpc-chrome) - [tRPC](https://trpc.io/) adapter for Web Extensions. +- [`webext-bridge`](https://www.npmjs.com/package/webext-bridge) - Messaging in WebExtensions made super easy. Out of the box. +- [`@webext-core/messaging`](https://www.npmjs.com/package/@webext-core/messaging) - Light weight, type-safe wrapper around the web extension messaging APIs +- [`@webext-core/proxy-service`](https://www.npmjs.com/package/@webext-core/proxy-service) - A type-safe wrapper around the web extension messaging APIs that lets you call a function from anywhere, but execute it in the background. diff --git a/docs/guide/essentials/project-structure.md b/docs/guide/essentials/project-structure.md new file mode 100644 index 00000000..d8cb3959 --- /dev/null +++ b/docs/guide/essentials/project-structure.md @@ -0,0 +1,101 @@ +# Project Structure + +WXT follows a strict project structure. By default, it's a flat folder structure that looks like this: + + +```html +📂 {rootDir}/ + 📁 .output/ + 📁 .wxt/ + 📁 assets/ + 📁 components/ + 📁 composables/ + 📁 entrypoints/ + 📁 hooks/ + 📁 modules/ + 📁 public/ + 📁 utils/ + 📄 .env + 📄 .env.publish + 📄 app.config.ts + 📄 package.json + 📄 tsconfig.json + 📄 web-ext.config.ts + 📄 wxt.config.ts +``` + +Here's a brief summary of each of these files and directories: + +- `.output/`: All build artifacts will go here +- `.wxt/`: Generated by WXT, it contains TS config +- `assets/`: Contains all CSS, images, and other assets that should be processed by WXT +- `components/`: Auto-imported by default, contains UI components +- `composables/`: Auto-imported by default, contains composable functions for Vue +- `entrypoints/`: Contains all the entrypoints that get bundled into your extension +- `hooks/`: Auto-imported by default, contains hooks for React and Solid +- `public/`: Contains any files you want to copy into the output folder as-is, without being processed by WXT +- `utils/`: Auto-imported by default, contains generic utilities used throughout your project +- `.env`: Contains [Environment Variables](/guide/essentials/config/runtime#environment-variables) +- `.env.publish`: Contains Environment Variables for [publishing](/guide/essentials/publishing) +- `app.config.ts`: Contains [Runtime Config](/guide/essentials/config/runtime) +- `package.json`: The standard file used by your package manager +- `tsconfig.json`: Config telling TypeScript how to behave +- `web-ext.config.ts`: Configure [Browser Startup](/guide/essentials/config/browser-startup) +- `wxt.config.ts`: The main config file for WXT projects + +## Adding a `src/` Directory + +Many developers like having a `src/` directory to separate source code from configuration files. You can enable it inside the `wxt.config.ts` file: + +```ts +// wxt.config.ts +export default defineConfig({ + srcDir: 'src', +}); +``` + +After enabling it, your project structure should look like this: + + +```html +📂 {rootDir}/ +📁 .output/ +📁 .wxt/ +📂 src/ + 📁 assets/ + 📁 components/ + 📁 composables/ + 📁 entrypoints/ + 📁 hooks/ + 📁 modules/ + 📁 public/ + 📁 utils/ + 📄 app.config.ts +📄 .env +📄 .env.publish +📄 package.json +📄 tsconfig.json +📄 web-ext.config.ts +📄 wxt.config.ts +``` + +## Customizing Other Directories + +You can configure the following directories: + + +```ts +// wxt.config.ts +export default defineConfig({ + // Relative to project root + srcDir: "src", // default: "." + outDir: "dist", // default: ".output" + + // Relative to srcDir + entrypointsDir: "entries", // default: "entrypoints" + modulesDir: "wxt-modules", // default: "modules" + publicDir: "static", // default: "public" +}) +``` + +You can use absolute or relative paths. diff --git a/docs/get-started/publishing.md b/docs/guide/essentials/publishing.md similarity index 84% rename from docs/get-started/publishing.md rename to docs/guide/essentials/publishing.md index f51373fd..7edf7d1d 100644 --- a/docs/get-started/publishing.md +++ b/docs/guide/essentials/publishing.md @@ -4,7 +4,7 @@ outline: deep # Publishing -WXT will help you ZIP your extensions and submit them to the stores for review. +WXT can ZIP your extension and submit it to various stores for review or for self-hosting. ## First Time Publishing @@ -18,7 +18,7 @@ For specific details about each store, see the stores sections below. ## Automation -WXT provides two commands to help automate the release process: +WXT provides two commands to help automate submitting a new version for review and publishing: - `wxt submit init`: Setup all the required secrets and options for the `wxt submit` command - `wxt submit`: Submit new versions of your extension for review (and publish them automatically once approved) @@ -27,7 +27,7 @@ To get started, run `wxt submit init` and follow the prompts. Once finished, you > In CI, make sure you add all the environment variables to the submit step. -To release an update, build all the ZIPs you plan on releasing: +To submit a new version for publishing, build all the ZIPs you plan on releasing: ```sh wxt zip @@ -36,29 +36,25 @@ wxt zip -b firefox Then run the `wxt submit` command, passing in all the ZIP files you want to release. In this case, we'll do a release for all 3 major stores: Chrome Web Store, Edge Addons, and Firefox Addons Store. -If it's your first time running the command, you'll want to test your secrets by passing the `--dry-run` flag: +If it's your first time running the command or you recently made changes to the release process, you'll want to test your secrets by passing the `--dry-run` flag. ```sh wxt submit --dry-run \ - --chrome-zip .output/--chrome.zip \ - --firefox-zip .output/--firefox.zip --firefox-sources-zip .output/--sources.zip \ - --edge-zip .output/--chrome.zip + --chrome-zip .output/{your-extension}-{version}-chrome.zip \ + --firefox-zip .output/{your-extension}-{version}-firefox.zip --firefox-sources-zip .output/{your-extension}-{version}-sources.zip \ + --edge-zip .output/{your-extension}-{version}-chrome.zip ``` If the dry run passes, remove the flag and do the actual release: ```sh wxt submit \ - --chrome-zip .output/--chrome.zip \ - --firefox-zip .output/--firefox.zip --firefox-sources-zip .output/--sources.zip \ - --edge-zip .output/--chrome.zip + --chrome-zip .output/{your-extension}-{version}-chrome.zip \ + --firefox-zip .output/{your-extension}-{version}-firefox.zip --firefox-sources-zip .output/{your-extension}-{version}-sources.zip \ + --edge-zip .output/{your-extension}-{version}-chrome.zip ``` -:::tip -If you only need to release to a single store, only pass that store's ZIP flag. -::: - -:::tip +:::warning See the [Firefox Addon Store](#firefox-addon-store) section for more details about the `--firefox-sources-zip` option. ::: @@ -133,9 +129,7 @@ wxt zip Firefox requires you to upload a ZIP of your source code. This allows them to rebuild your extension and review the code in a readable way. More details can be found in [Firefox's docs](https://extensionworkshop.com/documentation/publish/source-code-submission/). -WXT fully supports generating and automatically submitting a source code ZIP. - -When you run `wxt zip -b firefox`, your sources are zipped into the `.output` directory alongside the extension. WXT will automatically exclude certain files such as config files, hidden files, and tests. However, it's important to manually check the ZIP to ensure it only contains the files necessary to rebuild your extension. +When running `wxt zip -b firefox`, WXT will zip both your extension and sources. Certain files (such as config files, hidden files, and tests) are automatically excluded from your sources. However, it's important to manually check the ZIP to ensure it only contains the files necessary to rebuild your extension. To customize which files are zipped, add the `zip` option to your config file. @@ -181,7 +175,7 @@ Ensure that you have a `README.md` or `SOURCE_CODE_REVIEW.md` file with the abov 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 -If you use a `.env` files, they can effect the chunk hashes in the output directory. Either delete the .env file before running `wxt zip -b firefox`, or include it in your sources zip with the [`zip.includeSources`](/api/reference/wxt/interfaces/InlineConfig#includesources) option. Be careful to not include any secrets in your `.env` files. +If you use a `.env` files, they can affect the chunk hashes in the output directory. Either delete the .env file before running `wxt zip -b firefox`, or include it in your sources zip with the [`zip.includeSources`](/api/reference/wxt/interfaces/InlineConfig#includesources) option. Be careful to not include any secrets in your `.env` files. See Issue [#377](https://github.com/wxt-dev/wxt/issues/377) for more details. ::: @@ -205,7 +199,7 @@ export default defineConfig({ Depending on your package manager, the `package.json` in the sources zip will be modified to use the downloaded dependencies via the `overrides` or `resolutions` field. :::warning -WXT uses the command `npm pack ` to download the package. That means regardless of your package manager, you need to properly setup a `.npmrc` file. NPM and PNPM both respect `.npmrc` files, but Yarn and Bun have their own ways of authorizing private registries, so you'll need to add an `.npmrc` file. +WXT uses the command `npm pack ` to download the package. That means regardless of your package manager, you need to properly setup a `.npmrc` file. NPM and PNPM both respect `.npmrc` files, but Yarn and Bun have their own ways of authorizing private registries, so you'll need to add a `.npmrc` file. ::: ### Safari diff --git a/docs/guide/go-further/remote-code.md b/docs/guide/essentials/remote-code.md similarity index 100% rename from docs/guide/go-further/remote-code.md rename to docs/guide/essentials/remote-code.md diff --git a/docs/guide/extension-apis/scripting.md b/docs/guide/essentials/scripting.md similarity index 70% rename from docs/guide/extension-apis/scripting.md rename to docs/guide/essentials/scripting.md index 9565a739..53b8a304 100644 --- a/docs/guide/extension-apis/scripting.md +++ b/docs/guide/essentials/scripting.md @@ -1,12 +1,12 @@ -# `browser.scripting` +# Scripting -[Chrome Docs](https://developer.chrome.com/docs/extensions/reference/api/scripting) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting) +[Chrome Docs](https://developer.chrome.com/docs/extensions/reference/api/scripting) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting) Refer to the browser docs above for basics on how the API works. ## Execute Script Return Values -When using `browser.scripting.executeScript`, you can execute content scripts or unlisted scripts. To return a value, just return a value from the script's main function. +When using `browser.scripting.executeScript`, you can execute content scripts or unlisted scripts. To return a value, just return a value from the script's `main` function. ```ts // entrypoints/background.ts @@ -19,7 +19,7 @@ console.log(res); // "Hello John!" ```ts // entrypoints/injected.js -export default defineContentScript(() => { +export default defineUnlistedScript(() => { console.log('Script was injected!'); return 'Hello John!'; }); diff --git a/docs/guide/essentials/storage.md b/docs/guide/essentials/storage.md new file mode 100644 index 00000000..5213e115 --- /dev/null +++ b/docs/guide/essentials/storage.md @@ -0,0 +1,15 @@ +# Storage + +[Chrome Docs](https://developer.chrome.com/docs/extensions/reference/api/storage) • [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage) + +You can use the vanilla APIs (see docs above), use [WXT's built-in storage API](/storage), or install a package from NPM. + +## Alternatives + +1. [`wxt/storage`](/storage) (recommended): WXT ships with its own wrapper around the vanilla storage APIs that simplifies common use cases + +2. DIY: If you're migrating to WXT and already have a storage wrapper, keep using it. In the future, if you want to delete that code, you can use one of these alternatives, but there's no reason to replace working code during a migration. + +3. Any other NPM package: [There are lots of wrappers around the storage API](https://www.npmjs.com/search?q=chrome%20storage), you can find one you like. Here's some popular ones: + - [`webext-storage`](https://www.npmjs.com/package/webext-storage) - A more usable typed storage API for Web Extensions + - [`@webext-core/storage`](https://www.npmjs.com/package/@webext-core/storage) - A type-safe, localStorage-esque wrapper around the web extension storage APIs diff --git a/docs/guide/essentials/target-different-browsers.md b/docs/guide/essentials/target-different-browsers.md new file mode 100644 index 00000000..680042dd --- /dev/null +++ b/docs/guide/essentials/target-different-browsers.md @@ -0,0 +1,69 @@ +# Targeting Different Browsers + +When building an extension with WXT, you can create multiple builds of your extension targeting different browsers and manifest versions. + +## Target a Browser + +Use the `-b` CLI flag to create a separate build of your extension for a specific browser. By default, `chrome` is targetted. + +```sh +wxt # same as: wxt -b chrome +wxt -b firefox +wxt -b custom +``` + +Targeting a browser has several effects: + +1. During development, when passing `firefox`, WXT will automatically open Firefox with the extension installed. For all other browsers, it will open Chrome/Chromium +2. Changes build-time constants provided by WXT: + - `import.meta.env.BROWSER`: A string, the targeted browser + - `import.meta.env.CHROME`: A boolean equivalent to `import.meta.env.BROWSER === "chrome"` + - `import.meta.env.FIREFOX`: A boolean equivalent to `import.meta.env.BROWSER === "firefox"` + - `import.meta.env.EDGE`: A boolean equivalent to `import.meta.env.BROWSER === "edge"` + - `import.meta.env.SAFARI`: A boolean equivalent to `import.meta.env.BROWSER === "safari"` + - `import.meta.env.OPERA`: A boolean equivalent to `import.meta.env.BROWSER === "opera"` + +## Target a Manifest Version + +To target specific manifest versions, use the `--mv2` or `--mv3` CLI flags. + +:::tip Default Manifest Version +By default, WXT will target MV2 for Safari and Firefox and MV3 for all other browers. +::: + +To get the target manifest version at runtime, use the built-time constant provided by WXT: + +- `import.meta.env.MANIFEST_VERSION`: A number, either `2` or `3` + +## Filtering Entrypoints + +Every entrypoint can be included or excluded when targetting specific browsers via the `include` and `exclude` options. + +Here are some examples: + +- Content script only built when targetting `firefox`: + + ```ts + export default defineContentScript({ + include: ['firefox'], + + main(ctx) { + // ... + }, + }); + ``` + +- HTML file only built for all targets other than `chrome`: + ```html + + + + + + + + + + + + ``` diff --git a/docs/guide/essentials/testing-updates.md b/docs/guide/essentials/testing-updates.md new file mode 100644 index 00000000..e578778b --- /dev/null +++ b/docs/guide/essentials/testing-updates.md @@ -0,0 +1,28 @@ +# Testing Updates + +## Testing Permission Changes + +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. + +You can test if your permission changes will result in a disabled extension: + +- Chromium: Use [Google's Extension Update Testing tool](https://github.com/GoogleChromeLabs/extension-update-testing-tool) +- Firefox: See their [Test Permission Requests](https://extensionworkshop.com/documentation/develop/test-permission-requests/) page +- Safari: Everyone breaks something in production eventually... 🫡 Good luck soldier + +## Update Event + +You can setup a callback that runs after your extension updates like so: + +```ts +browser.runtime.onInstalled.addListener(({ reason }) => { + if (reason === 'update') { + // Do something + } +}); +``` + +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` +2. Use [Google's Extension Update Testing tool](https://github.com/GoogleChromeLabs/extension-update-testing-tool) diff --git a/docs/guide/essentials/unit-testing.md b/docs/guide/essentials/unit-testing.md new file mode 100644 index 00000000..43f38b5a --- /dev/null +++ b/docs/guide/essentials/unit-testing.md @@ -0,0 +1,80 @@ +# Unit Testing + +[[toc]] + +## Vitest + +WXT provides first class support for Vitest for unit testing: + +```ts +// vitest.config.ts +import { defineConfig } from 'vitest/config'; +import { WxtVitest } from 'wxt/testing'; + +export default defineConfig({ + plugins: [WxtVitest()], +}); +``` + +This plugin does several things: + +- Polyfills the extension API, `browser`, with an in-memory implementation using [`@webext-core/fake-browser`](https://webext-core.aklinker1.io/fake-browser/installation) +- Adds all vite config or plugins in `wxt.config.ts` +- Configures auto-imports (if enabled) +- Applies internal WXT vite plugins for things like [bundling remote code](/guide/essentials/remote-code) +- Sets up global variables provided by WXT (`import.meta.env.BROWSER`, `import.meta.env.MANIFEST_VERSION`, `import.meta.env.IS_CHROME`, etc) +- Configures aliases (`@/*`, `@@/*`, etc) so imports can be resolved + +Here are real projects with unit testing setup. Look at the code and tests to see how they're written. + +- [`aklinker1/github-better-line-counts`](https://github.com/aklinker1/github-better-line-counts) +- [`wxt-dev/examples`'s Vitest Example](https://github.com/wxt-dev/examples/tree/main/examples/vitest-unit-testing) + +### Example Tests + +This example demonstrates that you don't have to mock `browser.storage` (used by `wxt/storage`) in tests - [`@webext-core/fake-browser`](https://webext-core.aklinker1.io/fake-browser/installation) implements storage in-memory so it behaves like it would in a real extension! + +```ts +import { describe, it, expect } from 'vitest'; +import { fakeBrowser } from 'wxt/testing'; + +const accountStorage = storage.defineItem('local:account'); + +async function isLoggedIn(): Promise { + const value = await accountStorage.getValue(); + return value != null; +} + +describe('isLoggedIn', () => { + beforeEach(() => { + // See https://webext-core.aklinker1.io/fake-browser/reseting-state + fakeBrowser.reset(); + }); + + it('should return true when the account exists in storage', async () => { + const account: Account = { + username: '...', + preferences: { + // ... + }, + }; + await accountStorage.setValue(account); + + expect(await isLoggedIn()).toBe(true); + }); + + it('should return false when the account does not exist in storage', async () => { + await accountStorage.deleteValue(); + + expect(await isLoggedIn()).toBe(false); + }); +}); +``` + +## Other Testing Frameworks + +To use a different framework, you will likely have to disable auto-imports, setup import aliases, manually mock the extension APIs, and setup the test environment to support all of WXT's features that you use. + +It is possible to do, but will require a bit more setup. Refer to Vitest's setup for an example of how to setup a test environment: + +https://github.com/wxt-dev/wxt/blob/main/packages/wxt/src/testing/wxt-vitest-plugin.ts diff --git a/docs/guide/essentials/wxt-modules.md b/docs/guide/essentials/wxt-modules.md new file mode 100644 index 00000000..e7fa2d4e --- /dev/null +++ b/docs/guide/essentials/wxt-modules.md @@ -0,0 +1,242 @@ +# WXT Modules + +WXT provides a "module system" that let's you run code at different steps in the build process to modify it. + +[[toc]] + +## Adding a Module + +There are two ways to add a module to your project: + +1. **NPM**: install an NPM package, like [`@wxt-dev/auto-icons`](https://www.npmjs.com/package/@wxt-dev/auto-icons) and add it to your config: + ```ts + // wxt.config.ts + export default defineConfig({ + modules: ['@wxt-dev/auto-icons'], + }); + ``` + > Searching for ["wxt module"](https://www.npmjs.com/search?q=wxt%20module) on NPM is a good way to find published WXT modules. +2. **Local**: add a file to your project's `modules/` directory: + ``` + / + modules/ + my-module.ts + ``` + > To learn more about writing your own modules, read the [Writing Modules](/guide/essentials/wxt-modules) docs. + +## Module Options + +WXT modules may require or allow setting custom options to change their behavior. There are two types of options: + +1. **Build-time**: Any config used during the build process, like feature flags +2. **Runtime**: Any config accessed at runtime, like callback functions + +Build-time options are placed in your `wxt.config.ts`, while runtime options is placed in the [`app.config.ts` file](/guide/essentials/config/runtime). Refer to each module's documentation about what options are required and where they should be placed. + +If you use TypeScript, modules augment WXT's types so you will get type errors if options are missing or incorrect. + +## Writing Modules + +Here's what a basic WXT module looks like: + +```ts +import { defineWxtModule } from 'wxt/modules'; + +export default defineWxtModule({ + setup(wxt) { + // Your module code here... + }, +}); +``` + +Each module's setup function is executed after the `wxt.config.ts` file is loaded. The `wxt` object provides everything you need to write a module: + +- Use `wxt.hook(...)` to hook into the build's lifecycle and make changes +- Use `wxt.config` to get the resolved config from the project's `wxt.config.ts` file +- Use `wxt.logger` to log messages to the console +- and more! + +Refer to the [API reference](/api/reference/wxt/interfaces/Wxt) for a complete list of properties and functions available. + +Also to make sure and read about all the [hooks that are available](https://wxt.dev/api/reference/wxt/interfaces/WxtHooks) - they are essential to writing modules. + +### Recipes + +Modules are complex and require a deeper understanding of WXT's code and how it works. The best way to learn is by example. + +#### Update resolved config + +```ts +import { defineWxtModule } from 'wxt/modules'; + +export default defineWxtModule({ + setup(wxt) { + wxt.hook('ready', () => { + wxt.config.outDir = 'dist'; + }); + }, +}); +``` + +#### Add built-time config + +```ts +import { defineWxtModule } from 'wxt/modules'; +import 'wxt'; + +export interface MyModuleOptions { + // Add your build-time options here... +} +declare module 'wxt' { + export interface InlineConfig { + // Add types for the "myModule" key in wxt.config.ts + myModule: MyModuleOptions; + } +} + +export default defineWxtModule({ + configKey: 'myModule', + + // Build time config is available via the second argument of setup + setup(wxt, options) { + console.log(options); + }, +}); +``` + +#### Add runtime config + +```ts +import { defineWxtModule } from 'wxt/modules'; +import 'wxt/sandbox'; + +export interface MyModuleRuntimeOptions { + // Add your runtime options here... +} +declare module 'wxt/sandbox' { + export interface WxtAppConfig { + myModule: MyModuleOptions; + } +} +``` + +Runtime options are returned when calling + +```ts +const config = useAppConfig(); +console.log(config.myModule); +``` + +This is very useful when [generating runtime code](#generate-runtime-module). + +#### Generate output file + +```ts +import { defineWxtModule } from 'wxt/modules'; + +export default defineWxtModule({ + setup(wxt) { + // Relative to the output directory + const generatedFilePath = 'some-file.txt'; + + wxt.hook('build:publicAssets', (_, assets) => { + assets.push({ + relativeDest: generatedFilePath, + contents: 'some generated text', + }); + }); + + wxt.hook('build:manifestGenerated', (_, manifest) => { + manifest.web_accessible_resources ??= []; + manifest.web_accessible_resources.push({ + matches: ['*://*'], + resources: [generatedFilePath], + }); + }); + }, +}); +``` + +This file could then be loaded at runtime: + +```ts +const res = await fetch(browser.runtime.getURL('/some-text.txt')); +``` + +#### Generate runtime module + +Create a file in `.wxt`, add an alias to import it, and add auto-imports for exported variables. + +```ts +import { defineWxtModule } from 'wxt/modules'; +import { resolve } from 'node:path'; + +export default defineWxtModule({ + imports: [ + // Add auto-imports + { from: '#analytics', name: 'analytics' }, + { from: '#analytics', name: 'reportEvent' }, + { from: '#analytics', name: 'reportPageView' }, + ], + + setup(wxt) { + const analyticsModulePath = resolve( + wxt.config.wxtDir, + 'analytics/index.ts', + ); + const analyticsModuleCode = ` + import { createAnalytics } from 'some-module'; + + export const analytics = createAnalytics(useAppConfig().analytics); + export const { reportEvent, reportPageView } = analytics; + `; + + addAlias(wxt, '#analytics', analyticsModulePath); + + wxt.hook('prepare:types', async (_, entries) => { + entries.push({ + path: analyticsModulePath, + text: analyticsModuleCode, + }); + }); + }, +}); +``` + +#### Generate declaration file + +```ts +import { defineWxtModule } from 'wxt/modules'; +import { resolve } from 'node:path'; + +export default defineWxtModule({ + setup(wxt) { + const typesPath = resolve(wxt.config.wxtDir, 'my-module/types.d.ts'); + const typesCode = ` + // Declare global types, perform type augmentation + `; + + wxt.hook('prepare:types', async (_, entries) => { + entries.push({ + path: 'my-module/types.d.ts', + text: ` + // Declare global types, perform type augmentation, etc + `, + // IMPORTANT - without this line your declaration file will not be a part of the TS project: + tsReference: true, + }); + }); + }, +}); +``` + +### Example Modules + +You should also look through the code of modules other people have written and published. Here's some examples: + +- [`@wxt-dev/auto-icons`](https://github.com/wxt-dev/wxt/blob/main/packages/auto-icons) +- [`@wxt-dev/i18n`](https://github.com/wxt-dev/wxt/blob/main/packages/i18n) +- [`@wxt-dev/module-vue`](https://github.com/wxt-dev/wxt/blob/main/packages/module-vue) +- [`@wxt-dev/module-solid`](https://github.com/wxt-dev/wxt/blob/main/packages/module-solid) +- [`@wxt-dev/module-react`](https://github.com/wxt-dev/wxt/blob/main/packages/module-react) +- [`@wxt-dev/module-svelte`](https://github.com/wxt-dev/wxt/blob/main/packages/module-svelte) diff --git a/docs/guide/extension-apis/i18n.md b/docs/guide/extension-apis/i18n.md deleted file mode 100644 index e02e0134..00000000 --- a/docs/guide/extension-apis/i18n.md +++ /dev/null @@ -1,56 +0,0 @@ -# Internationalization - -This guide is for using the vanilla, `browser.i18n` APIs. There are two other alternatives: - -1. [`@wxt-dev/i18n`](/guide/i18n/installation) - a wrapper around `browser.i18n` APIs with additional features, a simplified localization file format, and editor support -2. Third party packages - You can use any i18n package on NPM, most of which are more feature rich than `browser.i18n` and `@wxt-dev/i18n` - -:::info -Currently, using the `browser.i18n` APIs are the recommended approach. WXT has some built-in support for them and they work well enough. `@wxt-dev/i18n` was recently released, and it will become the recommended approach after some of the bugs have been worked out. Head over to [it's docs](/guide/i18n/introduction.md) to learn more. -::: - -## Setup - -First familiarize yourself with [Chrome's docs](https://developer.chrome.com/docs/extensions/reference/api/i18n). The only difference when using these APIs with WXT is where you put the localization files - in the [`public` directory](/guide/directory-structure/public/). - -``` -/ -└─ public/ - └─ _locales/ - ├─ en/ - │ └─ messages.json - ├─ de/ - │ └─ messages.json - └─ ko/ - └─ messages.json -``` - -Next, to set a `default_locale` on your manifest, add it to your `wxt.config.ts` file: - -```ts -// wxt.config.ts -export default defineConfig({ - manifest: { - default_locale: 'en', - name: '__MSG_extName__', - description: '__MSG_extDescription__', - }, -}); -``` - -> You can localize the `name` and `description` of your extension from the `manifest` config as well. - -Finally, to get a translation, call `browser.i18n.getMessage`: - -```ts -browser.i18n.getMessage('extName'); -browser.i18n.getMessage('extDescription'); -browser.i18n.getMessage(/* etc */); -``` - -## Examples - -See the official localization examples for more details: - -- [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) diff --git a/docs/guide/extension-apis/messaging.md b/docs/guide/extension-apis/messaging.md deleted file mode 100644 index a55f1355..00000000 --- a/docs/guide/extension-apis/messaging.md +++ /dev/null @@ -1,36 +0,0 @@ -# Messaging - -## Overview - -Follow [Chrome's message passing guide](https://developer.chrome.com/docs/extensions/mv3/messaging/) to understand how message passing works in web extensions. In Google's examples, just replace `chrome` with `browser`, and it will work in WXT. - -Here's a basic request/response example: - -```ts -// popup/main.ts -const res = await browser.runtime.sendMessage('ping'); - -console.log(res); // "pong" -``` - -```ts -// background.ts -export default defineBackground(() => { - browser.runtime.onMessage.addListener((message, sender, sendResponse) => { - console.log(message); // "ping" - - // Wait 1 second and respond with "pong" - setTimeout(() => sendResponse('pong'), 1000); - return true; - }); -}); -``` - -## Third Party Libraries - -There are a number of message passing libraries you can use to improve the message passing experience. - -- [`@webext-core/messaging`](https://webext-core.aklinker1.io/guide/messaging/) - "A light-weight, type-safe wrapper around the `browser.runtime` messaging APIs" -- [`@webext-core/proxy-service`](https://webext-core.aklinker1.io/guide/proxy-service/) - "Create RPC-like services that can be called from anywhere but run in the background" -- [`webext-bridge`](https://github.com/zikaari/webext-bridge) - "Messaging in Web Extensions made super easy. Out of the box." -- [`trpc-chrome`](https://www.npmjs.com/package/trpc-chrome) - "tRPC adapter for Web Extensions 🧩" diff --git a/docs/guide/extension-apis/others.md b/docs/guide/extension-apis/others.md deleted file mode 100644 index db707c98..00000000 --- a/docs/guide/extension-apis/others.md +++ /dev/null @@ -1,5 +0,0 @@ -# All Other APIs - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/go-further/custom-events.md b/docs/guide/go-further/custom-events.md deleted file mode 100644 index 9963a574..00000000 --- a/docs/guide/go-further/custom-events.md +++ /dev/null @@ -1,5 +0,0 @@ -# Custom Events - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/go-further/debugging.md b/docs/guide/go-further/debugging.md deleted file mode 100644 index 26920e60..00000000 --- a/docs/guide/go-further/debugging.md +++ /dev/null @@ -1,5 +0,0 @@ -# Debugging - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/go-further/entrypoint-loaders.md b/docs/guide/go-further/entrypoint-loaders.md deleted file mode 100644 index 4f295390..00000000 --- a/docs/guide/go-further/entrypoint-loaders.md +++ /dev/null @@ -1,120 +0,0 @@ -# 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() { - // ... - }, -}); -``` diff --git a/docs/guide/go-further/es-modules.md b/docs/guide/go-further/es-modules.md deleted file mode 100644 index ad9a859f..00000000 --- a/docs/guide/go-further/es-modules.md +++ /dev/null @@ -1,40 +0,0 @@ -# ES Modules - -Configure entrypoints to use ESM at runtime. - -Currently, ESM entrypoints are opt-in, so you must configure each entrypoint with that in mind. - -## HTML Pages - -In general, you should always make HTML pages import ESM scripts, unless you need to support old browsers. - -To make a script ESM, add `type="module"`: - - -```html - - -``` - -## Background - -In your background script, set `type: "module"`: - -```ts -export default defineBackground({ - type: 'module', // !code ++ - main() { - // ... - }, -}); -``` - -:::warning -Only MV3 support ESM background scripts/service workers. When targeting MV2, the `type` option is ignored and the background is always bundled into a single file as IIFE. -::: - -## Content Scripts - -WXT does not include built-in support for ESM content scripts. There are several technical issues that make implementing a generic solution impossible. See [Content Script ESM Support #357](https://github.com/wxt-dev/wxt/issues/357) for details. - -Instead, depending on your requirements, you can implement ESM support manually. See the [ESM Content Script UI](https://github.com/wxt-dev/examples/tree/main/examples/esm-content-script-ui) example to get started. diff --git a/docs/guide/go-further/handling-updates.md b/docs/guide/go-further/handling-updates.md deleted file mode 100644 index 63f39d2f..00000000 --- a/docs/guide/go-further/handling-updates.md +++ /dev/null @@ -1,77 +0,0 @@ -# Handling Extension Updates - -When releasing an update to your extension, there's a couple of things you need to keep in mind: - -[[toc]] - -## 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 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. - -When your extension updates or reloads, the context will become invalidated, and will trigger any `ctx.onInvalidated` listeners you add: - -```ts -export default defineContentScript({ - main(ctx) { - ctx.onInvalidated(() => { - // Do something - }); - }, -) -``` - -The `ctx` also provides other convenient APIs for stopping your content script without manually calling `onInvalidated` to add a listener: - -1. Setting timers: - ```ts - ctx.setTimeout(() => { ... }, ...); - ctx.setInterval(() => { ... }, ...); - ctx.requestAnimationFrame(() => { ... }); - ``` -1. Adding DOM events: - ```ts - ctx.addEventListener(window, "mousemove", (event) => { ... }); - ``` -1. Implements [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) for canceling standard APIs: - ```ts - fetch('...', { - signal: ctx.signal, - }); - ``` - -Other WXT APIs require a `ctx` object so they can clean themselves up. For example, [`createIntegratedUi`](/guide/key-concepts/content-script-ui#integrated), [`createShadowRootUi`](/guide/key-concepts/content-script-ui#shadow-root), and [`createIframeUi`](/guide/key-concepts/content-script-ui#iframe) automatically unmount and stop a UI when the script is invalidated. - -:::warning -When working with content scripts, **you should always use the `ctx` object to stop any async or future work.** - -This prevents old content scripts from interfering with new content scripts, and prevents error messages from being logged to the console in production. -::: - -## Testing Permission Changes - -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. - -You can test if your permission changes will result in a disabled extension: - -- Chromium: Use [Google's Extension Update Testing tool](https://github.com/GoogleChromeLabs/extension-update-testing-tool) -- Firefox: See their [Test Permission Requests](https://extensionworkshop.com/documentation/develop/test-permission-requests/) page -- Safari: Everyone breaks something in production eventually... 🫡 Good luck soldier - -## Update Event - -You can setup a callback that runs after your extension updates like so: - -```ts -browser.runtime.onInstalled.addListener(({ reason }) => { - if (reason === 'update') { - // Do something - } -}); -``` - -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` -2. Use [Google's Extension Update Testing tool](https://github.com/GoogleChromeLabs/extension-update-testing-tool) diff --git a/docs/guide/go-further/reusable-modules.md b/docs/guide/go-further/reusable-modules.md deleted file mode 100644 index 50aaf8f0..00000000 --- a/docs/guide/go-further/reusable-modules.md +++ /dev/null @@ -1,186 +0,0 @@ ---- -outline: deep ---- - -# Reusable Modules - -## Overview - -WXT provides a "module" API that lets you modify the build process. This API lets you add entrypoints, inject runtime code, add vite plugins, and more! - -What's more, these modules can be shared on NPM and re-used between projects! - -## Adding a Module - -There are two ways to add a module to your project: - -1. **Local file**: Any file present in the `modules/` directory will be treated as a module and loaded at build-time by WXT. You can use `modules/*.ts` or `modules/*/index.ts`, similar to entrypoints. - - ```ts - // modules/example.ts - import { defineWxtModule } from 'wxt/modules'; - - export default defineWxtModule((wxt) => { - // ... - }); - ``` - -2. **NPM package**: Find WXT modules on NPM and include them in your project: - ```ts - // wxt.config.ts - export default defineConfig({ - // Add the module to your project - modules: ['@wxt-dev/auto-icons'], - }); - ``` - -## Writing Modules - -Modules contain a setup function that is executed at the beginning of the build process. - -:::code-group - -```ts [Function Definition] -import { defineWxtModule } from 'wxt/modules'; - -export default defineWxtModule((wxt) => { - // ... -}); -``` - -```ts [Object Definition] -import { defineWxtModule } from 'wxt/modules'; - -export default defineWxtModule({ - // Add metadata... - setup(wxt) { - // ... - }, -}); -``` - -::: - -### Module Options - -You can define custom options for your module by setting the `configKey`: - -```ts -// modules/analytics.ts -import { defineWxtModule } from 'wxt/modules'; - -export default defineWxtModule({ - configKey: 'analytics', - setup(wxt, options) { - console.log(options); // { clientId: "..." } - }, -}); - -// Define the option types -export interface AnalyticsModuleOptions { - clientId: string; -} - -// Use "module augmentation" to add types for the new key -declare module 'wxt' { - export interface InlineConfig { - analytics: AnalyticsModuleOptions; - } -} -``` - -Now, when the user provides options to the `analytics` key in their `wxt.config.ts`, those options are passed into the setup function as the second argument. - -```ts -export default defineConfig({ - analytics: { clientId: '...' }, -}); -``` - -### 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 with `wxt.hooks`. - -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 -export default defineWxtModule((wxt) => { - if (wxt.config.mode === 'development') { - // Use the "ready" hook to update wxt.config - wxt.hooks.hook('ready', (wxt) => { - wxt.config.outDir = wxt.config.outDir.replace('.output', '.output/dev'); - }); - } -}); -``` - -:::info Async Modules -Both the `setup` function and hook callbacks can be async. Don't forget to add `await`! -::: - -It's important to understand the basics of how hooks work. Make sure to read the [API reference](/api/reference/wxt/interfaces/WxtHooks.html) for the full list of hooks and what they should be used for. They are the key to modifying your extension. - -### Module Utils - -Additionally, WXT provides several helper functions that setup hooks behind the scenes to streamline common operations. - -For example, if you want to include an entrypoint from inside a module, you can use the `addEntrypoint` util: - -```ts -// modules/changelog.ts -import { defineWxtModule, addEntrypoint } from 'wxt/modules'; -import { resolve } from 'node:path'; - -export default defineWxtModule({ - name: 'changelog', - setup(wxt) { - addEntrypoint(wxt, { - type: 'unlisted-page', - name: 'changelog', - // Point to the "modules/changelog.html" file - inputPath: resolve(__dirname, 'changelog.html'), - outputDir: wxt.config.outDir, - options: {}, - }); - }, -}); -``` - -Refer to the [API reference](/api/reference/wxt/modules/#functions) for the full list of the utilities. - -## Plugins - -Whereas modules are executed at build-time, plugins are executed at runtime. As of now, the only way to add a plugin is with the `addWxtPlugin` helper inside a module. - -Here's a minimal example to execute something at runtime. - -:::code-group - -```ts [modules/example/index.ts] -import { defineWxtModule, addWxtPlugin } from 'wxt/modules'; -import { resolve } from 'node:path'; - -export default defineWxtModule((wxt) => { - addWxtPlugin(wxt, resolve(__dirname, 'plugin.ts')); -}); -``` - -```ts [modules/example/plugin.ts] -import { defineWxtPlugin } from 'wxt/sandbox'; - -export default defineWxtPlugin(() => { - console.log('Executing plugin!'); -}); -``` - -::: - -:::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, store the result's promise synchronously and await it later on. -::: - -## Publishing to NPM - -:::warning 🚧 Under construction -These docs will be coming soon! -::: diff --git a/docs/guide/go-further/testing.md b/docs/guide/go-further/testing.md deleted file mode 100644 index 8c5f2300..00000000 --- a/docs/guide/go-further/testing.md +++ /dev/null @@ -1,27 +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: - -- [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 - -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.mjs` -- **[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. diff --git a/docs/guide/go-further/vite.md b/docs/guide/go-further/vite.md deleted file mode 100644 index 98e67d10..00000000 --- a/docs/guide/go-further/vite.md +++ /dev/null @@ -1,39 +0,0 @@ -# Vite - -Under the hood, WXT uses Vite to bundle your web extension. - -## Basic Vite Configuration - -All of Vite's config can be customized by setting the `vite` configuration in your `wxt.config.ts` file. - -```ts -import { defineConfig } from 'wxt'; - -export default defineConfig({ - vite: () => ({ - // Same as `defineConfig({ ... })` inside vite.config.ts - }), -}); -``` - -## Using Plugins - -Plugins can be passed into the `vite` configuration in your `wxt.config.ts` file, just like any other option. - -```ts -import { defineConfig } from 'wxt'; - -export default defineConfig({ - vite: () => ({ - plugins: [ - // ... - ], - }), -}); -``` - -:::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)! -::: diff --git a/docs/guide/i18n/build-integrations.md b/docs/guide/i18n/build-integrations.md deleted file mode 100644 index 0dd9aba2..00000000 --- a/docs/guide/i18n/build-integrations.md +++ /dev/null @@ -1,82 +0,0 @@ -# Build Integrations - -To use the custom messages file format, you'll need to use `@wxt-dev/i18n/build` to transform the custom format to the one expected by browsers. - -Here's a list of build tools that already have an integration: - -[[toc]] - -:::info -If you want to contribute, please do! In particular, an `unplugin` integration would be awesome! -::: - -## WXT - -See [Installation with WXT](./installation#with-wxt). - -But TLDR, all you need is: - -```ts -// wxt.config.ts -export default defineConfig({ - modules: ['@wxt-dev/i18n/module'], -}); -``` - -Types are generated whenever you run `wxt prepare` or another build command: - -```sh -wxt prepare -wxt -wxt build -wxt zip -# etc -``` - -## Custom - -If you're not using WXT, you'll have to pre-process the localization files yourself. Here's a basic script to generate the `_locales/.../messages.json` and `wxt-i18n-structure.d.ts` files: - -```ts -// build-i18n.js -import { - parseMessagesFile, - generateChromeMessagesFile, - generateTypeFile, -} from '@wxt-dev/i18n/build'; - -// Read your localization files -const messages = { - en: await parseMessagesFile('path/locales/en.yml'), - de: await parseMessagesFile('path/locales/de.yml'), - // ... -}; - -// Generate JSON files for the browser -await generateChromeMessagesFile('dist/_locales/en/messages.json', messages.en); -await generateChromeMessagesFile('dist/_locales/de/messages.json', messages.de); -// ... - -// Generate a types file based on your default_locale -await generateTypeFile('wxt-i18n-structure.d.ts', messages.en); -``` - -Then run the script: - -```sh -node generate-i18n.js -``` - -If your build tool has a dev mode, you'll also want to rerun the script whenever you change a localization file. - -### Type Safety - -Once you've generated `wxt-i18n-structure.d.ts` (see the [Custom](#custom) section), you can use it to pass the generated type into `createI18n`: - -```ts -import type { WxtI18nStructure } from './wxt-i18n-structure'; - -export const i18n = createI18n(); -``` - -And just like that, you have type safety! diff --git a/docs/guide/i18n/editor-support.md b/docs/guide/i18n/editor-support.md deleted file mode 100644 index 704ab104..00000000 --- a/docs/guide/i18n/editor-support.md +++ /dev/null @@ -1,48 +0,0 @@ -# Editor Support - -For better DX, you can configure your editor with plugins and extensions. - -[[toc]] - -## VS Code - -Install the [I18n Ally Extension](https://marketplace.visualstudio.com/items?itemName=lokalise.i18n-ally) to: - -- Go to translation definition -- Inline previews of text -- Hover to see other translations - -You'll need to configure it the extension so it knows where your localization files are and what function represents getting a translation: - -`.vscode/i18n-ally-custom-framework.yml`: - -```yml -# An array of strings which contain Language Ids defined by VS Code -# You can check available language ids here: https://code.visualstudio.com/docs/languages/identifiers -languageIds: - - typescript - -# Look for t("...") -usageMatchRegex: - - "[^\\w\\d]t\\(['\"`]({key})['\"`]" - -# Disable other built-in i18n ally frameworks -monopoly: true -``` - -`.vscode/settings.json`: - -```json -{ - "i18n-ally.localesPaths": ["src/locales"], - "i18n-ally.keystyle": "nested" -} -``` - -## Zed - -As of time of writing, Aug 18, 2024, no extensions exist for Zed to add I18n support. - -## IntelliJ - -Unknown - Someone who uses IntelliJ will have to open a PR for this! diff --git a/docs/guide/i18n/installation.md b/docs/guide/i18n/installation.md deleted file mode 100644 index f1779ffd..00000000 --- a/docs/guide/i18n/installation.md +++ /dev/null @@ -1,81 +0,0 @@ -# Installation - -[[toc]] - -### With WXT - -1. Install `@wxt-dev/i18n` via your package manager: - - ```sh - pnpm i @wxt-dev/i18n - ``` - -2. Add the WXT module to your `wxt.config.ts` file and setup a default locale: - - ```ts - export default defineConfig({ - modules: ['@wxt-dev/i18n/module'], - manifest: { - default_locale: 'en', - }, - }); - ``` - -3. Create a localization file at `/locales/.yml` or move your existing localization files there. - - ```yml - # /locales/en.yml - helloWorld: Hello world! - ``` - - :::tip - `@wxt-dev/i18n` supports the standard messages format, so if you already have localization files at `/public/_locale//messages.json`, you don't need to convert them to YAML or refactor them - just move them to `/locales/.json` and they'll just work out of the box! - ::: - -4. To get a translation, use the auto-imported `i18n` object or import it manually: - - ```ts - import { i18n } from '#i18n'; - - i18n.t('helloWorld'); // "Hello world!" - ``` - -And you're done! Using WXT, you get type-safety out of the box. - -### Without WXT - -1. Install `@wxt-dev/i18n` via your package manager: - - ```sh - pnpm i @wxt-dev/i18n - ``` - -2. Create a messages file at `_locales//messages.json` or move your existing translations there: - - ```json - { - "helloWorld": { - "message": "Hello world!" - } - } - ``` - - :::info - For the best DX, you should to integrate `@wxt-dev/i18n` into your build process. This enables: - - 1. Plural forms - 2. Simple messages file format - 3. Type safety - - See [Build Integrations](./build-integrations) to set it up. - ::: - -3. Create the `i18n` object, export it, and use it wherever you want! - - ```ts - import { createI18n } from '@wxt-dev/i18n'; - - export const i18n = createI18n(); - - i18n.t('helloWorld'); // "Hello world!"; - ``` diff --git a/docs/guide/i18n/introduction.md b/docs/guide/i18n/introduction.md deleted file mode 100644 index 37404dda..00000000 --- a/docs/guide/i18n/introduction.md +++ /dev/null @@ -1,22 +0,0 @@ -# Introduction - -:::info -You don't have to use `wxt` to use this package - it will work in any bundler setup. See [Installation without WXT](./installation#without-wxt) for more details. -::: - -`@wxt-dev/i18n` is a simple, type-safe wrapper around the `browser.i18n` APIs. It provides several benefits over the standard API: - -1. Simple messages file format -2. Plural form support -3. Integrates with the [I18n Ally VS Code extension](./editor-support#vscode) - -It also provides several benefits over other non-web extension specific i18n packages: - -1. Does not bundle localization files into every entrypoint -2. Don't need to fetch the localization files asynchronously -3. Can localize extension name in manifest -4. Can access localized strings inside CSS files - -However, it does have one major downside: - -1. Like the `browser.i18n` API, to change the language, users must change the browser's language diff --git a/docs/guide/i18n/messages-file-format.md b/docs/guide/i18n/messages-file-format.md deleted file mode 100644 index f6e699d9..00000000 --- a/docs/guide/i18n/messages-file-format.md +++ /dev/null @@ -1,170 +0,0 @@ -# Messages File Format - -You can only use the file format discussed on this page if you have [integrated `@wxt-dev/i18n` into your build process](./build-integrations). If you have not integrated it into your build process, you must use JSON files in the `_locales` directory, like a normal web extension. - -[[toc]] - -## File Extensions - -You can define your messages in several different file types: - -- `.yml` -- `.yaml` -- `.json` -- `.jsonc` -- `.json5` -- `.toml` - -## Nested Keys - -You can have translations at the top level or nest them into groups: - -```yml -ok: OK -cancel: Cancel -welcome: - title: Welcome to XYZ -dialogs: - confirmation: - title: 'Are you sure?' -``` - -To access a nested key, use `.`: - -```ts -i18n.t('ok'); // "OK" -i18n.t('cancel'); // "Cancel" -i18n.t('welcome.title'); // "Welcome to XYZ" -i18n.t('dialogs.confirmation.title'); // "Are you sure?" -``` - -## Substitutions - -Because `@wxt-dev/i18n` is based on `browser.i18n`, you define substitutions the same way, with `$1`-`$9`: - -```yml -hello: Hello $1! -order: Thanks for ordering your $1 -``` - -### Escapting `$` - -To escape the dollar sign, put another `$` in front of it: - -```yml -dollars: $$$1 -``` - -```ts -i18n.t('dollars', ['1.00']); // "$1.00" -``` - -## Plural Forms - -:::warning -Plural support languages like Arabic, that have different forms for "few" or "many", is not supported right now. Feel free to open a PR if you are interested in this! -::: - -To get a different translation based on a count: - -```yml -items: - 1: 1 item - n: $1 items -``` - -Then you pass in the count as the second argument to `i18n.t`: - -```ts -i18n.t('items', 0); // "0 items" -i18n.t('items', 1); // "1 item" -i18n.t('items', 2); // "2 items" -``` - -To add a custom translation for 0 items: - -```yml -items: - 0: No items - 1: 1 item - n: $1 items -``` - -```ts -i18n.t('items', 0); // "No items" -i18n.t('items', 1); // "1 item" -i18n.t('items', 2); // "2 items" -``` - -If you need to pass a custom substitution for `$1` instead of the count, just add the substitution: - -```yml -items: - 0: No items - 1: $1 item - n: $1 items -``` - -```ts -i18n.t('items', 0, ['Zero']); // "No items" -i18n.t('items', 1, ['One']); // "One item" -i18n.t('items', 2, ['Multiple']); // "Multiple items" -``` - -## Verbose Keys - -`@wxt-dev/i18n` is compatible with the message format used by [`browser.i18n`](https://developer.chrome.com/docs/extensions/reference/api/i18n). - -:::info -This means if you're migrating to `@wxt-dev/i18n` and you're already using the verbose format, you don't have to change anything! -::: - -A key is treated as "verbose" when it is: - -1. At the top level (not nested) -2. Only contains the following properties: `message`, `description` and/or `placeholder` - -:::code-group - -```json [JSON] -{ - "appName": { - "message": "GitHub - Better Line Counts", - "description": "The app's name, should not be translated", - }, - "ok": "OK", - "deleteConfirmation": { - "title": "Delete XYZ?" - "message": "You cannot undo this action once taken." - } -} -``` - -```yml [YAML] -appName: - message: GitHub - Better Line Counts - description: The app's name, should not be translated -ok: OK -deleteConfirmation: - title: Delete XYZ? - message: You cannot undo this action once taken. -``` - -::: - -In this example, only `appName` is considered verbose. `deleteConfirmation` is not verbose because it contains the additional property `title`. - -```ts -i18n.t('appName'); // ✅ "GitHub - Better Line Counts" -i18n.t('appName.message'); // ❌ -i18n.t('ok'); // ✅ "OK" -i18n.t('deleteConfirmation'); // ❌ -i18n.t('deleteConfirmation.title'); // ✅ "Delete XYZ?" -i18n.t('deleteConfirmation.message'); // ✅ "You cannot undo this action once taken." -``` - -If this is confusing, don't worry! With type-safety, you'll get a type error if you do it wrong. If type-safety is disabled, you'll get a runtime warning in the devtools console. - -:::warning -Using the verbose format is not recommended. I have yet to see a translation service and software that supports this format out of the box. Stick with the simple format when you can. -::: diff --git a/docs/guide/installation.md b/docs/guide/installation.md new file mode 100644 index 00000000..1f59ad49 --- /dev/null +++ b/docs/guide/installation.md @@ -0,0 +1,123 @@ +# Installation + +Bootstrap a new project, start from scratch, or [migrate an existing project](/guide/resources/migrate). + +[[toc]] + +## Bootstrap Project + +Run the [`init` command](/api/cli/wxt-init), and follow the instructions. + +:::code-group + +```sh [PNPM] +pnpm dlx wxt@latest init +``` + +```sh [Bun] +bunx wxt@latest init +``` + +```sh [NPM] +npx wxt@latest init +``` + +```sh [Yarn] +# Use NPM initially, but select Yarn when prompted +npx wxt@latest init +``` + +::: + +:::info Starter Templates: +[Vanilla](https://github.com/wxt-dev/wxt/tree/main/templates/vanilla)
[Vue](https://github.com/wxt-dev/wxt/tree/main/templates/vue)
[React](https://github.com/wxt-dev/wxt/tree/main/templates/react)
[Svelte](https://github.com/wxt-dev/wxt/tree/main/templates/svelte)
[Solid](https://github.com/wxt-dev/wxt/tree/main/templates/solid) + +All templates use TypeScript by default. To use JavaScript, change the file extensions. +::: + +### Demo + +![wxt init demo](/assets/init-demo.gif) + +Once you've run the `dev` command, continue to [Next Steps](#next-steps)! + +## From Scratch + +1. Create a new project + :::code-group + ```sh [PNPM] + cd my-project + pnpm init + ``` + ```sh [Bun] + cd my-project + bun init + ``` + ```sh [NPM] + cd my-project + npm init + ``` + ```sh [Yarn] + cd my-project + yarn init + ``` + ::: +2. Install WXT: + :::code-group + ```sh [PNPM] + pnpm i -D wxt + ``` + ```sh [Bun] + bun i -D wxt + ``` + ```sh [NPM] + npm i -D wxt + ``` + ```sh [Yarn] + yarn add --dev wxt + ``` + ::: +3. Add an entrypoint, `my-project/entrypoints/background.ts`: + :::code-group + ```ts + export default defineBackground(() => { + console.log('Hello world!'); + }); + ``` + ::: +4. Add scripts to your `package.json`: + ```json + { + "scripts": { + "dev": "wxt", // [!code ++] + "dev:firefox": "wxt -b firefox", // [!code ++] + "build": "wxt build", // [!code ++] + "build:firefox": "wxt build -b firefox", // [!code ++] + "zip": "wxt zip", // [!code ++] + "zip:firefox": "wxt zip -b firefox", // [!code ++] + "postinstall": "wxt prepare" // [!code ++] + } + } + ``` +5. Run your extension in dev mode + :::code-group + ```sh [PNPM] + pnpm dev + ``` + ```sh [Bun] + bun run dev + ``` + ```sh [NPM] + npm run dev + ``` + ```sh [Yarn] + yarn dev + ``` + ::: + WXT will automatically open a browser window with your extension installed. + +## Next Steps + +- Keep reading on about WXT's [Project Structure](/guide/essentials/project-structure) and other essential concepts to learn +- Configure [automatic browser startup](/guide/essentials/config/browser-startup) during dev mode +- Explore [WXT's example library](/examples) to see how to use specific APIs or perform common tasks diff --git a/docs/guide/introduction.md b/docs/guide/introduction.md new file mode 100644 index 00000000..c373e7c5 --- /dev/null +++ b/docs/guide/introduction.md @@ -0,0 +1,26 @@ +# Welcome to WXT! + +WXT is a modern, open-source framework for building web extensions. Inspired by Nuxt, its goals are to: + +- Provide an awesome [DX](https://about.gitlab.com/topics/devops/what-is-developer-experience/) +- Provide first-class support for all major browsers + +Check out the [comparison](/guide/resources/compare) to see how WXT compares to other tools for building web extnesions. + +## Prerequisites + +These docs assume you have a basic knowledge of how Chrome extensions are structured and how you access the extension APIs. + +:::warning New to extension development? +If you have never written an extension before, follow Chrome's [Hello World tutorial](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world) to first **_create an extension without WXT_**, then come back here. +::: + +You should also be aware of [Chrome's extension docs](https://developer.chrome.com/docs/extensions) and [Mozilla's extension docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions). WXT does not change how you use the extension APIs, and you'll need to refer to these docs often when using specific APIs. + +
+ +--- + +
+ +Alright, got a basic understanding of how web extensions are structured? Do you know how to access the extension APIs? Then continue to the [Installation page](/guide/installation) to create your first WXT extension. diff --git a/docs/guide/key-concepts/auto-imports.md b/docs/guide/key-concepts/auto-imports.md deleted file mode 100644 index ac3b699d..00000000 --- a/docs/guide/key-concepts/auto-imports.md +++ /dev/null @@ -1,117 +0,0 @@ -# Auto-imports - -WXT uses the same tool as Nuxt for auto-imports, [`unimport`](https://github.com/unjs/unimport). - -## WXT Auto-imports - -Some WXT APIs can be used without importing them: - -- [`browser`](/api/reference/wxt/browser/variables/browser) from `wxt/browser`, a small wrapper around `webextension-polyfill` -- [`defineContentScript`](/api/reference/wxt/sandbox/functions/defineContentScript) from `wxt/sandbox` -- [`defineBackground`](/api/reference/wxt/sandbox/functions/defineBackground) from `wxt/sandbox` -- [`defineUnlistedScript`](/api/reference/wxt/sandbox/functions/defineUnlistedScript) from `wxt/sandbox` -- [`createIntegratedUi`](/api/reference/wxt/client/functions/createIntegratedUi) from `wxt/client` -- [`createShadowRootUi`](/api/reference/wxt/client/functions/createShadowRootUi) from `wxt/client` -- [`createIframeUi`](/api/reference/wxt/client/functions/createIframeUi) from `wxt/client` -- [`fakeBrowser`](/api/reference/wxt/testing/variables/fakeBrowser) from `wxt/testing` - -And more! - -## Project Auto-imports - -In addition WXT APIs, default and named exports from inside the following directories can be used without listing them in imports. - -- `/components/*` -- `/composables/*` -- `/hooks/*` -- `/utils/*` - -To add auto-imports from subdirectories, like `utils/api/some-file.ts`, re-export them from the base directory: - -```ts -// utils/index.ts -export * from './api/some-file.ts'; -``` - -Alternatively, you could add the directory to the list of auto-import directories in your config file. - -## TypeScript - -For TypeScript to work, you need to run the `wxt prepare` command. This will ensure types are generated for auto-imports. - -This should be added to your `postinstall` script so your editor has everything it needs to report type errors after installing dependencies: - -```json -// package.json -{ - "scripts": { - "postinstall": "wxt prepare" // [!code ++] - } -} -``` - -## Customization - -You can override the default auto-import behavior in your `wxt.config.ts` file. - -See [`unimport`'s documentation](https://github.com/unjs/unimport#configurations) for a complete list of options. - -```ts -import { defineConfig } from 'wxt'; - -export default defineConfig({ - imports: { - // Add auto-imports for vue functions like createApp, ref, computed, watch, toRaw, etc... - presets: ['vue'], - }, -}); -``` - -## Disabling Auto-imports - -To disable auto-imports, set `imports: false` - -```ts -export default defineConfig({ - imports: false, -}); -``` - -## ESLint - -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. - -```ts -// wxt.config.ts -export default defineConfig({ - imports: { - eslintrc: { - 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'], -}; -``` diff --git a/docs/guide/key-concepts/manifest.md b/docs/guide/key-concepts/manifest.md deleted file mode 100644 index 6ee21f6f..00000000 --- a/docs/guide/key-concepts/manifest.md +++ /dev/null @@ -1,249 +0,0 @@ -# Manifest - -## Overview - -Sometimes, you'll need to make manual changes to how the `manifest.json` is generated. You can do this by using the `manifest` configuration: - -```ts -// wxt.config.ts -export default defineConfig({ - manifest: { - // Put manual changes here - }, -}); -``` - -## Manifest Version Compatibility - -When defining options in the manifest, always define them for MV3 when possible. WXT will either convert them to their MV2 equivalents or remove them from the generated manifest if there is not MV2 equivalent. - -So for fields like `web_accessible_resources` or `content_security_policy`, you just need to list them in their MV3 forms. Other fields, like `side_panel`, which doesn't exist in MV2, will be removed automatically. - -Here's an example `wxt.config.ts` file: - -```ts -import { defineConfig } from 'wxt'; - -export default defineConfig({ - manifest: { - action: { - default_title: 'Some Title', - }, - web_accessible_resources: [ - { - matches: ['*://*.google.com/*'], - resources: ['icon/*.png'], - }, - ], - }, -}); -``` - -And here's the different `manifest.json` files generated: - -:::code-group - -```json [MV2] -{ - "manifest_version": 2, - // ... - "browser_action": { - "default_title": "Some Title" - }, - "web_accessible_resources": ["icon/*.png"] -} -``` - -```json [MV3] -{ - "manifest_version": 3, - // ... - "action": { - "default_title": "Some Title" - }, - "web_accessible_resources": [ - { - "matches": ["*://*.google.com/*"], - "resources": ["icon/*.png"] - } - ] -} -``` - -::: - -## Name - -If not provided via the `manifest` config, the [manifest's `name`](https://developer.chrome.com/docs/extensions/mv3/manifest/name/) defaults to your `package.json`'s `name` property. - -## Version - -The [manifest's `version` and `version_name`](https://developer.chrome.com/docs/extensions/mv3/manifest/version/) properties are based on the `version` field listed in your `package.json` or `wxt.config.ts`. - -- `version_name` is the exact string listed in your `package.json` or `wxt.config.ts` file -- `version` is the string cleaned up, with any invalid suffixes removed - -If a version is not found, a warning is logged and the version defaults to `"0.0.0"`. - -#### Example - -```json -// package.json -{ - "version": "1.3.0-alpha2" -} -``` - -```json -// .output/
/manifest.json -{ - "version": "1.3.0", - "version_name": "1.3.0-alpha2" -} -``` - -## `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/). - -``` -public/ -├─ icon-16.png -├─ icon-24.png -├─ icon-48.png -├─ icon-96.png -└─ icon-128.png -``` - -Icon files need to match the following regex to be automatically included in the manifest. Most design software can output icons in one of these formats - -<<< @/../packages/wxt/src/core/utils/manifest.ts#snippet - -If you prefer to use filenames in a different format, you can add the icons manually in your `wxt.config.ts` file: - -```ts -export default defineConfig({ - manifest: { - icons: { - 16: '/extension-icon-16.png', - 24: '/extension-icon-24.png', - 48: '/extension-icon-48.png', - 96: '/extension-icon-96.png', - 128: '/extension-icon-128.png', - }, - }, -}); -``` - -## Permissions - -[Permissions](https://developer.chrome.com/docs/extensions/reference/permissions/) must be listed in the manifest config. - -```ts -export default defineConfig({ - manifest: { - permissions: ['storage', 'tabs'], - }, -}); -``` - -## 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 ? [...] : [...], - }), -}); -``` - -::: - -## Default Locale - -See the dedicated [I18n docs](/guide/extension-apis/i18n) for setting up localization and a `default_locale`. - -## Actions - -In MV2, you had two options: [`browser_action`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action) and [`page_action`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/page_action). In MV3, they were merged into a single [`action`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/action) API. - -By default, whenever an action is generated, WXT falls back to `browser_action` when targetting MV2. - -### Action With Popup - -To generate a manifest where a UI appears after clicking the icon, just create a [popup entrypoint](/guide/directory-structure/entrypoints/popup). - -If you want to use a `page_action` for MV2, add the following `meta` tag to the HTML document's head: - -```html - -``` - -### Action Without Popup - -If you want to use the `activeTab` permission or the `browser.action.onClick` event, but don't want to show a popup UI: - -1. Delete the [popup entrypoint](/guide/directory-structure/entrypoints/popup) if it exists -2. Add the `action` key to your manifest: - ```ts - // wxt.config.ts - export default defineConfig({ - manifest: { - action: {}, - }, - }); - ``` - -Same as an action with a popup, WXT will fallback on using `browser_action` for MV2. To use a `page_action` instead, add that key as well: - -```ts -// wxt.config.ts -export default defineConfig({ - manifest: { - action: {}, - page_action: {}, - }, -}); -``` - -## Full Control - -The `manifest` option can also be set equal to a function, letting you use logical statements to determine what should be output. - -```ts -// wxt.config.ts -export default defineConfig({ - manifest: ({ manifestVersion, browser, mode, command }) => { - return { ... } - } -}) -``` - -Or, you can use the `build:manifestGenerated` hook to transform the manifest before it is written to the output directory. - -```ts -// wxt.config.ts -export default defineConfig({ - hooks: { - build: { - manifestGenerated(manifest) { - // Update the manifest variable by reference - manifest.name = 'Overriden name'; - }, - }, - }, -}); -``` diff --git a/docs/guide/key-concepts/multiple-browsers.md b/docs/guide/key-concepts/multiple-browsers.md deleted file mode 100644 index ee5a743d..00000000 --- a/docs/guide/key-concepts/multiple-browsers.md +++ /dev/null @@ -1,133 +0,0 @@ -# Multiple Browsers - -You can build an extension for any combination of browser and manifest version. Different browsers and manifest versions support different APIs and entrypoints, so be sure to check that your extension functions as expected for each target. - -Separate build targets are written to their own output directories: - -``` - -└─ .output - ├─ chrome-mv3 - ├─ firefox-mv2 - ├─ edge-mv3 - └─ ... -``` - -## Target Browser - -To build for a specific browser, pass the `-b --browser` flag from the CLI: - -```sh -wxt --browser firefox -wxt build --browser firefox -``` - -By default, it will build for `chrome`. When excluding the [manifest version flags](#target-manifest-version), it will default to the commonly accepted manifest version for that browser. - -| Browser | Default Manifest Version | -| ---------------- | :----------------------: | -| `chrome` | 3 | -| `firefox` | 2 | -| `safari` | 2 | -| `edge` | 3 | -| Any other string | 3 | - -:::tip -To configure which browser is opened when running dev mode via `wxt -b `, see the [`web-ext.config.ts` docs](/guide/directory-structure/web-ext-config). -::: - -## Target Manifest Version - -To build for a specific manifest version, pass either the `--mv2` flag or `--mv3` flag from the CLI. - -```sh -wxt --mv2 -wxt build --mv2 -``` - -When the `-b --browser` flag is not passed, it defaults to `chrome`. So here, we're targeting MV2 for Chrome. - -## Customizing Entrypoints - -There are several ways to customize entrypoint definitions per browser. - -First, you can use either the `include` or `exclude` option to include or exclude the entrypoint from specific browsers. Here are some examples - -:::code-group - -```ts [Background] -export default defineBackground({ - // Only include a background script when targeting chrome - include: ['chrome'], -}); -``` - -```ts [Content Script] -export default defineContentScript({ - // Do not add this content script to the manifest when targeting firefox - exclude: ['firefox'], -}); -``` - -```html [HTML page] - - - - - - - -``` - -::: - -Second, you can change individual options per-browser: - -:::code-group - -```ts [Background] -export default defineBackground({ - persistent: { - // Use a non-persistent background script for just safari - safari: false, - }, -}); -``` - -```ts [Content Script] -export default defineContentScript({ - matches: { - // Run the content script on different pages for each browser - chrome: ['*://*.google.com/*'], - firefox: ['*://*.duckduckgo.com/*'], - edge: ['*://*.bing.com/*'], - }, -}); -``` - -::: - -:::warning -Only `defineBackground` and `defineContentScript` support per-browser options right now. -::: - -## Runtime - -To determine the browser or manifest version at runtime, you can use any of the below variables: - -- `import.meta.env.BROWSER`: A string, the target browser, usually equal to the `--browser` flag -- `import.meta.env.MANIFEST_VERSION`: A number, either `2` or `3`, depending on the manifest version targeted -- `import.meta.env.CHROME`: A boolean equivalent to `import.meta.env.BROWSER === "chrome"` -- `import.meta.env.FIREFOX`: A boolean equivalent to `import.meta.env.BROWSER === "firefox"` -- `import.meta.env.EDGE`: A boolean equivalent to `import.meta.env.BROWSER === "edge"` -- `import.meta.env.SAFARI`: A boolean equivalent to `import.meta.env.BROWSER === "safari"` -- `import.meta.env.OPERA`: A boolean equivalent to `import.meta.env.BROWSER === "opera"` -- `import.meta.env.COMMAND`: A string, `"serve"` when running `wxt` for development or `"build"` in all other cases. - -:::info -These variables are constants defined at build time based on the build target. They do not actually detect which browser the code is running in. - -For example, if you build for `--browser chrome` and publish it on Edge, `import.meta.env.BROWSER` will be `"chrome"`, not `"edge"`. You have to build a separate ZIP for `--browser edge` before `import.meta.env.BROWSER` will be `"edge"`. - -If you need to know the actual browser your code is being ran on, you should use a [user agent parser](https://www.npmjs.com/package/ua-parser-js). -::: diff --git a/docs/guide/key-concepts/web-extension-polyfill.md b/docs/guide/key-concepts/web-extension-polyfill.md deleted file mode 100644 index 09ae0139..00000000 --- a/docs/guide/key-concepts/web-extension-polyfill.md +++ /dev/null @@ -1,108 +0,0 @@ -# Web Extension Polyfill - -## Overview - -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 access the extension APIs: - -```ts -import { browser } from 'wxt/browser'; - -console.log(browser.runtime.id); -``` - -If you use auto-imports (enabled by default), you don't need to import this variable, it will work just like the `chrome` global: - -```ts -console.log(browser.runtime.id); -``` - -## Handling Differences - -Web extensions behave **_VERY_** differently between browsers and manifest versions. You will have to handle these API differences yourself. - -:::info -MDN has great compatibility tables for tracking which browsers support which APIs: [Web Extension Browser Support for JavaScript APIs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs) -::: - -Lets go over a few approaches: - -1. **Feature detection**: If an API isn't available, it is `undefined`. So check if that's the case before using it. - - ```ts - if (browser.runtime.onStartup) { - browser.runtime.onStartup.addListener(...); - } - ``` - - If there's a similar API you can fallback on, you can do something like this: - - ```ts - (browser.action ?? browser.browserAction).setBadgeColor('red'); - ``` - -2. **Check the browser**: WXT provides environment variables about which browser is being targeted. - ```ts - if (!import.meta.env.SAFARI) { - // Safari doesn't implement `onStartup` correctly, so we need a custom solution - // ... - } else { - browser.runtime.onStartup.addListener(...) - } - ``` -3. **Check the manifest version**: WXT provides environment variables about which manifest version is being targeted. - ```ts - if (import.meta.env.MANIFEST_VERSION === 3) { - // MV3 only code... - } else { - // MV2 only code... - } - ``` - -### Environment Variables - -| Name | Type | Description | -| ---------------------------------- | --------- | ----------------------------------------------------- | -| `import.meta.env.BROWSER` | `string` | The target browser | -| `import.meta.env.MANIFEST_VERSION` | `2 │ 3` | The target manifest version | -| `import.meta.env.CHROME` | `boolean` | equivalent to `import.meta.env.BROWSER === "chrome"` | -| `import.meta.env.FIREFOX` | `boolean` | equivalent to `import.meta.env.BROWSER === "firefox"` | -| `import.meta.env.SAFARI` | `boolean` | equivalent to `import.meta.env.BROWSER === "safari"` | -| `import.meta.env.EDGE` | `boolean` | equivalent to `import.meta.env.BROWSER === "edge"` | -| `import.meta.env.OPERA` | `boolean` | equivalent to `import.meta.env.BROWSER === "opera"` | - -WXT uses Vite, so all of Vite's `import.meta.env` variables are also available: - - - -## Augmented Types - -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. `browser.i18n.getMessage` will only allow getting translations of messages defined in your `public/_locales//messages.json` file. - -## Missing Types - -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. - -```ts -// @ts-expect-error: desktopCapture is not typed -browser.desktopCapture.chooseDesktopMedia(...) -``` - -Note that when running this code in a different browser that doesn't support the `desktopCapture` API, `browser.desktopCapture` will evaluate to `undefined` and an error will be thrown. - -## Missing Permissions - -Just like with the `chrome` global, you need to request the required permissions to use each API. Otherwise, `browser.{apiName}` will be `undefined`. - -For example, if you try to use `browser.storage.local.getItem(...)` without requesting the `storage` permission, the extension will throw an error: - -``` -Cannot access property "local" of undefined. -``` - -You can request permissions using the [`wxt.config.ts` file](/guide/directory-structure/wxt-config#permissions). diff --git a/docs/guide/key-concepts/wxt-submit.md b/docs/guide/key-concepts/wxt-submit.md deleted file mode 100644 index 2c194929..00000000 --- a/docs/guide/key-concepts/wxt-submit.md +++ /dev/null @@ -1,9 +0,0 @@ -# `wxt submit` - -> Alias for [`publish-browser-extension`](https://www.npmjs.com/package/publish-browser-extension) - - - -
{{ data.submit }}
diff --git a/docs/guide/resources/compare.md b/docs/guide/resources/compare.md new file mode 100644 index 00000000..ef025f7f --- /dev/null +++ b/docs/guide/resources/compare.md @@ -0,0 +1,57 @@ +# Compare + +Lets compare the features of WXT vs [Plasmo](https://docs.plasmo.com/framework) (another framework) and [CRXJS](https://crxjs.dev/vite-plugin) (a bundler plugin). + +## Overview + +- ✅ - Full support +- 🟡 - Partial support +- ❌ - No support + +| Features | WXT | Plasmo | CRXJS | +| ------------------------------------------------------- | :--------------: | :-------------: | :--------------: | +| Supports all browsers | ✅ | ✅ | 🟡 10 | +| MV2 Support | ✅ | ✅ | 🟡 1 | +| MV3 Support | ✅ | ✅ | 🟡 1 | +| Create Extension ZIPs | ✅ | ✅ | ❌ | +| Create Firefox Sources ZIP | ✅ | ❌ | ❌ | +| First-class TypeScript support | ✅ | ✅ | ✅ | +| Entrypoint discovery | ✅ 2 | ✅ 2 | ❌ | +| Inline entrypoint config | ✅ | ✅ | ❌ 9 | +| Auto-imports | ✅ | ❌ | ❌ | +| Reusable module system | ✅ | ❌ | ❌ | +| Supports all frontend frameworks | ✅ | 🟡 3 | ✅ | +| Framework specific entrypoints (like `Popup.tsx`) | 🟡 4 | ✅ 5 | ❌ | +| Automated publishing | ✅ | ✅ | ❌ | +| Remote Code Bundling (Google Analytics) | ✅ | ✅ | ❌ | +| Unlisted HTML Pages | ✅ | ✅ | ✅ | +| Unlisted Scripts | ✅ | ❌ | ❌ | +| ESM Content Scripts | ❌ 12 | ❌ | ✅ | +| Dev Mode | | | +| `.env` Files | ✅ | ✅ | ✅ | +| Opens browser with extension installed | ✅ | ❌ | ❌ | +| HMR for UIs | ✅ | 🟡 6 | ✅ | +| Reload HTML Files on Change | ✅ | 🟡 7 | ✅ | +| Reload Content Scripts on Change | ✅ | 🟡 7 | ✅ | +| Reload Background on Change | 🟡 7 | 🟡 7 | 🟡 7 | +| Respects Content Script `run_at` | ✅ | ✅ | ❌ 8 | +| Built-in Wrappers | | | | +| Storage | ✅ | ✅ | ❌ 11 | +| Messaging | ❌ 11 | ✅ | ❌ 11 | +| Content Script UI | ✅ | ✅ | ❌ 11 | +| I18n | ✅ | ❌ | ❌ | + + + 1: Either MV2 or MV3, not both. +
2: File based. +
3: Only React, Vue, and Svelte. +
4: .html .ts .tsx. +
5: .html .ts .tsx. .vue .svelte. +
6: React only. +
7: Reloads entire extension. +
8: ESM-style loaders run asynchronously. +
9: Entrypoint options all configured in manifest.json. +
10: As of v2.0.0-beta.23, but v2 stable hasn't been released yet. +
11: There is no built-in wrapper around this API. However, you can still access the standard APIs via chrome/browser globals or use any 3rd party NPM package. +
12: WIP, moving very slowly. Follow
wxt-dev/wxt#357 for updates. + diff --git a/docs/guide/resources/faq.md b/docs/guide/resources/faq.md new file mode 100644 index 00000000..275bfb3b --- /dev/null +++ b/docs/guide/resources/faq.md @@ -0,0 +1,21 @@ +--- +outline: false +--- + +# FAQ + +Commonly asked questions about how to use WXT or why it behaves the way it does. + +[[toc]] + +--- + +### Why are content scripts not showing up in the manifest? + +During development, WXT registers content scripts dynamically so they can be reloaded individually when a file is saved without reloading your entire extension. + +To list the content scripts registered during development, open the service worker's console and run: + +```js +await chrome.scripting.getRegisteredContentScripts(); +``` diff --git a/docs/guide/go-further/how-wxt-works.md b/docs/guide/resources/how-wxt-works.md similarity index 100% rename from docs/guide/go-further/how-wxt-works.md rename to docs/guide/resources/how-wxt-works.md diff --git a/docs/get-started/migrate-to-wxt.md b/docs/guide/resources/migrate.md similarity index 67% rename from docs/get-started/migrate-to-wxt.md rename to docs/guide/resources/migrate.md index d51a3339..d7a14901 100644 --- a/docs/get-started/migrate-to-wxt.md +++ b/docs/guide/resources/migrate.md @@ -18,15 +18,18 @@ pnpm dlx wxt@latest init example-wxt --template vanilla In general, you'll need to:   Install `wxt`
+  [Extend `.wxt/tsconfig.json`](/guide/essentials/config/typescript.html#typescript-configuration) in your project's `tsconfig.json`
Update/create `package.json` scripts to use `wxt` (don't forget about `postinstall`)
Move entrypoints into `entrypoints/` directory
Move assets into either the `assets/` or `public/` directories
-  Move manifest.json content into `wxt.config.ts`
+  Move `manifest.json` content into `wxt.config.ts`
Convert custom import syntax to be compatible with Vite
-  Add a default export to JS entrypoints
+  Add a default export to JS entrypoints (`defineBackground`, `defineContentScript`, or `defineUnlistedScript`)
Use the `browser` global instead of `chrome`
-  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
-  Extension output by `wxt build` works the same way as before the migration
+  Compare final `manifest.json` files, making sure permissions and host permissions are unchanged
+:::warning +If your extension is already live on the Chrome Web Store, use [Google's update testing tool](https://github.com/GoogleChromeLabs/extension-update-testing-tool) to make sure no new permissions are being requested. +::: 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! @@ -34,6 +37,18 @@ Every project is different, so there's no one-solution-fits-all to migrating you Here's specific steps for other popular frameworks/build tools. +### Plasmo + +1. Install `wxt` +2. Move entrypoints into `entrypoints/` directory + - For JS entrypoints, merge the named exports used to configure your JS entrypoints into WXT's default export + - For HTML entrypoints, you cannot use JSX/Vue/Svelte files directly, you need to create an HTML file and manually create and mount your app. Refer to the [React](https://github.com/wxt-dev/wxt/tree/main/templates/react/entrypoints/popup), [Vue](https://github.com/wxt-dev/wxt/tree/main/templates/vue/entrypoints/popup), and [Svelte](https://github.com/wxt-dev/wxt/tree/main/templates/svelte/src/entrypoints/popup) templates as an example. +3. Move public `assets/*` into the `public/` directory +4. If you use CSUI, migrate to WXT's `createContentScriptUi` +5. Convert Plasmo's custom import resolutions to Vite's +6. If importing remote code via a URL, add a `url:` prefix so it works with WXT +7. Compare your output `manifest.json` files from before the migration to after the migration. They should have the same content. If not, tweak your entrypoints and config to get as close as possible. + ### `vite-plugin-web-extension` Since you're already using Vite, it's a simple refactor. @@ -45,21 +60,3 @@ Since you're already using Vite, it's a simple refactor. 5. Move the `manifest.json` into `wxt.config.ts` 6. Move any custom settings from `vite.config.ts` into `wxt.config.ts`'s 7. Compare `dist/manifest.json` to `.output/*/manifest.json`, they should have the same content as before. If not, tweak your entrypoints and config to get as close as possible. - -### `plasmo` - -1. Install `wxt` -2. Move entrypoints into `entrypoints/` directory, merging the named exports used to configure your JS entrypoints into WXT's default export -3. Move public `assets/*` into the `public/` directory -4. If you use CSUI, migrate to WXT's `createContentScriptUi` -5. Convert Plasmo's custom import resolutions to Vite's -6. If importing remote code via a URL, add a `url:` prefix so it works with WXT -7. Compare your output `manifest.json` files from before the migration to after the migration. They should have the same content. If not, tweak your entrypoints and config to get as close as possible. - - diff --git a/docs/guide/upgrade-guide/wxt.md b/docs/guide/resources/upgrading.md similarity index 89% rename from docs/guide/upgrade-guide/wxt.md rename to docs/guide/resources/upgrading.md index fae42874..4bf8f1c1 100644 --- a/docs/guide/upgrade-guide/wxt.md +++ b/docs/guide/resources/upgrading.md @@ -8,7 +8,9 @@ To upgrade WXT to the latest version... just install it! pnpm i wxt@latest ``` -If there was a major version change, follow the steps below to fix breaking changes. +Listed below are all the breaking changes you should address when upgrading to a new version of WXT. + +Currently, WXT is in pre-release. This means changes to the second digit, `v0.X`, are considered major and have breaking changes. Once v1 is released, only major version bumps will have breaking changes. ## v0.18.5 → v0.19.0 @@ -27,7 +29,7 @@ export default defineConfig({ }); ``` -> [Read the full docs](/guide/go-further/entrypoint-loaders#vite-node) for more information. +> [Read the full docs](/guide/essentials/config/entrypoint-loaders#vite-node) for more information. :::details This change enables: @@ -92,7 +94,28 @@ Vite also provides steps for migrating to ESM. Check them out for more details: ### New `modules/` Directory -WXT now recognizes the `modules/` directory as a folder containing [WXT modules](/guide/go-further/reusable-modules). +WXT now recognizes the `modules/` directory as a folder containing [WXT modules](/guide/essentials/wxt-modules). + +If you already have `/modules` or `/Modules` directory, `wxt prepare` and other commands will fail. + +You have two options: + +1. [Recommended] Keep your files where they are and tell WXT to look in a different folder: + ```ts + // wxt.config.ts + export default defineConfig({ + modulesDir: 'wxt-modules', // defaults to "modules" + }); + ``` +2. Rename your `modules` directory to something else. + +## v0.18.0 → v0.18.5 + +> When this version was released, it was not considered a breaking change... but it should have been. + +### New `modules/` Directory + +WXT now recognizes the `modules/` directory as a folder containing [WXT modules](/guide/essentials/wxt-modules). If you already have `/modules` or `/Modules` directory, `wxt prepare` and other commands will fail. diff --git a/docs/i18n.md b/docs/i18n.md new file mode 100644 index 00000000..1447f7d5 --- /dev/null +++ b/docs/i18n.md @@ -0,0 +1,5 @@ +--- +outline: deep +--- + + diff --git a/docs/index.md b/docs/index.md index d0c15a8e..b880af3e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,29 +13,29 @@ hero: actions: - theme: brand text: Get Started - link: /get-started/installation + link: /guide/installation - theme: alt text: Learn More - link: /get-started/introduction + link: /guide/introduction features: - icon: 🌐 title: Supported Browsers details: WXT will build extensions for Chrome, Firefox, Edge, Safari, and any Chromium based browser. - link: /guide/key-concepts/web-extension-polyfill + link: /guide/essentials/target-different-browsers linkText: Read docs - icon: ✅ title: MV2 and MV3 details: Build Manifest V2 or V3 extensions for any browser using the same codebase. - link: /guide/key-concepts/manifest + link: /guide/essentials/config/manifest linkText: Read docs - icon: ⚡ title: Fast Dev Mode - details: Lighting fast HMR for UI development and fast reloads for content/background scripts enables faster iterations. + details: Lightning fast HMR for UI development and fast reloads for content/background scripts enables faster iterations. - icon: 📂 title: File Based Entrypoints details: Manifest is generated based on files in the project with inline configuration. - link: /get-started/entrypoints + link: /guide/essentials/project-structure linkText: See project structure - icon: 🚔 title: TypeScript @@ -43,7 +43,7 @@ features: - icon: 🦾 title: Auto-imports details: Nuxt-like auto-imports to speed up development. - link: /guide/key-concepts/auto-imports + link: /guide/essentials/config/auto-imports linkText: Read docs - icon: 🤖 title: Automated Publishing @@ -51,17 +51,17 @@ features: - icon: 🎨 title: Frontend Framework Agnostic details: Works with any front-end framework with a Vite plugin. - link: /guide/key-concepts/frontend-frameworks + link: /guide/essentials/frontend-frameworks linkText: Add a framework - icon: 📦 - title: Modular Architecture + title: Module System details: Reuse build-time and runtime-code across multiple extensions. - link: /guide/go-further/reusable-modules + link: /guide/essentials/wxt-modules linkText: Read docs - icon: 🖍️ title: Bootstrap a New Project details: Get started quickly with several awesome project templates. - link: /get-started/installation#bootstrap-project + link: /guide/installation#bootstrap-project linkText: See templates - icon: 📏 title: Bundle Analysis @@ -69,13 +69,13 @@ features: - icon: ⬇️ title: Bundle Remote Code details: Downloads and bundles remote code imported from URLs. - link: /guide/go-further/remote-code + link: /guide/essentials/remote-code linkText: Read docs --- ## Put Developer Experience First -WXT's simplifies the chrome extension development process by providing tools for zipping and publishing, the best-in-class dev mode, an opinionated project structure, and more. Iterate faster, develop features not build scripts, and use everything the JS ecosystem has to offer. +WXT simplifies the chrome extension development process by providing tools for zipping and publishing, the best-in-class dev mode, an opinionated project structure, and more. Iterate faster, develop features not build scripts, and use everything the JS ecosystem has to offer.
diff --git a/docs/public/_redirects b/docs/public/_redirects index efd94762..ccc1a02a 100644 --- a/docs/public/_redirects +++ b/docs/public/_redirects @@ -6,6 +6,7 @@ # OLD /config.html /api/reference/wxt/interfaces/InlineConfig.html /api/config.html /api/reference/wxt/interfaces/InlineConfig.html +/api/config /api/reference/wxt/interfaces/InlineConfig.html /entrypoints /entrypoints/background.html /get-started/assets.html /guide/assets.html /get-started/build-targets.html /guide/multiple-browsers.html @@ -34,3 +35,71 @@ # 0.19.0 /guide/go-further/entrypoint-side-effects.html /guide/go-further/entrypoint-loaders.html + +# https://github.com/wxt-dev/wxt/issues/704 +# Generated via `pnpm docs:build && find docs/.vitepress/dist -type f -name "*.html"` + +/guide/i18n/build-integrations.html /i18n#build-integrations +/guide/i18n/introduction.html /i18n +/guide/i18n/messages-file-format.html /i18n#messages-file-format +/guide/i18n/editor-support.html /i18n#editor-support +/guide/i18n/installation.html /i18n#installation +/guide/key-concepts/content-script-ui.html /guide/essentials/content-scripts.html#ui +/guide/key-concepts/manifest.html /guide/essentials/config/manifest.html +/guide/key-concepts/wxt-submit.html /api/cli/wxt-submit.html +/guide/key-concepts/auto-imports.html /guide/essentials/config/auto-imports.html +/guide/key-concepts/web-extension-polyfill.html /guide/essentials/extension-apis.html +/guide/key-concepts/frontend-frameworks.html /guide/essentials/frontend-frameworks.html +/guide/key-concepts/multiple-browsers.html /guide/essentials/target-different-browsers.html +/guide/go-further/entrypoint-loaders.html /guide/essentials/config/entrypoint-loaders.html +/guide/go-further/es-modules.html /guide/essentials/es-modules.html +/guide/go-further/handling-updates.html /guide/essentials/testing-updates.html +/guide/go-further/custom-events.html /guide/essentials/content-scripts.html#dealing-with-spas +/guide/go-further/debugging.html /TODO +/guide/go-further/remote-code.html /guide/essentials/remote-code.html +/guide/go-further/vite.html /guide/essentials/config/vite.html +/guide/go-further/testing.html /guide/essentials/unit-testing.html +/guide/go-further/how-wxt-works.html /guide/resources/how-wxt-works.html +/guide/go-further/reusable-modules.html /guide/essentials/wxt-modules.html +/guide/extension-apis/messaging.html /guide/essentials/messaging.html +/guide/extension-apis/i18n.html /guide/essentials/i18n.html +/guide/extension-apis/storage.html /guide/essentials/storage.html +/guide/extension-apis/scripting.html /guide/essentials/scripting.html +/guide/extension-apis/others.html /guide/essentials/extension-apis.html +/guide/upgrade-guide/wxt.html /guide/resources/upgrading.html +/guide/directory-structure/components.html /guide/essentials/project-structure.html +/guide/directory-structure/hooks.html /guide/essentials/config/hooks.html +/guide/directory-structure/assets.html /guide/essentials/assets.html#assets-directory +/guide/directory-structure/package.html /guide/essentials/project-structure.html +/guide/directory-structure/env.html /guide/essentials/config/runtime.html +/guide/directory-structure/wxt-config.html /guide/essentials/project-structure.html +/guide/directory-structure/wxt.html /guide/essentials/project-structure.html +/guide/directory-structure/public/locales.html /guide/essentials/project-structure.html +/guide/directory-structure/public/index.html /guide/essentials/assets.html#public-directory +/guide/directory-structure/entrypoints/devtools.html /guide/essentials/entrypoints.html#devtools +/guide/directory-structure/entrypoints/sidepanel.html /guide/essentials/entrypoints.html#sidepanel +/guide/directory-structure/entrypoints/content-scripts.html /guide/essentials/entrypoints.html#content-scripts +/guide/directory-structure/entrypoints/newtab.html /guide/essentials/entrypoints.html#newtab +/guide/directory-structure/entrypoints/bookmarks.html /guide/essentials/entrypoints.html#bookmarks +/guide/directory-structure/entrypoints/unlisted-pages.html /guide/essentials/entrypoints.html#unlisted-pages +/guide/directory-structure/entrypoints/unlisted-scripts.html /guide/essentials/entrypoints.html#unlisted-scripts +/guide/directory-structure/entrypoints/options.html /guide/essentials/entrypoints.html#options +/guide/directory-structure/entrypoints/background.html /guide/essentials/entrypoints.html#background +/guide/directory-structure/entrypoints/popup.html /guide/essentials/entrypoints.html#popup +/guide/directory-structure/entrypoints/history.html /guide/essentials/entrypoints.html#history +/guide/directory-structure/entrypoints/sandbox.html /guide/essentials/entrypoints.html#sandbox +/guide/directory-structure/entrypoints/css.html /guide/essentials/entrypoints.html#unlisted-css +/guide/directory-structure/web-ext-config.html /guide/essentials/config/browser-startup.html +/guide/directory-structure/tsconfig.html /guide/essentials/config/typescript.html +/guide/directory-structure/utils.html /guide/essentials/project-structure.html +/guide/directory-structure/app-config.html /guide/essentials/config/runtime.html +/guide/directory-structure/composables.html /guide/essentials/project-structure.html +/guide/directory-structure/output.html /guide/essentials/project-structure.html +/get-started/assets.html /guide/essentials/assets.html +/get-started/introduction.html /guide/introduction.html +/get-started/configuration.html /guide/essentials/config/manifest.html +/get-started/publishing.html /guide/essentials/publishing.html +/get-started/migrate-to-wxt.html /guide/resources/migrate.html +/get-started/compare.html /guide/resources/compare.html +/get-started/entrypoints.html /guide/essentials/entrypoints.html +/get-started/installation.html /guide/installation.html diff --git a/docs/guide/extension-apis/storage.md b/docs/storage.md similarity index 96% rename from docs/guide/extension-apis/storage.md rename to docs/storage.md index 9d593074..6fb876d3 100644 --- a/docs/guide/extension-apis/storage.md +++ b/docs/storage.md @@ -2,7 +2,9 @@ outline: deep --- -# Storage API +# WXT Storage + +[Changelog](https://github.com/wxt-dev/wxt/blob/main/packages/wxt/CHANGELOG.md) WXT provides a simplified API to replace the `browser.storage.*` APIs. Use the `storage` auto-import from `wxt/storage` or import it manually to get started: @@ -10,22 +12,17 @@ WXT provides a simplified API to replace the `browser.storage.*` APIs. Use the ` import { storage } from 'wxt/storage'; ``` -:::warning -To use the `wxt/storage` API, the `"storage"` permission must be added to the manifest: - -```ts -// wxt.config.ts -export default defineConfig({ - manifest: { - permissions: ['storage'], - }, -}); -``` - -More info on permissions [here](/guide/key-concepts/manifest#permissions). -::: - -[[toc]] +> [!IMPORTANT] +> To use the `wxt/storage` API, the `"storage"` permission must be added to the manifest: +> +> ```ts +> // wxt.config.ts +> export default defineConfig({ +> manifest: { +> permissions: ['storage'], +> }, +> }); +> ``` ## Basic Usage diff --git a/packages/auto-icons/README.md b/packages/auto-icons/README.md index 0cef2993..3ee34773 100644 --- a/packages/auto-icons/README.md +++ b/packages/auto-icons/README.md @@ -1,5 +1,7 @@ # WXT Auto Icons +[Changelog](https://github.com/wxt-dev/wxt/blob/main/packages/auto-icons/CHANGELOG.md) + ## Features - Generate extension icons with the correct sizes diff --git a/packages/i18n/README.md b/packages/i18n/README.md index ea50ac14..d1fc05dc 100644 --- a/packages/i18n/README.md +++ b/packages/i18n/README.md @@ -1,3 +1,368 @@ -# WXT I18n +# `@wxt-dev/i18n` -[Read the docs](https://wxt.dev/guide/i18n/installation) to get started. +[Changelog](https://github.com/wxt-dev/wxt/blob/main/packages/i18n/CHANGELOG.md) + +`@wxt-dev/i18n` is a simple, type-safe wrapper around the `browser.i18n` APIs. It provides several benefits over the standard API: + +1. Simple messages file format +2. Plural form support +3. Integrates with the [I18n Ally VS Code extension](#vscode) + +It also provides several benefits over other non-web extension specific i18n packages: + +1. Does not bundle localization files into every entrypoint +2. Don't need to fetch the localization files asynchronously +3. Can localize text in manifest and CSS files + +However, it does have one major downside: + +1. Like the `browser.i18n` API, to change the language, users must change the browser's language + +> [!IMPORTANT] +> You don't have to use `wxt` to use this package - it will work in any bundler setup. See [Installation without WXT](#without-wxt) for more details. + +## Installation + +### With WXT + +1. Install `@wxt-dev/i18n` via your package manager: + + ```sh + pnpm i @wxt-dev/i18n + ``` + +2. Add the WXT module to your `wxt.config.ts` file and setup a default locale: + + ```ts + export default defineConfig({ + modules: ['@wxt-dev/i18n/module'], + manifest: { + default_locale: 'en', + }, + }); + ``` + +3. Create a localization file at `/locales/.yml` or move your existing localization files there. + + ```yml + # /locales/en.yml + helloWorld: Hello world! + ``` + + > `@wxt-dev/i18n` supports the standard messages format, so if you already have localization files at `/public/_locale//messages.json`, you don't need to convert them to YAML or refactor them - just move them to `/locales/.json` and they'll just work out of the box! + +4. To get a translation, use the auto-imported `i18n` object or import it manually: + + ```ts + import { i18n } from '#i18n'; + + i18n.t('helloWorld'); // "Hello world!" + ``` + +And you're done! Using WXT, you get type-safety out of the box. + +### Without WXT + +1. Install `@wxt-dev/i18n` via your package manager: + + ```sh + pnpm i @wxt-dev/i18n + ``` + +2. Create a messages file at `_locales//messages.json` or move your existing translations there: + + ```json + { + "helloWorld": { + "message": "Hello world!" + } + } + ``` + + > [!NOTE] + > For the best DX, you should to integrate `@wxt-dev/i18n` into your build process. This enables: + + > 1. Plural forms + > 2. Simple messages file format + > 3. Type safety + > + > See [Build Integrations](#build-integrations) to set it up. + +3. Create the `i18n` object, export it, and use it wherever you want! + + ```ts + import { createI18n } from '@wxt-dev/i18n'; + + export const i18n = createI18n(); + + i18n.t('helloWorld'); // "Hello world!"; + ``` + +## Messages File Format + +> [!DANGER] +> You can only use the file format discussed on this page if you have [integrated `@wxt-dev/i18n` into your build process](#build-integrations). If you have not integrated it into your build process, you must use JSON files in the `_locales` directory, like a normal web extension. + +### File Extensions + +You can define your messages in several different file types: + +- `.yml` +- `.yaml` +- `.json` +- `.jsonc` +- `.json5` +- `.toml` + +### Nested Keys + +You can have translations at the top level or nest them into groups: + +```yml +ok: OK +cancel: Cancel +welcome: + title: Welcome to XYZ +dialogs: + confirmation: + title: 'Are you sure?' +``` + +To access a nested key, use `.`: + +```ts +i18n.t('ok'); // "OK" +i18n.t('cancel'); // "Cancel" +i18n.t('welcome.title'); // "Welcome to XYZ" +i18n.t('dialogs.confirmation.title'); // "Are you sure?" +``` + +### Substitutions + +Because `@wxt-dev/i18n` is based on `browser.i18n`, you define substitutions the same way, with `$1`-`$9`: + +```yml +hello: Hello $1! +order: Thanks for ordering your $1 +``` + +#### Escapting `$` + +To escape the dollar sign, put another `$` in front of it: + +```yml +dollars: $$$1 +``` + +```ts +i18n.t('dollars', ['1.00']); // "$1.00" +``` + +### Plural Forms + +> [!WARNING] +> Plural support languages like Arabic, that have different forms for "few" or "many", is not supported right now. Feel free to open a PR if you are interested in this! + +To get a different translation based on a count: + +```yml +items: + 1: 1 item + n: $1 items +``` + +Then you pass in the count as the second argument to `i18n.t`: + +```ts +i18n.t('items', 0); // "0 items" +i18n.t('items', 1); // "1 item" +i18n.t('items', 2); // "2 items" +``` + +To add a custom translation for 0 items: + +```yml +items: + 0: No items + 1: 1 item + n: $1 items +``` + +```ts +i18n.t('items', 0); // "No items" +i18n.t('items', 1); // "1 item" +i18n.t('items', 2); // "2 items" +``` + +If you need to pass a custom substitution for `$1` instead of the count, just add the substitution: + +```yml +items: + 0: No items + 1: $1 item + n: $1 items +``` + +```ts +i18n.t('items', 0, ['Zero']); // "No items" +i18n.t('items', 1, ['One']); // "One item" +i18n.t('items', 2, ['Multiple']); // "Multiple items" +``` + +### Verbose Keys + +`@wxt-dev/i18n` is compatible with the message format used by [`browser.i18n`](https://developer.chrome.com/docs/extensions/reference/api/i18n). + +> [!IMPORTANT] +> This means if you're migrating to `@wxt-dev/i18n` and you're already using the verbose format, you don't have to change anything! + +A key is treated as "verbose" when it is: + +1. At the top level (not nested) +2. Only contains the following properties: `message`, `description` and/or `placeholder` + +```json +{ + "appName": { + "message": "GitHub - Better Line Counts", + "description": "The app's name, should not be translated", + }, + "ok": "OK", + "deleteConfirmation": { + "title": "Delete XYZ?" + "message": "You cannot undo this action once taken." + } +} +``` + +In this example, only `appName` is considered verbose. `deleteConfirmation` is not verbose because it contains the additional property `title`. + +```ts +i18n.t('appName'); // ✅ "GitHub - Better Line Counts" +i18n.t('appName.message'); // ❌ +i18n.t('ok'); // ✅ "OK" +i18n.t('deleteConfirmation'); // ❌ +i18n.t('deleteConfirmation.title'); // ✅ "Delete XYZ?" +i18n.t('deleteConfirmation.message'); // ✅ "You cannot undo this action once taken." +``` + +If this is confusing, don't worry! With type-safety, you'll get a type error if you do it wrong. If type-safety is disabled, you'll get a runtime warning in the devtools console. + +> [!WARNING] +> Using the verbose format is not recommended. I have yet to see a translation service and software that supports this format out of the box. Stick with the simple format when you can. + +## Build Integrations + +To use the custom messages file format, you'll need to use `@wxt-dev/i18n/build` to transform the custom format to the one expected by browsers. + +### WXT + +See [Installation with WXT](#with-wxt). + +But TLDR, all you need is: + +```ts +// wxt.config.ts +export default defineConfig({ + modules: ['@wxt-dev/i18n/module'], +}); +``` + +Types are generated whenever you run `wxt prepare` or another build command. + +### Custom + +If you're not using WXT, you'll have to pre-process the localization files yourself. Here's a basic script to generate the `_locales/.../messages.json` and `wxt-i18n-structure.d.ts` files: + +```ts +// build-i18n.js +import { + parseMessagesFile, + generateChromeMessagesFile, + generateTypeFile, +} from '@wxt-dev/i18n/build'; + +// Read your localization files +const messages = { + en: await parseMessagesFile('path/locales/en.yml'), + de: await parseMessagesFile('path/locales/de.yml'), + // ... +}; + +// Generate JSON files for the browser +await generateChromeMessagesFile('dist/_locales/en/messages.json', messages.en); +await generateChromeMessagesFile('dist/_locales/de/messages.json', messages.de); +// ... + +// Generate a types file based on your default_locale +await generateTypeFile('wxt-i18n-structure.d.ts', messages.en); +``` + +Then run the script: + +```sh +node generate-i18n.js +``` + +If your build tool has a dev mode, you'll also want to rerun the script whenever you change a localization file. + +#### Type Safety + +Once you've generated `wxt-i18n-structure.d.ts` (see the [Custom](#custom) section), you can use it to pass the generated type into `createI18n`: + +```ts +import type { WxtI18nStructure } from './wxt-i18n-structure'; + +export const i18n = createI18n(); +``` + +And just like that, you have type safety! + +## Editor Support + +For better DX, you can configure your editor with plugins and extensions. + +### VS Code + +The [I18n Ally Extension](https://marketplace.visualstudio.com/items?itemName=lokalise.i18n-ally) adds several features to VS Code: + +- Go to translation definition +- Inline previews of text +- Hover to see other translations + +You'll need to configure it the extension so it knows where your localization files are and what function represents getting a translation: + +`.vscode/i18n-ally-custom-framework.yml`: + +```yml +# An array of strings which contain Language Ids defined by VS Code +# You can check available language ids here: https://code.visualstudio.com/docs/languages/identifiers +languageIds: + - typescript + +# Look for t("...") +usageMatchRegex: + - "[^\\w\\d]t\\(['\"`]({key})['\"`]" + +# Disable other built-in i18n ally frameworks +monopoly: true +``` + +`.vscode/settings.json`: + +```json +{ + "i18n-ally.localesPaths": ["src/locales"], + "i18n-ally.keystyle": "nested" +} +``` + +### Zed + +As of time of writing, Aug 18, 2024, no extensions exist for Zed to add I18n support. + +### Jetbrains IDEs + +Install the [I18n Ally plugin](https://plugins.jetbrains.com/plugin/17212-i18n-ally). The docs are limited around their Jetbrains support, but you'll probably need to configure the plugin similar to [VS Code](#vs-code)... Not sure where the files go though. + +Please open a PR if you figure it out! diff --git a/packages/wxt/README.md b/packages/wxt/README.md index f629dbd0..530b187b 100644 --- a/packages/wxt/README.md +++ b/packages/wxt/README.md @@ -71,7 +71,7 @@ Or see the [installation guide](https://wxt.dev/guide/installation.html) to get - 🦾 Auto-imports - 🤖 Automated publishing - 🎨 Frontend framework agnostic: works with Vue, React, Svelte, etc -- 📦 Modular architecture with [WXT modules](https://wxt.dev/guide/go-further/reusable-modules.html#overview) +- 📦 [Module system](https://wxt.dev/guide/essentials/wxt-modules.html#overview) for reusing code between extensions - 🖍️ Quickly bootstrap a new project - 📏 Bundle analysis - ⬇️ Download and bundle remote URL imports diff --git a/packages/wxt/src/browser/chrome.ts b/packages/wxt/src/browser/chrome.ts index cb9a4430..d1dad85d 100644 --- a/packages/wxt/src/browser/chrome.ts +++ b/packages/wxt/src/browser/chrome.ts @@ -13,9 +13,11 @@ export type WxtBrowser = Omit & { i18n: WxtI18n & Omit<(typeof chrome)['i18n'], 'getMessage'>; }; +// #region snippet export const browser: WxtBrowser = // @ts-expect-error globalThis.browser?.runtime?.id == null ? globalThis.chrome : // @ts-expect-error globalThis.browser; +// #endregion snippet diff --git a/packages/wxt/src/client/content-scripts/ui/index.ts b/packages/wxt/src/client/content-scripts/ui/index.ts index c9ba6fb4..6c7a614a 100644 --- a/packages/wxt/src/client/content-scripts/ui/index.ts +++ b/packages/wxt/src/client/content-scripts/ui/index.ts @@ -17,7 +17,7 @@ export * from './types'; /** * Create a content script UI without any isolation. * - * @see https://wxt.dev/guide/key-concepts/content-script-ui.html#integrated + * @see https://wxt.dev/guide/essentials/content-scripts.html#integrated */ export function createIntegratedUi( ctx: ContentScriptContext, @@ -53,7 +53,7 @@ export function createIntegratedUi( /** * Create a content script UI using an iframe. * - * @see https://wxt.dev/guide/key-concepts/content-script-ui.html#iframe + * @see https://wxt.dev/guide/essentials/content-scripts.html#iframe */ export function createIframeUi( ctx: ContentScriptContext, @@ -96,7 +96,7 @@ export function createIframeUi( * * > This function is async because it has to load the CSS via a network call. * - * @see https://wxt.dev/guide/key-concepts/content-script-ui.html#shadowroot + * @see https://wxt.dev/guide/essentials/content-scripts.html#shadowroot */ export async function createShadowRootUi( ctx: ContentScriptContext, diff --git a/packages/wxt/src/core/builders/vite/index.ts b/packages/wxt/src/core/builders/vite/index.ts index 9af93a7a..dfe7fc9b 100644 --- a/packages/wxt/src/core/builders/vite/index.ts +++ b/packages/wxt/src/core/builders/vite/index.ts @@ -111,7 +111,7 @@ export async function createViteBuilder( plugins, esbuild: { // Add a footer with the returned value so it can return values to `scripting.executeScript` - // Footer is added apart of esbuild to make sure it's not minified. It + // Footer is added a part of esbuild to make sure it's not minified. It // get's removed if added to `build.rollupOptions.output.footer` // See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/executeScript#return_value footer: iifeReturnValueName + ';', diff --git a/packages/wxt/src/core/generate-wxt-dir.ts b/packages/wxt/src/core/generate-wxt-dir.ts index ef39c8a8..cf9980c7 100644 --- a/packages/wxt/src/core/generate-wxt-dir.ts +++ b/packages/wxt/src/core/generate-wxt-dir.ts @@ -22,7 +22,7 @@ export async function generateWxtDir(entrypoints: Entrypoint[]): Promise { // Add references to modules installed from NPM to the TS project so their // type augmentation can update InlineConfig correctly. Local modules defined - // in /modules are already apart of the project, so we don't need to + // in /modules are already a part of the project, so we don't need to // add them. wxt.config.userModules.forEach((module) => { if (module.type === 'node_module') entries.push({ module: module.id }); diff --git a/packages/wxt/src/virtual/README.md b/packages/wxt/src/virtual/README.md index b06cebed..248c7042 100644 --- a/packages/wxt/src/virtual/README.md +++ b/packages/wxt/src/virtual/README.md @@ -2,7 +2,7 @@ This folder contains scripts that are either loaded as entrypoints to JS files or included in HTML files, just like a project using WXT might load their own scripts. -While they are bundled and shipped inside WXT, Vite considers them apart of your project's source code, not WXT's. This means they cannot import 3rd party modules directly, otherwise `pnpm i --shamefully-hoist=false` and Yarn PnP will fail. +While they are bundled and shipped inside WXT, Vite considers them a part of your project's source code, not WXT's. This means they cannot import 3rd party modules directly, otherwise `pnpm i --shamefully-hoist=false` and Yarn PnP will fail. For this reason, the virtual entrypoints get their own TS project to isolate them from the rest of the project. They can only import from `wxt/*` or utils that don't have any imports from node_modules, like the logger.
Input PatternFilename Output Path
+ entrypoints/{{ pattern[0] }} @@ -31,7 +31,7 @@ const props = defineProps<{ /> + /{{ pattern[1] }}